Como posso me recuperar de um mestre git push -f origin errado?


Respostas:


53

Git geralmente não joga nada fora, mas se recuperar disso ainda pode ser complicado.

Se você tiver a fonte correta, basta colocá-la no controle remoto com a --forceopção. O Git não terá excluído nenhum branch a menos que você mande. Se você realmente perdeu commits, dê uma olhada neste guia útil para recuperar commits . Se você conhece o SHA-1 dos commits que deseja, provavelmente está bem.

Melhor coisa a fazer: faça backup de tudo e veja o que ainda está em seu repositório local. Faça o mesmo no controle remoto, se possível. Use git fsckpara ver se consegue recuperar coisas e acima de tudo NÃO executegit gc .

Acima de tudo, nunca use a --forceopção a menos que seja realmente sincero.


64
Provavelmente, você pode apenas olhar os reflogs para determinar onde os ramos remotos estavam originalmente. Por exemplo git reflog show remotes/origin/master,. Você deve ser capaz de ver seu empurrão lá; o commit na linha anterior está onde estava antes de você estragar tudo. Você pode então apenas empurrar essa revisão (com --force) para a origem e voltar para onde estava!
Cascabel de

@David: Oh. Você não mencionou em sua pergunta que não tinha o repo. (É claro que isso é algo que você nunca vai querer fazer.) Se você tiver acesso ao sistema de arquivos para o qual enviou, você ainda pode fazer tudo isso lá.
Cascabel de

1
@David: Caramba. É sempre bom ter seu diretório atual como parte de seu prompt para evitar esse tipo de coisa.
Cascabel de

1
@Jefromi Acho que o que você disse aí é a resposta real: Mesmo com uma versão antiga (sem git fetchedição há muito tempo) você pode exibir o reflog do lado do GitHub e se recuperar!
nh2

1
Onde está essa resposta de @Jefromi? Não vejo esse usuário mencionado nesta página fora deste tópico de comentários.
Don McCurdy de

47

Se você conhece o hash do commit, é fácil, apenas recrie seu branch.

5794458...b459f069 master -> master (forced update)

Exclua o branch remoto:

git push origin :master

em seguida, recrie seu branch com os seguintes comandos:

git checkout 5794458
git branch master
git push origin master

28

A solução já foi mencionada aqui

# work on local master
git checkout master

# reset to the previous state of origin/master, as recorded by reflog
git reset --hard origin/master@{1}

# at this point verify that this is indeed the desired commit.
# (if necessary, use git reflog to find the right one, and
# git reset --hard to that one)

# finally, push the master branch (and only the master branch) to the server
git push -f origin master

Obrigado, isso funcionou para mim. Não tive acesso para excluir o mestre, então o comentário aprovado falhou.
Andi de

Sim, e git reflog show remotes/origin/masterse o git reflog for necessário (conforme mencionado por @Cascabel acima)
Josiah Yoder

2
Esta é a resposta correta, obrigado por vincular a resposta correta.
Noitidart

6

Se você não estiver no repositório local de onde o push forçado veio, no nível de origem / mestre não há como recuperar. Mas se você tiver sorte o suficiente para usar GitHub ou GitHub for Enterprise , você pode dar uma olhada na API REST e recuperar o commit perdido como patch, exemplo:

  1. Liste os eventos e encontre o formato longo do commit sha1

https://api.github.com/repos/apache/logging-log4j2/events

  1. Baixe o commit perdido e recupere o patch relacionado no caminho json .files [] / patch

https://api.github.com/repos/apache/logging-log4j2/commits/889232e28f3863d2a17392c06c1dd8cac68485de

  1. Aplique localmente e empurre novamente

git apply patch.patch && git commit -m "commit restaurado" && git push origin master


4

Outra maneira de recuperar o commit perdido ou mesmo descobrir quais commits foram perdidos, se o push anterior não veio de seu repositório local, é olhar para sua máquina de CI.

Se você tem um trabalho que testa o branch master após cada commit (ou série de commits consecutivos), o que você deveria ter, você pode dar uma olhada no que ele testou por último. Esse é o commit que você precisa restaurar.

A máquina de CI pode até mesmo manter um clone local do repo, a partir do qual você poderá realizar essa recuperação.

Fonte: provavelmente entrega contínua: lançamentos de software confiáveis ​​por meio de construção, teste e automação de implantação (Addison-Wesley Signature Series (Fowler))


3

Sim, você pode recuperar commits depois git push -f your_branch

Texto do Doc :

Remova as entradas mais antigas do que o tempo especificado. Se essa opção não for especificada, o tempo de expiração será obtido da definição de configuração gc.reflogExpire, que, por sua vez, é padronizada para 90 dias. --expire = todas as entradas de ameixas independente de sua idade; --expire = nunca desativa a remoção de entradas alcançáveis ​​(mas veja --expire-unreachable).

Então você pode fazer:

1- git reflog

insira a descrição da imagem aqui

2- você escolhe Head_Number com o qual deseja recuperar git reset –hard HEAD@{HEAD-NUMBER}

insira a descrição da imagem aqui

3- você pode ver todos os commits neste cabeçalho por git cherry -v branch_name

4- no final você deve forçar o push git push -f branch_name

OU

1- obtenha o número de SHA de seu cliente GIT (interface)

git reset --hard commit_SHA

2- forçar empurrar

git push -f your_branch

Espero que isto ajude


2

Eu fiz a mesma coisa ao desfazer um último push para apenas um arquivo. Acabou voltando ao estado original do repositório. Eu estava usando comandos git do Linus porque tinha a cópia local no Linux. Felizmente, essa cópia ainda estava intacta.

Tudo o que fiz foi (depois de fazer freneticamente mais algumas cópias do repositório local):

git add .
git status

(dizia que origin / master estava à frente de 68 commits, tudo bem ... esses foram todos os commits que eu deletei)

git remote set-url origin <GIT_SSH_URL>
git push

E tudo foi restaurado do jeito que estava antes de eu fazer um empurrão forte. A coisa mais importante a lembrar é nunca fazer uma verificação do git. depois de ter empurrado com força. Mas a prática recomendada é desabilitar a opção push. Eu nunca vou usá-lo novamente. Aprendeu minha lição !!


0

Aqui você pode ler as decisões https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it

O segundo me ajudou. Errei esses comandos

1) (some-branch) git pull -> correct command was git pull origin some-branch

2) (some-branch) git push -f origin some-branch

Após esses comandos, perdi três commits. Para recuperá-los, olhei para o terminal onde fiz 'git pull' incorretamente e vi uma saída como

60223bf ... 0b258eb algum-ramo -> origem / algum-ramo

O segundo hash 0b258eb era exatamente o que eu precisava. Então, peguei esse hash e produzi o comando

git push --force origin 0b258eb:some-branch

0

Para pessoas em situações realmente ruins como eu (por exemplo, se você estiver recebendo bad objecterros durante a execução git reset --hard):

Eu escrevi um script chamado treesaver que puxa todos os seus arquivos da API do GitHub como último recurso. Veja como usá-lo:

  1. Clone o treesaverscript e cdpara ele.
  2. Encontre a SHAseqüência da árvore que você gostaria de restaurar acessando https://api.github.com/repos/<your_username_or_org>/<repo>/events.
  3. Na payloadpropriedade correspondente ao seu evento push, encontre o commitpara o qual você gostaria de reverter e clique nele url.
  4. Abaixo commit.tree, copie o tree's url.
  5. Corra python3 main.py <tree_url> <path_to_save_to>.

Por exemplo, no meu caso, eu executaria:

python3 main.py https://api.github.com/repos/anthonykrivonos/my-repo/git/trees/1234567 .

Claro, os PRs são bem-vindos.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.