Annuler une plage de commits dans git

128

Comment puis-je annuler une plage de commits dans git? En regardant la documentation de gitrevisions , je ne vois pas comment spécifier la plage dont j'ai besoin. Par exemple:

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

Je veux faire l'équivalent de:

git revert B-D

où le résultat serait:

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

où F contient l'inverse de BD inclus.

Alex Spurling
la source
Vers la fin de la page gitrevisions (7), il y a une section intitulée "SPÉCIFICATION DES GAMMES". En quoi ce que vous voulez diffère-t-il de ce qui y est décrit?
Gareth McCaughan le
2
La page gitrevisions suggère que 'git revert A..D' fera ce que je veux. Cependant, quand j'essaye que j'obtiens l'erreur "fatal: Impossible de trouver 'A..D'"
Alex Spurling

Réponses:

173

Quelle version de Git utilisez-vous?

Rétablissement de plusieurs commits uniquement pris en charge dans Git1.7.2 +: voir « Revenir à un ancien commit en utilisant revenir plusieurs fois » pour plus de détails.
La git revertpage de manuel actuelle concerne uniquement la version actuelle de Git (1.7.4+).


Comme le rapporte l' OP Alex Spurling dans les commentaires:

La mise à niveau vers la version 1.7.4 fonctionne correctement.
Pour répondre à ma propre question, voici la syntaxe que je recherchais:

git revert B^..D 

B^signifie "le premier commit parent de B": cela permet de l'inclure Bdans le retour.
Voir la section " git rev-parseSPÉCIFICATION DES RÉVISIONS " qui inclut la syntaxe <rev>^, par exempleHEAD^ : voir plus à " Que signifie le caractère caret ( ^)? ")

Notez que chaque validation annulée est validée séparément.

Henrik N clarifie dans les commentaires :

git revert OLDER_COMMIT^..NEWER_COMMIT

Comme indiqué ci-dessous, vous pouvez revenir en arrière sans vous engager immédiatement:

git revert -n OLDER_COMMIT^..NEWER_COMMIT
git commit -m "revert OLDER_COMMIT to NEWER_COMMIT"
VonC
la source
1
Merci, c'était la réponse. La mise à niveau vers la version 1.7.4 fonctionne correctement. Pour répondre à ma propre question, voici la syntaxe que je recherchais: git revert B ^ .. D
Alex Spurling
génie. Merci. Je n'avais pas pensé que je devais annuler les commits dans l'ordre inverse pour que les correctifs s'appliquent, duh. Cette commande montre le chemin.
Tim Abell
5
Je me réfère souvent à cette réponse, et il me faut toujours un certain temps pour comprendre l'ordre. Alors pour aider mon futur moi:git revert OLDER_COMMIT^..NEWER_COMMIT
Henrik N
2
que signifie le ^?
Dustin Getz
1
@DustinGetz premier parent: voir git-scm.com/docs/gitrevisions : "Un suffixe ^à un paramètre de révision signifie le premier parent de cet objet de validation".
VonC
15

Si vous souhaitez rétablir la plage de validation B en D (au moins dans la version 2 de git) en un seul commit, vous pouvez faire

 git revert -n B^..D

Cela rétablit les modifications effectuées par les validations du commit parent de B (exclu) vers le commit D (inclus), mais ne crée aucun commit avec les modifications annulées. Le retour ne modifie que l'arborescence de travail et l'index.

N'oubliez pas de valider les modifications après

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

Vous pouvez également annuler plusieurs validations non liées en une seule validation, en utilisant la même méthode. par exemple pour inverser B et D mais pas C

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

Référence: https://www.kernel.org/pub/software/scm/git/docs/git-revert.html

Merci Honza Haering pour la correction

Ramast
la source
3
git revert -n B..Dn'annule pas le commit B, seuls C et D. git revert -n B^..Dannulent également B.
Honza Haering
selon la documentation de git, il le fait. référence dans le post
Ramast
1
Si vous vous référez à cet exemple (qui je pense est un peu déroutant) dans la référence:, git revert -n master~5..master~2il est dit cinquième dernier commit inclus. Mais master~5c'est en fait le 6e dernier commit. Voir la sélection de révision dans la documentation git pour des informations détaillées sur la ..notation :-)
Honza Haering
6

Faire git revert OLDER_COMMIT^..NEWER_COMMIT n'a pas fonctionné pour moi.

Je l'ai utilisé git revert -n OLDER_COMMIT^..NEWER_COMMITet tout est bon. J'utilise la version git 1.7.9.6.

Orlando
la source
J'ai eu le même problème et je le corrige en utilisant -n, mais vous devriez laisser ^ avec OLDER_COMMIT (git revert -n OLDER_COMMIT ^ .. NEWER_COMMIT).
FeelGood
@FeelGood pourquoi devriez-vous quitter le ^?
Orlando
J'avais l'historique A -> B -> C et le but était de revenir à B et C. Quand je lance 'git revert -n B..C', seul C était inversé. Quand j'ai utilisé 'git revert -n B ^ .. C', git a annulé les deux commits. Peut-être que j'ai fait quelque chose de mal.
FeelGood
cool, je dois le tester mais je pense que dans mon cas, cela a bien fonctionné (à moins que je ne revienne à une plage de validation de 1 lol), je vais modifier la réponse pour inclure le ^. merci
Orlando
2
L' option -nou --no-commitannulera toutes les modifications de la plage en une seule validation, au lieu de créer une validation de retour pour chaque validation de la plage. Le résultat final est le même, comme dans, les mêmes modifications seront annulées. Cela dépend de la façon dont vous voulez que votre historique git ressemble.
Dennis
0

Utilisez git rebase -ipour écraser les commits pertinents en un seul. Ensuite, vous n'avez qu'un seul commit à annuler.

Graham Borland
la source
7
Si vous utilisez git rebase, vous pouvez simplement supprimer les commits. Je pense qu'il y a une raison de ne pas rebase, comme vouloir garder SHA1 du commit F identique.
Paŭlo Ebermann
5
Sinon, écrasez les commits de retour en un seul.
aeosynth