Reverter uma série de confirmações no git

127

Como posso reverter um intervalo de confirmações no git? De olhar para as gitrevisions documentação , não consigo ver como especificar o intervalo necessário. Por exemplo:

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

Eu quero fazer o equivalente a:

git revert B-D

onde o resultado seria:

A -> B -> C -> D -> E -> F -> HEAD

onde F contém o reverso do BD inclusive.

Alex Spurling
fonte
No final da página gitrevisions (7), há uma seção intitulada "SPECIFYING RANGES". Como o que você quer difere do descrito aqui?
Gareth McCaughan
2
A página gitrevisions sugere que 'git revert A..D' fará o que eu quero. No entanto, quando tento obter o erro "fatal: Não é possível encontrar 'A..D'"
Alex Spurling

Respostas:

172

Qual versão do Git você está usando?

A reversão de várias confirmações é suportada apenas no Git1.7.2 +: consulte " Reversão para uma confirmação antiga usando a reversão várias vezes " . Para obter mais detalhes.
A git revertpágina de manual atual é apenas para a versão atual do Git (1.7.4+).


Como o OP Alex Spurling relata nos comentários:

A atualização para 1.7.4 funciona bem.
Para responder minha própria pergunta, esta é a sintaxe que eu estava procurando:

git revert B^..D 

B^significa "o primeiro commit pai de B": que permite incluir Bna reversão.
Consulte a git rev-parseseção " ESPECIFICANDO REVISÕES ", que inclui a sintaxe <rev>^, por exemploHEAD^ : veja mais em " O que o ^caractere de sinal de intercalação ( ) significa? ")

Observe que cada confirmação revertida é confirmada separadamente.

Henrik N esclarece nos comentários :

git revert OLDER_COMMIT^..NEWER_COMMIT

Como mostrado abaixo, você pode reverter sem confirmar imediatamente:

git revert -n OLDER_COMMIT^..NEWER_COMMIT
git commit -m "revert OLDER_COMMIT to NEWER_COMMIT"
VonC
fonte
1
Obrigado, essa foi a resposta. A atualização para 1.7.4 funciona bem. Para responder à minha própria pergunta, esta é a sintaxe que eu estava procurando: git revert B ^ .. D
Alex Spurling
gênio. obrigado. Não me ocorreu que eu preciso reverter confirmações em ordem inversa para que os patches se apliquem, duh. Este comando mostra o caminho.
Tim Abell 15/05
5
Refiro-me a essa resposta com frequência e sempre levo um tempo para descobrir a ordem. Então, para ajudar meu futuro eu:git revert OLDER_COMMIT^..NEWER_COMMIT
Henrik N
2
o que significa o ^?
Dustin Getz
1
Primeiro pai do @DustinGetz: consulte git-scm.com/docs/gitrevisions : "Um sufixo ^para um parâmetro de revisão significa o primeiro pai desse objeto de confirmação".
VonC 15/10/2015
15

Se você deseja reverter o intervalo de confirmação B para D (pelo menos na versão 2 do git) em uma única confirmação, você pode fazer

 git revert -n B^..D

Isso reverte as alterações feitas por confirmações do commit pai de B (excluído) no commit D (incluído), mas não cria nenhum commit com as alterações revertidas. A reversão modifica apenas a árvore de trabalho e o índice.

Não se esqueça de confirmar as alterações depois

 git commit -m "revert commit range B to D"

Você também pode reverter várias confirmações não relacionadas em uma única confirmação, usando o mesmo método. por exemplo, para reverter B e D, mas não C

 git revert -n B D
 git commit -m "Revert commits B and D"

Referência: https://www.kernel.org/pub/software/scm/git/docs/git-revert.html

Obrigado Honza Haering pela correção

Ramast
fonte
3
git revert -n B..Dnão reverte a confirmação B, apenas C e D. git revert -n B^..Dreverte B também.
Honza Haering 02/02
de acordo com a documentação do git. referência no post
Ramast 03/02
1
Se você se referir a este exemplo (o que eu acho um pouco confuso) na referência git revert -n master~5..master~2:, diz o quinto commit mais recente incluído. Mas master~5é realmente o sexto mais recente commit. Consulte a seleção de revisões nos documentos do git para obter informações detalhadas sobre.. notação :-)
Honza Haering
6

Fazer git revert OLDER_COMMIT^..NEWER_COMMITnão funcionou para mim.

Eu usei git revert -n OLDER_COMMIT^..NEWER_COMMITe está tudo bem. Estou usando a versão git 1.7.9.6.

Orlando
fonte
Eu tive o mesmo problema e o corrigi usando -n, mas você deve deixar ^ com OLDER_COMMIT (git revert -n OLDER_COMMIT ^ .. NEWER_COMMIT).
FeelGood
@FeelGood Por que você deveria deixar o ^?
Orlando
Eu tinha o histórico A -> B -> C e o objetivo era reverter B e C. Quando executo 'git revert -n B..C', apenas C foi revertido. Quando eu usei 'git revert -n B ^ .. C', o git reverteu os dois commits. Talvez eu tenha feito algo errado.
FeelGood
legal, bem tenho que testá-lo, mas acho que no meu caso funcionou bem (a menos que eu estivesse revertendo um intervalo de 1 confirmação lol) vou modificar a resposta para incluir o ^. obrigada
Orlando
2
A opção -nou --no-commitreverterá todas as alterações no intervalo em uma única confirmação, em vez de criar uma confirmação de reversão para cada confirmação no intervalo. O resultado final é o mesmo, pois as mesmas alterações serão revertidas. Depende apenas de como você deseja que seu histórico do git seja.
Dennis
0

Use git rebase -ipara esmagar os commits relevantes em um. Então você apenas tem um compromisso para reverter.

Graham Borland
fonte
7
Se estiver usando o git rebase, você pode simplesmente remover as confirmações. Eu acho que há uma razão para não fazer uma nova recuperação, como querer manter o SHA1 do commit F igual.
Paŭlo Ebermann
5
Como alternativa, esmague a consolidação reversa em uma.
precisa saber é