git-revert delete - Como reverter vários commits git?




tag sort (11)

Eu tenho um repositório git que se parece com isso:

A -> B -> C -> D -> HEAD

Eu quero que o chefe do ramo aponte para A, ou seja, quero que B, C, D e HEAD desapareçam e quero que a cabeça seja sinônimo de A.

Parece que eu posso tentar rebase (não se aplica, desde que eu empurrei mudanças no meio), ou reverter. Mas como reverter vários commits? Eu reverter um de cada vez? O pedido é importante?


Answers

Semelhante à resposta de Jakub, isso permite que você selecione com facilidade confirmações consecutivas para reverter.

# revert all commits from B to HEAD, inclusively
$ git revert --no-commit B..HEAD  
$ git commit -m 'message'

Na minha opinião, uma maneira muito fácil e limpa poderia ser:

voltar para A

git checkout -f A

apontar a cabeça do mestre para o estado atual

git symbolic-ref HEAD refs/heads/master

Salve 

git commit

Maneira limpa que eu achei útil

git revert --no-commit HEAD~3..

Este comando reverte os últimos 3 commits com apenas um commit.

Também não reescreve a história.


Se você quiser reverter temporariamente as confirmações de um recurso, poderá usar a série de comandos a seguir.

Aqui é como funciona

git log --pretty = oneline | grep 'feature_name' | corte -d '' -f1 | xargs -n1 git revert --no-edit


git reset --hard a
git reset --mixed d
git commit

Isso funcionará como uma reversão para todos eles de uma só vez. Dê uma boa mensagem de commit.


Para fazer isso você só precisa usar o comando revert , especificando o intervalo de commits que você deseja reverter.

Levando em conta o seu exemplo, você teria que fazer isso (assumindo que você está na ramificação 'master'):

git revert master~3..master

Isto irá criar um novo commit no seu local com o commit inverso de B, C e D (o que significa que ele irá desfazer as mudanças introduzidas por estes commits):

A <- B <- C <- D <- BCD' <- HEAD

Esta é uma expansão de uma das soluções fornecidas na resposta de Jakub

Fui confrontado com uma situação em que os commits que eu precisava reverter eram um pouco complexos, com vários dos commits sendo mesclados com commits, e eu precisava evitar reescrever o histórico. Eu não era capaz de usar uma série de comandos git revert porque acabei encontrando conflitos entre as mudanças de reversão sendo adicionadas. Acabei usando os seguintes passos.

Primeiro, confira o conteúdo do commit alvo enquanto deixa o HEAD na ponta do branch:

$ git checkout -f <target-commit> -- .

(O - garante que <target-commit> seja interpretado como um commit em vez de um arquivo; o arquivo. Refere-se ao diretório atual.)

Em seguida, determine quais arquivos foram adicionados nos commits que estão sendo revertidos e, portanto, precisam ser excluídos:

$ git diff --name-status --cached <target-commit>

Os arquivos que foram adicionados devem aparecer com um "A" no início da linha e não deve haver outras diferenças. Agora, se algum arquivo precisar ser removido, monte esses arquivos para remoção:

$ git rm <filespec>[ <filespec> ...]

Por fim, comprometa a reversão:

$ git commit -m 'revert to <target-commit>'

Se desejar, certifique-se de que estamos de volta ao estado desejado:

$git diff <target-commit> <current-commit>

Não deve haver diferenças.


Nenhum deles funcionou para mim, então eu tinha três commits para reverter (os últimos três commits), então eu fiz:

git revert HEAD
git revert HEAD~2
git revert HEAD~4
git rebase -i HEAD~3 # pick, squash, squash

Funcionou como um encanto :)


Primeiro, certifique-se de que sua cópia de trabalho não seja modificada. Então:

git diff HEAD commit_sha_you_want_to_revert_to | git apply

e depois apenas se comprometer. Não esqueça de documentar qual é o motivo da reversão.


Expandindo o que escrevi em um comentário

A regra geral é que você não deve reescrever (mudar) a história que você publicou, porque alguém pode ter baseado seu trabalho nela. Se você reescrever (alterar) o histórico, você teria problemas ao mesclar as alterações e atualizá-las.

Portanto, a solução é criar um novo commit que reverta as alterações das quais você deseja se livrar. Você pode fazer isso usando o comando git revert .

Você tem a seguinte situação:

A <-- B  <-- C <-- D                                               <-- master <-- HEAD

(setas aqui se referem à direção do ponteiro: a referência "pai" no caso de commits, a top commit no caso de head de ramificação (branch ref) e o nome de branch no caso de referência HEAD).

O que você precisa criar é o seguinte:

A <-- B  <-- C <-- D <-- [(BCD)^-1]                   <-- master <-- HEAD

onde "[(BCD) ^ - 1]" significa o commit que reverte as mudanças em commits B, C, D. A matemática nos diz que (BCD) ^ - 1 = D ^ -1 C ^ -1 B ^ -1, então você pode obter a situação necessária usando os seguintes comandos:

$ git revert --no-commit D
$ git revert --no-commit C
$ git revert --no-commit B
$ git commit -m "the commit message"

A solução alternativa seria checkout conteúdo do commit A e confirmar este estado:

$ git checkout -f A -- .
$ git commit -a

Então você teria a seguinte situação:

A <-- B  <-- C <-- D <-- A'                       <-- master <-- HEAD

O commit A 'tem o mesmo conteúdo que o commit A, mas é um commit diferente (commit message, parents, commit date).

A solução de Jeff Ferland, modificada por Charles Bailey, baseia-se na mesma ideia, mas usa o git reset :

$ git reset --hard A
$ git reset --soft @{1}  # (or ORIG_HEAD), which is D
$ git commit

Um caso de uso de git fetch é que o seguinte informará quaisquer alterações na ramificação remota desde o último pull ... para que você possa verificar antes de fazer um pull real, o que poderia alterar os arquivos na ramificação atual e na cópia de trabalho.

git fetch
git diff ...origin




git commit git-revert