Setzen Sie eine Reihe von Commits in git zurück

127

Wie kann ich eine Reihe von Commits in Git zurücksetzen? In der Dokumentation zu gitrevisions kann ich nicht erkennen, wie der von mir benötigte Bereich angegeben werden soll. Beispielsweise:

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

Ich möchte das Äquivalent von tun:

git revert B-D

wo das Ergebnis wäre:

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

wobei F die Umkehrung von BD einschließlich enthält.

Alex Spurling
quelle
Gegen Ende der Seite gitrevisions (7) befindet sich ein Abschnitt mit der Überschrift "SPECIFYING RANGES". Wie unterscheidet sich das, was Sie wollen, von dem, was dort beschrieben wird?
Gareth McCaughan
2
Die Seite gitrevisions schlägt vor, dass 'git revert A..D' macht, was ich will. Wenn ich jedoch versuche, dass ich den Fehler "fatal: Kann 'A..D' nicht finden" erhalte
Alex Spurling

Antworten:

172

Welche Version von Git verwenden Sie?

Das Zurücksetzen mehrerer Commits wird nur in Git1.7.2 + unterstützt: Weitere Informationen finden Sie unter " Rollback auf ein altes Commit durch mehrmaliges Zurücksetzen ".
Die aktuelle git revertManpage ist nur für die aktuelle Git-Version (1.7.4+).


Wie der OP Alex Spurling in den Kommentaren berichtet:

Ein Upgrade auf 1.7.4 funktioniert einwandfrei.
Um meine eigene Frage zu beantworten, ist dies die Syntax, nach der ich gesucht habe:

git revert B^..D 

B^bedeutet "das erste übergeordnete Commit von B": Dies ermöglicht die Einbeziehung Bin das Zurücksetzen.
Siehe " git rev-parseAbschnitt SPEZIFIZIEREN VON REVISIONEN ", der <rev>^z. B. dieHEAD^ Syntax enthält: Weitere Informationen finden Sie unter " Was bedeutet das ^Zeichen caret ( )? ")

Beachten Sie, dass jedes zurückgesetzte Commit separat festgeschrieben wird.

Henrik N stellt in den Kommentaren klar :

git revert OLDER_COMMIT^..NEWER_COMMIT

Wie unten gezeigt, können Sie ohne sofortiges Festschreiben zurückkehren:

git revert -n OLDER_COMMIT^..NEWER_COMMIT
git commit -m "revert OLDER_COMMIT to NEWER_COMMIT"
VonC
quelle
1
Danke, das war die Antwort. Ein Upgrade auf 1.7.4 funktioniert einwandfrei. Um meine eigene Frage zu beantworten, ist dies die Syntax, nach der ich gesucht habe: git revert B ^ .. D
Alex Spurling
Genius. Vielen Dank. Mir war nicht in den Sinn gekommen, dass ich Commits in umgekehrter Reihenfolge zurücksetzen muss, damit die Patches angewendet werden, duh. Dieser Befehl zeigt den Weg.
Tim Abell
5
Ich beziehe mich oft auf diese Antwort und es dauert immer eine Weile, bis ich die Reihenfolge herausgefunden habe. Also, um meinem zukünftigen Selbst zu helfen:git revert OLDER_COMMIT^..NEWER_COMMIT
Henrik N
2
was bedeutet das ^
Dustin Getz
1
@DustinGetz erstes übergeordnetes Element: siehe git-scm.com/docs/gitrevisions : "Ein Suffix ^zu einem Revisionsparameter bedeutet das erste übergeordnete Element dieses Festschreibungsobjekts ."
VonC
15

Wenn Sie den Commit-Bereich B in einem einzigen Commit auf D zurücksetzen möchten (zumindest in Git-Version 2), können Sie dies tun

 git revert -n B^..D

Dadurch werden die durch Commits vorgenommenen Änderungen vom übergeordneten Commit von B (ausgeschlossen) zum Commit von D (enthalten) zurückgesetzt, es wird jedoch kein Commit mit den zurückgesetzten Änderungen erstellt. Durch das Zurücksetzen werden nur der Arbeitsbaum und der Index geändert.

Vergessen Sie nicht, die Änderungen danach zu übernehmen

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

Sie können mit derselben Methode auch mehrere nicht verwandte Commits in einem einzigen Commit zurücksetzen. Zum Beispiel, um B und D zurückzusetzen, aber nicht C.

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

Referenz: https://www.kernel.org/pub/software/scm/git/docs/git-revert.html

Danke Honza Haering für die Korrektur

Ramast
quelle
3
git revert -n B..Dsetzt Commit B nicht zurück, nur C und D. setzen auch git revert -n B^..DB zurück.
Honza Haering
Laut Git-Dokumentation ist dies der Fall. Referenz in der Post
Ramast
1
Wenn Sie in der Referenz auf dieses Beispiel verweisen (was meiner Meinung nach etwas verwirrend ist) git revert -n master~5..master~2, heißt es, dass das fünftletzte Commit enthalten ist. Ist master~5aber eigentlich 6. letzter Commit. Siehe Revisionsauswahl in Git-Dokumenten für detaillierte Informationen zur ..Notation :-)
Honza Haering
6

Das git revert OLDER_COMMIT^..NEWER_COMMIThat bei mir nicht funktioniert.

Ich habe verwendet git revert -n OLDER_COMMIT^..NEWER_COMMITund alles ist gut. Ich benutze die Git-Version 1.7.9.6.

Orlando
quelle
Ich hatte das gleiche Problem und behebte es mit -n, aber Sie sollten ^ mit OLDER_COMMIT verlassen (git revert -n OLDER_COMMIT ^ .. NEWER_COMMIT).
FeelGood
@FeelGood warum solltest du das ^ verlassen?
Orlando
Ich hatte Geschichte A -> B -> C und das Ziel war es, B und C zurückzusetzen. Wenn ich 'git revert -n B..C' ausführe, wurde nur C zurückgesetzt. Wenn ich 'git revert -n B ^ .. C' verwendet habe, hat git beide Commits zurückgesetzt. Vielleicht habe ich etwas falsch gemacht.
FeelGood
cool, muss es testen, aber ich denke, in meinem Fall hat es gut funktioniert (es sei denn, ich habe einen 1-Commit-Bereich zurückgesetzt lol), ich werde die Antwort so ändern, dass sie das ^ enthält. danke
Orlando
2
Mit der Option -noder --no-commitwerden alle Änderungen im gesamten Bereich in einem einzigen Commit zurückgesetzt, anstatt für jedes Commit im Bereich ein Commit zum Zurücksetzen zu erstellen. Das Endergebnis ist das gleiche wie in, die gleichen Änderungen werden zurückgesetzt. Kommt nur darauf an, wie deine Git-Geschichte aussehen soll.
Dennis
0

Verwenden Sie git rebase -idiese Option, um die relevanten Commits zu einem zusammenzufassen. Dann müssen Sie nur noch ein Commit zurücksetzen.

Graham Borland
quelle
7
Wenn Sie Git Rebase verwenden, können Sie die Commits einfach entfernen. Ich denke, es gibt einen Grund, nicht neu zu gründen, wie SHA1 von Commit F gleich zu halten.
Paŭlo Ebermann
5
Alternativ können Sie die zurückgesetzten Commits zu einem Squash zusammenfassen.
Aeosynth