Qual é a melhor maneira de desfazer uma mesclagem do Git que apaga arquivos do repositório?

13

Imagine o seguinte: o que acontece (e todos nós estamos usando o SourceTree):

  1. Estamos todos trabalhando fora da origem / desenvolvimento.
  2. Eu vou de férias por uma semana.
  3. Meu colega de trabalho trabalha localmente há vários dias, sem mesclar origem / desenvolvimento de volta ao seu ramo de desenvolvimento local.
  4. Ele tenta dar um empurrão, é informado que ele precisa se fundir primeiro e depois faz um puxão.
  5. Ele entra em conflito, impedindo o processo automático de consolidação após mesclagem.
  6. Supondo que o Git seja como o SVN, meu colega de trabalho descarta os "novos" arquivos em sua cópia de trabalho e, em seguida, confirma a mesclagem - limpando esses "novos" arquivos da cabeça de origem / desenvolvimento.
  7. Uma semana de trabalho para desenvolvedores continua em cima dessa revisão.
  8. Volto de férias e descubro que faltam vários dias do meu trabalho.

Somos todos muito novos no Git (este é o nosso primeiro projeto a usá-lo), mas o que fiz para corrigi-lo foi:

  1. Renomeie "develop" para "develop_old".
  2. Mesclar develop_old em uma nova ramificação "develop_new".
  3. Redefina a ramificação develop_new para a última confirmação antes da mesclagem incorreta.
  4. Cherry escolhe cada commit desde então, um por um, resolvendo conflitos manualmente.
  5. Empurre develop_old e develop_new até a origem.

Neste ponto, develop_new é, espero, uma cópia "boa" de todas as nossas alterações com as semanas subsequentes no valor de trabalho reaplicado. Eu também estou assumindo que "reverso cometer" vai fazer coisas estranhas em um merge, especialmente desde que as próximas semanas de trabalho baseia-se sobre ele - e desde que de mesclagem contém um monte de coisas que não quero, juntamente com material que nós don' t.

Espero que isso nunca aconteça novamente, mas se acontecer novamente, gostaria de saber uma maneira mais fácil / melhor de consertar as coisas. Existe uma maneira melhor de desfazer uma mesclagem "ruim", quando muito trabalho foi feito no repositório com base nessa mesclagem?

George
fonte
1
Você poderia postar uma captura de tela da árvore git (redigida adequadamente) ou a saída do seu git logformato favorito com anotações apropriadas sobre o que aconteceu nos vários commits? (Eu redigir / anotar git log --graph --pretty=oneline --abbrev-commite ir a partir daí)
1
É muito tarde para você, mas os testes de unidade teriam percebido isso.
nalply
1
@ nalply: Não se a mesclagem incorreta também excluir os testes de unidade.
Aaronaught
Uau, isso é realmente azar insidioso.
nalply

Respostas:

6

Se entendi corretamente, esta é a sua situação:

    ,-c--c--c--c--M--a--a--X ← develop
o--o--y--y--y--y-´

Depois de um histórico comum (o), você comprometeu e empurrou seu trabalho (y). Seu colega de trabalho (c) trabalhou no repositório local e fez uma mesclagem incorreta (M). Posteriormente, pode haver alguns commits adicionais (a) em cima de M.

git reset --hard develop M^2
git branch coworker M^1

Agora, seu gráfico se parece exatamente com a mesclagem incorreta:

    ,-c--c--c--c ← coworker
o--o--y--y--y--y ← develop

Faça uma boa mesclagem (G):

git checkout develop
git merge coworker

Resultando em:

    ,-c--c--c--c-、
o--o--y--y--y--y--G ← develop

Agora transplante as confirmações adicionais:

git reset --hard X
git rebase --onto G M develop

Isso fornece o resultado final:

    ,-c--c--c--c-、
o--o--y--y--y--y--G--a--a--X ← develop

Esteja ciente de que isso pode resultar em mais conflitos de mesclagem. Além disso, você acabou de alterar o histórico, ou seja, todos os seus colegas de trabalho devem clonar / redefinir / redefinir o novo histórico.

PS: é claro que você deve substituir G, Me Xem seus comandos, o ID de confirmação correspondente.

michas
fonte
Parece bastante evidente na pergunta que todos esses commits já foram enviados para um repositório compartilhado, então não acho que rebasear seja uma boa opção. Reverter todos os commits recentes e, em seguida, escolher os que foram revertidos e não conflitantes, além da boa mesclagem, é mais seguro.
Aaronaught
Essa foi a parte do clone / reset / rebase. - Se houver apenas alguns desenvolvedores, pedir para atualizar seus repositórios pode ser uma opção válida.
Michas
1

É bom que você esteja pensando em como consertar o repositório, mas se seu colega de trabalho excluiu apenas novos arquivos e não substituiu muitas atualizações, uma abordagem muito mais simples seria simplesmente restaurar os arquivos que foram excluídos.

Eu provavelmente começaria tentando apenas selecionar (na cabeça atual) os commits originais nos quais você adicionou o código que agora está faltando. Se por algum motivo isso não funcionar, basta verificar a revisão antiga com os arquivos adicionados e adicioná-los novamente em uma nova confirmação.

O que você descreve é, na verdade, um subconjunto de um conhecido padrão Git, que para a minha vida não consigo lembrar o nome - mas o essencial é fazer todas as "edições manuais" durante uma mesclagem do Git (ou seja, edições que não estão realmente resolvendo nenhum conflito de mesclagem, mas estão fazendo alguma mudança totalmente não relacionada) é considerada uma prática extremamente ruim porque são essencialmente mascaradas pela própria mesclagem e são facilmente ignoradas nas revisões de código ou nas sessões de depuração.

Portanto, explique definitivamente ao seu colega de trabalho que foi um fracasso épico, mas considere colocar um curativo antes de se preparar para uma grande cirurgia.

Aaronaught
fonte
Concordo que, se arquivos inteiros inteiros desaparecerem, uma coisa que você pode fazer é isso se você não se importa com o histórico dos arquivos antigos: 1. crie um novo ramo a partir do ramo atualmente bagunçado. 2. volte para a ramificação incorreta e crie outra nova ramificação que é sua ramificação de resgate. 4. Copie os arquivos excluídos em algum lugar fora do git 5. Alterne para o outro novo ramo. 6. Copie as novas versões dos arquivos excluídos para a nova ramificação e confirme. Há uma maneira mais complicada que salva história que é um post famosa por Linus T.
Elin
1
Na verdade, isso mostra como você pode usar o checkout jasonrudolph.com/blog/2009/02/25/… Isso é muito melhor.
Elin