Wer ist "sie" und "wir" in einem "Git Revert"?

Sep 16 2020

Ich kann nicht verstehen, wer usund themin diesen Konflikten während eines git revert, also weiß ich nicht wirklich, was hier passiert:

git revert some_commit_hash

Dann git statuszeigt folgende Konflikte:

deleted by them: path/to/file1.h
both modified:   path/to/file2.h
deleted by them: path/to/file1.cpp
deleted by them: path/to/test_file1.cpp
added by us:     path/to/file3.h
deleted by them: path/to/file4.h
added by us:     path/to/file5.h

Wer ist "wir"? Wer sind sie"?

Update: Beachten Sie, dass das Commit, das ich zurücksetze, ein sehr großes Merge-Commit ist.


NICHT Duplikate:

  1. weil es nicht klarstellt, wer ist usund them: GIT: Wie gefährlich ist der Konflikt "von uns gelöscht"?
  2. weil es deckt mergeund rebaseaber NICHT revert, und git verwendet häufig die gleichen Begriffe, um je nach Operation entgegengesetzte Dinge zu bedeuten : Wer ist "wir" und wer sind "sie" laut Git?
  3. weil es nicht "uns" und "sie" erwähnt - Git - ein Zurücksetzen, Konflikte

Antworten

4 LeGEC Sep 16 2020 at 02:17

Wenn ein Konflikt auftritt, gilt in allen Situationen folgende Regel:

  • ours/ usist der Status des aktuellen HEAD(das aktive Commit)
  • theirs/ themist der Status der anderen Seite (das Commit wird zusammengeführt, das Commit wird ausgewählt / neu basiert oder in Ihrem Fall die "Umkehrung" des Commits, das Sie zurücksetzen möchten).

Einige zusätzliche rebaseErläuterungen im Fall von a (Beantwortung des Kommentars von @GabrielStaples):

Wenn Sie aktiviert sind my/branchund ausgeführt werden git rebase other/branch, gitwird das Head-Commit von other/branchausgecheckt und einige Commits werden erneut abgespielt.

Wenn ein Konflikt auftritt, wird, da das ausgecheckte Commit von stammt other/branch, oursgrob dargestellt other/branchund theirswird es sein my/branch.

Dieser Teil widerspricht der Intuition " ourssollte meine Änderungen sein", passt aber zur obigen Beschreibung: Zum Zeitpunkt des Konflikts ist das ausgecheckte Commit oursdie andere Seite (das Commit wird wiederholt) theirs.

2 GabrielStaples Sep 16 2020 at 07:05

TLDR;

Springen Sie ganz nach unten, um die Ergebnisse und Schlussfolgerungen zu erhalten.

Einzelheiten:

Hinsichtlich:

Dann git statuszeigt folgende Konflikte:

deleted by them: path/to/file1.h
both modified:   path/to/file2.h
deleted by them: path/to/file1.cpp
deleted by them: path/to/test_file1.cpp
added by us:     path/to/file3.h
deleted by them: path/to/file4.h
added by us:     path/to/file5.h

Ich habe experimentiert und Folgendes beobachtet.

Zuerst habe ich nur die Konflikte in der beiden geänderten Datei manuell gelöst path/to/file2.h, wie es für jeden Rebase- oder Merge-Konflikt normal ist. Ich habe dann alle Dateien hinzugefügt und das Zurücksetzen abgeschlossen:

git add -A
git revert --continue

Als nächstes habe ich beobachtet , dass alle Dateien mit markiert , indem sie gelöscht , sowie alle mit markierten Dateien von uns hinzugefügt , present / in Existenz auf meinem Dateisystem waren. Also löschte der Revert keinen von ihnen. Als nächstes wollte ich wissen: Welches Commit hat diese Dateien erstellt? Führen Sie dazu Folgendes aus ( Quelle ):

git log --diff-filter=A -- path/to/file

Dies zeigt die git log commit_hashfür nur die eine Single commit_hash, die diese Datei erstellt hat. Ich habe dies einzeln für jede Datei gemacht, die von ihnen gelöscht oder von uns hinzugefügt wurde :

git log --diff-filter=A -- path/to/file1.h        # added by the commit I reverted
git log --diff-filter=A -- path/to/file1.cpp      # added by the commit I reverted
git log --diff-filter=A -- path/to/test_file1.cpp # added by the commit I reverted
git log --diff-filter=A -- path/to/file3.h        # added by a later commit
git log --diff-filter=A -- path/to/file4.h        # added by the commit I reverted
git log --diff-filter=A -- path/to/file5.h        # added by a later commit

Ich habe festgestellt, dass 4 der Dateien, wie oben angegeben, durch das von mir zurückgesetzte Commit hinzugefügt wurden. Beachten Sie, dass dies bedeutet, dass sie vom Commit some_commit_hashselbst hinzugefügt wurden , NICHT vom Revert-Commit, das beim Ausführen erstellt wurde git revert some_commit_hash. Warum existierten sie noch, wenn ich dieses Commit rückgängig machte? Nun, es stellt sich heraus, dass ein späteres Commit, das wir aufrufen werden later_commit_hash, das NACH dem passiert ist some_commit_hash, alle 6 dieser Dateien berührt hat, 4 davon modifiziert und 2 davon erstellt hat.

Lassen Sie uns Gruppe die oben genannten Dateien von Gruppen von ihnen gelöscht vs von uns hinzugefügt :

# deleted by them:
path/to/file1.h
path/to/file1.cpp
path/to/test_file1.cpp
path/to/file4.h

# added by us:
path/to/file3.h
path/to/file5.h

Geben Sie nun an, welche Datei von welchem ​​Commit hinzugefügt wurde:

# deleted by them / added by the commit I reverted (`some_commit_hash`)
path/to/file1.h
path/to/file1.cpp
path/to/test_file1.cpp
path/to/file4.h

# added by us / added by a later commit (`later_commit_hash`)
path/to/file3.h
path/to/file5.h

Sie können also sehen, dass von ihnen gelöschte Dateien durch das von mir zurückgesetzte Commit hinzugefügt wurden, was bedeutet, dass durch das Zurücksetzen dieses Commits diese Dateien gelöscht werden! Also, thembezieht sich auf das, kehrte commit wird some_commit_hash, während usauf die übrigen Commits bezieht sich auf HEAD.

Der Konflikt bestand darin, dass later_commit_hashdiese 4 "von ihnen gelöschten" Dateien berührt wurden, sodass sie git revert some_commit_hashnicht gelöscht werden durften. Und die 2 "von uns hinzugefügten" Dateien existierten vorher NICHT some_commit_hash, daher bestand der Konflikt darin, dass sie nach dem Zurücksetzen nicht hätten existieren sollen, aber sie taten es, weil sie von erstellt wurden later_commit_hash.

Die Lösung, die ich gemacht habe, ist, dass ich alle 6 Dateien manuell gelöscht habe:

rm path/to/file1.h
rm path/to/file1.cpp
rm path/to/test_file1.cpp
rm path/to/file3.h
rm path/to/file4.h
rm path/to/file5.h

dann habe ich diese Änderung als neues Commit festgeschrieben:

git add -A
git commit

Ich hätte jedoch stattdessen vor dem Zurücksetzen des Commits auf den Speicherort zurücksetzen und later_commit_hashzuerst zurücksetzen können , gefolgt vom Zurücksetzen des some_commit_hashzweiten, um diese Änderungen effektiv in der folgenden Reihenfolge zurückzusetzen:

git reset --hard HEAD~  # WARNING! DESTRUCTIVE COMMAND! BE CAREFUL.
git revert later_commit_hash
git revert some_commit_hash
# should result in no conflicts during both of those reverts now

Ergebnisse und Schlussfolgerungen:

In beiden Fällen, um meine eigene Frage zu beantworten:

Während git revert some_commit_hash:

  1. "us" = das aktuell ausgecheckte Commit (dh :) HEADzum Zeitpunkt der Eingabe und Ausführung git revert some_commit_hashund:
  2. "them" = das (Umgekehrte oder Gegenteil von?) das Commit, das Sie zurücksetzen; Das heißt: Es handelt sich um ein kurzlebiges Commit, das das Gegenteil von ist some_commit_hash, um die some_commit_hashÄnderungen rückgängig zu machen , vorausgesetzt, Sie führen den Befehl aus git revert some_commit_hash.

Update 7. Januar 2020: Ja, das scheint es tatsächlich zu sein. Hier ist mein Kommentar, den ich gerade unter dieser anderen Antwort hier hinterlassen habe . Mein Kommentar scheint perfekt mit der obigen Beobachtung zu korrelieren:

Der Schlüssel zum Mitnehmen für mich hier in Bezug auf git revertist, glaube ich, dass , wenn Sie einen linearen Baum haben ...A--B--C--D(HEAD), mit DIhrem aktuellen zu sein HEAD, und Sie ein git revert B, dann Bdie sehr verpflichten Sie revert versuchen, wird die aktuelle merge-Base oder Slot 1 in dieser "Zusammenführung" und Slot 2 oder "unser" wird D/ HEADund Slot 3 oder "ihre" wird Aoder das übergeordnete Element des Commits, das zurückgesetzt wird, korrekt? Dann wird die "Zusammenführung" auf niedriger Ebene ausgeführt, was dazu führt, dass alle Änderungen von B..Dsowie alle Änderungen von korrekt B..Aangewendet werden Bund dadurch rückgängig gemacht werden. Das ist schwer.

Das bedeutet also, dass dieses "kurzlebige Festschreiben, das das Gegenteil von some_commit_hash" ist, wirklich nur das inverse Diff ist oder ein Diff in der Richtung von von some_commit_hash Ihnen zu seinem übergeordneten Commit zurückkehrt. Jetzt haben Sie eine Low-Level-Git-Zusammenführung unter der Haube, bei der die Zusammenführungsbasis some_commit_hashwiederhergestellt werden soll, "unsere" / "uns" HEADund "ihre" / "sie" die Eltern von some_commit_hashAKA : some_commit_hash~. Während git diese Zusammenführung auf niedriger Ebene durchführt, erfasst der Unterschied von some_commit_hashzu HEAD(dh: das Äquivalent von git diff some_commit_hash..HEAD) alle Ihre neuen Inhalte, und der Unterschied von some_commit_hashzu seinem übergeordneten Element (dh: das Äquivalent von git diff some_commit_hash..some_commit_hash~) erfasst die Umkehrung der durch Festschreiben vorgenommenen Änderungen some_commit_hash. Dadurch wird dieses Commit rückgängig gemacht!

Wenn ich das alles klar habe, macht alles jetzt vollkommen Sinn!


Ich kämpfe immer noch ein bisschen mit diesem Konzept, aber das ist der Kern davon. Die genaue Mechanik, wie Revert funktioniert, würde die Dinge hier wirklich klarstellen, denke ich. Diese Antwort bietet vielleicht etwas mehr Einblick, aber ich verstehe es nicht.

Ich habe gerade auch eine Antwort auf hier zu klären , „uns“ und „ihnen“ , ergänzt für alle 4 git Operationen kann ich mir vorstellen , wo dies passieren kann: git merge, git cherry-pick, git rebase, und git revert: Wer „wir“ ist und wer „sie“ nach zu Git?


(Anmerkungen zu sich selbst):

Müssen einen Blick darauf werfen: http://ezconflict.com/en/conflictsse12.html#x53-890001.7

1 torek Sep 16 2020 at 14:37

Obwohl dies bereits ziemlich gut beantwortet ist, gibt es noch eine Möglichkeit, alles zu betrachten. So sieht es Git selbst. Alle vier Vorgänge - Cherry-Pick, Merge, Rebase und Revert - verwenden dieselbe Maschinerie, und die --oursund --theirsFlags to git checkoutund die -X oursund -X theirsExtended-Optionen beziehen sich auf dieselben Dinge und verwenden denselben internen Code. Ich bezeichne diese Maschinerie gerne als Zusammenführung als Verb , weil wir sie zuerst kennenlernen git merge, wenn die Zusammenführung eine echte Zusammenführung durchführen muss.

Der Zusammenführungsfall

Bei einer echten Zusammenführung sind die Begriffe sinnvoll. Wir beginnen mit dem, was so dargestellt werden kann:

          I--J   <-- ourbranch (HEAD)
         /
...--G--H
         \
          K--L   <-- theirbranch

Hier ourbranchwählt der Name Commit aus J, was unser Commit für unseren Zweig ist (eines von zwei solchen Commits in diesem Fall, obwohl die Anzahl der Commits, die ausschließlich für unseren eigenen Zweig sind, nur mindestens 1 betragen muss , um eine echte Zusammenführung zu erzwingen). Der Name theirbranchwählt Commit aus L, dh das Commit in ihrem Zweig (wieder eines von zwei, wobei hier mindestens ein Commit erforderlich ist).

Was Git tut, um diese Verschmelzung zu tun Verb als eine Zusammenführung einiger Satz von Dateien-ist, für jede Datei in allen drei Commits H, Jund Lvergleichen Sie die Datei in Hvs dass in Jzu sehen , was wir geändert haben , und vergleichen Sie die Datei in Hvs das in, um Lzu sehen, was sie geändert haben. Dann kombiniert Git diese beiden Änderungssätze und wendet die kombinierten Änderungen auf alles an, was sich darin befindet H.

Commit Hist das Merge-Basis- Commit, Commit Jist das "unsere" Commit und Commit List das "ihre" Commit. Jeder Unterschied , ob es sich um eine neue Datei handelt, die "von uns hinzugefügt" wurde, oder um eine Datei, die "von ihnen gelöscht" wurde, oder was auch immer, betrifft das Festschreiben H.

Um die Zusammenführung über die Zusammenführungsmaschinerie auszuführen, führt Git eine im Voraus leicht optimierte Version der folgenden Aktionen aus:

  1. Konfiguration:

    • Lesen Sie Merge Base Commit ( H) in Index an Steckplatz 1
    • Lesen Sie oursCommit ( HEAD= J) in Index an Steckplatz 2
    • Lesen Sie theirscommit ( L) in Index an Steckplatz 3
  2. Identifizieren Sie "gleiche Dateien". Beachten Sie, dass die Schritte 2 und 3 für jede Datei wiederholt werden.

    • Wenn sich in allen drei Slots eine Datei mit dem Namen F befindet , handelt es sich um dieselbe Datei
    • Andernfalls, wenn sich in Steckplatz 1 etwas befindet, versuchen Sie, Umbenennungen zu erraten. Dadurch wird eine Zusammenführungsbasisdatei in Steckplatz 1 mit einer unserer oder ihrer Datei mit einem anderen Namen in Steckplatz 2 und / oder Steckplatz 3 verknüpft. Wenn keine Datei gefunden werden kann, die eine Umbenennung aufruft, haben unsere und / oder ihre Seite diese Datei gelöscht. Diese Fälle können auch zu Konflikten auf hoher Ebene führen, z. B. Umbenennen / Ändern oder Umbenennen / Löschen, bei denen wir einen Konflikt deklarieren und fortfahren, ohne Schritt 3 auszuführen
    • Andernfalls (nichts in Steckplatz 1, aber etwas in Steckplatz 2 und 3) liegt ein Add / Add-Konflikt vor: Erklären Sie, dass diese bestimmte Datei in Konflikt steht, und fahren Sie fort, ohne Schritt 3 auszuführen
  3. Schließen Sie einfache Fälle kurz und erledigen Sie die schweren Fälle mit einer Zusammenführung auf niedriger Ebene:

    • Wenn die Blob-Hash-IDs in den Steckplätzen 1, 2 und 3 übereinstimmen, sind alle drei Kopien gleich. benutze einen von ihnen
    • Wenn die Blob-Hash-ID in Steckplatz 1 mit der in 2 oder 3 übereinstimmt, hat jemand die Datei nicht geändert und jemand hat sie geändert. Verwenden Sie die geänderte Datei, dh nehmen Sie die andere Datei
    • Andernfalls unterscheiden sich alle drei Slots: Führen Sie einen Zeilenblock mit geänderten Blöcken auf niedriger Ebene durch
      • Wenn es während der Zusammenführung auf niedriger Ebene zu einem Zusammenführungskonflikt kommt -X oursoder -X theirsbedeutet "Lösen Sie den Konflikt mithilfe unseres / ihres", wobei sich unser Konflikt in Steckplatz 2 befindet und sich der Konflikt in Steckplatz 3 befindet
      • Beachten Sie, dass dies bedeutet, dass überall dort, wo kein Konflikt vorliegt, z. B. nur eine "Seite" die Zeile 42 geändert hat, die -Xerweiterte Option überhaupt nicht gilt und wir die Änderung vornehmen, unabhängig davon, ob es unsere oder ihre ist

Am Ende dieses Vorgangs wird jede vollständig aufgelöste Datei wieder in ihre normale Position für Steckplatz Null verschoben, wobei die Einträge für Steckplatz 1, 2 und 3 entfernt werden. In jeder nicht aufgelösten Datei bleiben alle drei Index-Slots belegt (bei Löschkonflikten und Add / Add-Konflikten sind einige Slots leer, es wird jedoch ein Slot mit einer Nicht-Null-Stufennummer verwendet, wodurch die Datei als in Konflikt stehend markiert wird).

Daher funktioniert das Zusammenführen oder Zusammenführen als Verb im Git-Index

Alle oben genannten Aktionen werden im Git-Index ausgeführt, mit dem Nebeneffekt, dass aktualisierte Dateien in Ihrem Arbeitsbaum verbleiben. Wenn Konflikte auf niedriger Ebene vorliegen, werden Ihre Arbeitsbaumdateien mit den Konfliktmarkierungen und den verschiedenen Abschnitten aus Zeilen markiert, die den Kopien der Dateien in den Indexsteckplätzen 1 (Zusammenführungsbasis), 2 (unsere) oder entsprechen 3 (ihre).

Letztendlich läuft es immer auf dieselbe Gleichung hinaus: 1 = Basis zusammenführen, 2 = unsere, 3 = ihre. Dies gilt auch dann, wenn der Befehl, der den Index lädt, dies nicht ist git merge.

Cherry-Pick und Revert verwenden die Merge-Maschinerie

Wenn wir ausführen git cherry-pick, haben wir ein Commit-Diagramm, das folgendermaßen aussieht:

...--P--C--...
   \
    ...--H   <-- somebranch (HEAD)

Die Buchstaben Pund Chier stehen für jedes Eltern-Kind-Commit-Paar. Ckann sogar ein Merge-Commit sein, solange wir die -mOption verwenden, um anzugeben, welches übergeordnete Element verwendet werden soll. (Es gibt keine wirkliche Einschränkung, wo die drei Commits in der Grafik leben: Ich habe es mit Heinem Kind eines Commits gezeichnet , das vorher kommt P, aber es kann nach dem P-CPaar sein, wie ...-E-P-C-F-G-Hzum Beispiel, oder es gibt möglicherweise keine Beziehung bei alles zwischen P-Cund HCommits, wenn Sie mehrere disjunkte Untergraphen haben.)

Wenn wir rennen:

git cherry-pick <hash-of-C>

Git findet Commit selbstständig Püber den übergeordneten Link von Czurück zu P. PJetzt fungiert es als Merge-Basis und wird in Index-Slot 1 eingelesen. Dient Cals --theirsCommit und wird in Index-Slot 3 eingelesen. Unser aktuelles Commit Hist das --oursCommit und wird in Index-Slot 2 eingelesen. Die Merge-Maschinerie wird jetzt ausgeführt „unser“ begehen HEADund „ihre“ begehen begehen C, mit der Zusammenführung Basis , die zeigt, wenn wir setzen merge.conflictStyleauf diff3, oder wenn wir verwenden git mergetoolein Merge - Tool Befinden begehen laufen P.

Wenn wir rennen:

git revert <hash-of-C>

Das gleiche passiert, außer dass diesmal Commit Cdie Zusammenführungsbasis in Slot 1 und Commit Pdas --theirsCommit in Slot 3 ist. Das --oursCommit in Slot 2 erfolgt HEADwie gewohnt.

Beachten Sie Folgendes, wenn Sie Cherry-Pick oder Revert für eine Reihe von Commits verwenden:

git cherry-pick stop..start

Das Kirschpflücken funktioniert jeweils ein Commit, wobei zuerst die topologisch älteren Commits verwendet werden, während das Zurücksetzen jeweils ein Commit unter Verwendung der topologisch neueren Commits zuerst ausführt. Das heißt, gegeben:

...--C--D--E--...
 \
  H   <-- HEAD

ein git cherry-pick C..EKopie Dzuerst, dann E, aber ein git revert C..Ezurückkehrt Ezuerst, dann D. (Commit Ckommt nicht ins Spiel, da die Zwei-Punkt-Syntax die Commits ausschließt, die auf der linken Seite des Zwei-Punkt-Ausdrucks erreichbar sind. Weitere Informationen finden Sie in der Dokumentation zu gitrevisions .)

Rebase wird wiederholt gepflückt

Der Rebase-Befehl wird git cherry-pickwiederholt ausgeführt, nachdem der HEAD- Modus verwendet git checkout --detachoder git switch --detachin den getrennten HEAD- Modus versetzt wurde. (Technisch gesehen funktioniert dies jetzt nur noch intern. Früher wurde ein Teil der Shell-Skript-basierten Version von git rebasetatsächlich verwendet git checkout, allerdings mit einer Hash-ID, die ohnehin immer in den getrennten Modus ging.)

Wenn wir rennen git rebase, beginnen wir mit so etwas:

       C--D--E   <-- ourbranch (HEAD)
      /
...--B--F--G--H   <-- theirbranch

Wir rennen:

git checkout ourbranch   # if needed - the above says we already did that
git rebase theirbranch   # or, git rebase --onto <target> <upstream>

Das erste - nun ja , das zweite -, was dies bewirkt, ist der getrennte HEAD-Modus, wobei das HEAD-Commit das Commit ist, das wir mit unserem --ontoArgument ausgewählt haben. Wenn wir kein separates --ontoFlag und Argument verwendet haben, --ontoist dies das einzige Argument, das wir in diesem Fall angegeben haben theirbranch. Wenn wir kein separates upstreamArgument verwendet haben, wird das eine Argument, das wir in diesem Fall angegeben haben theirbranch, für beide Zwecke verwendet.

Git listet auch (erstens, weshalb das Obige an zweiter Stelle steht) die rohen Hash-IDs jedes Commits auf, das kopiert werden soll. Diese Liste ist viel komplizierter, als es auf den ersten Blick scheint, aber wenn wir die zusätzlichen Komplikationen ignorieren, ist dies im Grunde das Ergebnis von:

git rev-list --topo-order --reverse <hash-of-upstream>..HEAD

das in diesem Fall das Hash - IDs von Commits ist C, Dund E: die drei Commits , die aus erreichbar sind ourbranch, die nicht auch von erreichbar theirbranch.

Mit git rebasedieser Liste erzeugt hat und in freistehende-HEAD - Modus gegangen, was haben wir denn jetzt sieht wie folgt aus :

       C--D--E   <-- ourbranch
      /
...--B--F--G--H   <-- theirbranch, HEAD

Jetzt führt Git einen aus git cherry-pick. Das Argument ist die Hash-ID von commit C, das erste Commit, das kopiert wird. Wenn wir uns oben ansehen, wie Cherry-Pick funktioniert, sehen wir, dass dies eine Operation zum Zusammenführen als Verb ist, wobei die Zusammenführungsbasis das übergeordnete Element von C, dh Commit B, das aktuelle --oursCommit oder Commit, das Commit ist H, und das to- Commit ist. kopiert werden oder --theirsfestschreiben, festgeschrieben werden C. Deshalb scheinen unsere und ihre umgekehrt zu sein.

Sobald dieser Kirschpflückvorgang abgeschlossen ist, haben wir nun:

       C--D--E   <-- ourbranch
      /
...--B--F--G--H   <-- theirbranch
               \
                C'  <-- HEAD

Git geht nun zu kopieren zu begehen Dmit git cherry-pick. Die Zusammenführungsbasis ist jetzt Festschreiben C, das --oursFestschreiben ist Festschreiben C'und das --theirsFestschreiben ist Festschreiben D. Dies bedeutet, dass sowohl unsere als auch ihre Commits uns gehören , aber diesmal ist das "unsere" Commit eines, das wir erst vor ein paar Sekunden (oder Millisekunden) erstellt haben!

Es basiert auf dem vorhandenen Commit H, das ihnen gehört, aber es basiert auf dem Commit C', das uns gehört. Wenn wir Zusammenführungskonflikte bekommen, sind sie zweifellos ein Ergebnis der Basis H, möglicherweise einschließlich einer Art Konfliktlösung, die wir manuell durchgeführt haben, um sie durchzuführen C'. Aber im wahrsten Sinne des Wortes sind alle drei Eingabe-Commits unsere . CIndexsteckplatz Nr. 1 stammt vom Commit , Indexsteckplatz Nr. 2 vom Commit C'und Indexsteckplatz Nr. 3 vom Commit D.

Sobald wir alles erledigt haben, ist unser Bild jetzt:

       C--D--E   <-- ourbranch
      /
...--B--F--G--H   <-- theirbranch
               \
                C'-D'  <-- HEAD

Git läuft jetzt git cherry-pickauf dem Hash von Commit E. Die Merge Basis verpflichten D, und die unsere und ihre Commits sind D'und Ejeweils. Während der Rebase gehören also wieder alle drei Commits uns - obwohl Zusammenführungskonflikte wahrscheinlich das Ergebnis des Aufbaus sind H.

Wenn die letzte Auswahl getroffen ist, beendet Git die Rebase, indem er den Namen ourbranch vom alten Commit abzieht Eund in das neue Commit einfügt E':

       C--D--E   [abandoned]
      /
...--B--F--G--H   <-- theirbranch
               \
                C'-D'-E'  <-- ourbranch (HEAD)

Wir befinden uns jetzt wieder im normalen Arbeitsmodus mit angehängten Köpfen. Da git logwir dort beginnen, wo wir uns jetzt befinden - beim Festschreiben E'- und rückwärts arbeiten, ohne das ursprüngliche Festschreiben zu besuchen C, scheint es, als hätten wir die ursprünglichen drei Festschreibungen irgendwie geändert. Wir haben nicht: Sie sind immer noch in unserem Repository vorhanden, verfügbar über den speziellen Pseudo-Ref ORIG_HEADund verfügbar über unsere Reflogs. Wir können sie standardmäßig für mindestens 30 Tage zurückbekommen. Danach können Sie git gcsie ernten und dann sind sie wirklich weg. (Nun, solange wir sie nicht git pushin einem anderen Git-Repository gespeichert haben, das sie noch aufbewahrt.)

eftshift0 Sep 16 2020 at 01:52

Nun ... revertist eine ganz besondere Situation. Denken Sie also an eine normale Verschmelzung mit dem gemeinsamen Vorfahren und allem, dem gesamten Paket, richtig? Nun funktioniert das Ganze die gleiche wie eine Zusammenführung mit Ausnahme (und es ist eine große Ausnahme) , dass die Zusammenführung Motorkräfte the common ancestor der Revision werden Sie zurücksetzen möchten, und the other branchist die Mutter dieser Revision.