Wie wähle ich eine Datei aus einem Zweig aus, wenn ich einen Konflikt während der Git-Rebase auflöse?

Lesezeit: 5 Minuten

Gegeben sei ein Git-Repo mit zwei Branches master und feature. Beim Rebasing des Feature-Zweigs über dem Master mit rebase master Sagen wir diese Datei a.txt enthält einen Konflikt, der gelöst werden muss, bevor die Neubasierung fortgesetzt werden kann.

Ich weiß, dass ich den Konflikt in drei Schritten lösen kann:

  1. offen a.txt in meinem Editor den Konflikt manuell lösen
  2. Anruf git add a.txt um git mitzuteilen, dass ich den Konflikt manuell gelöst habe
  3. Anruf git rebase --continue Bewegen Sie die Rebase nach vorne

Gibt es eine Möglichkeit, Schritt 1 zu vermeiden, indem Sie git mitteilen, dass ich die Version der Datei aus dem Master-Branch oder die Version der Datei aus dem Feature-Branch haben möchte, ohne die Schritte 1 und 2 oben ausführen zu müssen?

Toreks Benutzeravatar
Torek

Ja. Tatsächlich gibt es mehr als einen Weg, dies zu tun.

Die Befehle rebase und merge (und übrigens auch Cherry-Pick) haben alle das gleiche strategy und -X Flags, die an die zugrunde liegende Git-Merge-Maschinerie übergeben werden. Für die recursive Strategie, -Xours und -Xtheirs Wählen Sie die eine oder die andere “Seite” von Dateien aus, wenn eine Datei, die in beiden Zweigen geändert wurde, zusammengeführt wird.

Oder – das ist ganz anders – in den Fällen beim Merge hört bei einem Konflikt aufkönnen Sie verwenden git checkout mit dem --ours oder --theirs Flaggen, um die Version von der einen oder anderen Seite auszuwählen. (Sie können dies mit anderen Befehlen tun; hier bleibe ich dabei --ours und --theirs da diese mit den Argumenten der Befehle übereinstimmen, die die Zusammenführungsmaschinerie verwenden.)

Dies ist natürlich anders, da Sie die Auswahl ändern können:

$ git checkout main
Switched to branch 'main'
$ git merge branch
... conflicts in files A and B ...
$ git checkout --ours -- A    # takes main:A
$ git checkout --theirs -- B  # takes branch:B

Beachten Sie, dass dies ganz anders ist als die „unsere Strategie” (das Obige zeigt die “recursive Strategie mit der ours Option”). Mit der Option “unsere Strategie“, passiert etwas völlig anderes. Beginnen wir ohne es und führen die gleiche Zusammenführung noch einmal durch:

$ git checkout main && git merge branch
... conflicts ...
$ git checkout --ours -- A B  # take main:A and main:B

Nehmen wir an, es gibt eine dritte Datei, C, kann dieser Git alleine zusammenführen. Wenn Sie das oben Gesagte tun, wird git zusammengeführt C und du nimmst main:A und main:B. Wenn Sie verwenden würden git merge --strategy=ours branchaber Git würde nehmen main:A, main:Bund main:C. Es würde die verwerfen branch:C Änderungen, anstatt sie automatisch zusammenzuführen.

Ich habe verwendet git merge oben, weil es dafür sorgt, dass die “unseren” und “ihren” Sachen “richtig funktionieren”. Ich mag jedoch die Art und Weise, wie Git diese benennt, nicht, denn wenn Sie eine Rebase durchführen, wird die Ours/Theirs-Version vertauscht, da die Rebase funktioniert, indem Sie zum “anderen” Zweig wechseln und eine Reihe von Cherry-Picks durchführen. Das ist:

$ git checkout mine; git rebase theirs

funktioniert darunter, indem Sie das (sehr) grobe Äquivalent von:

$ git checkout theirs; git cherry-pick theirs..mine

und dann danach die Verzweigungsetiketten so verschieben, dass diese verzweigt sind theirs bewegt sich eigentlich nicht. (Es ist nicht annähernd so schlimm intern 🙂 aber es schafft es zu machen --ours bedeuten “ihre” und --theirs bedeutet “unser”, was ziemlich schlecht ist extern.)

  • vielen Dank für die Erklärung, warum die Rebase zwischen den Etiketten von Ours und Theirs wechselt.

    – ams

    31. Januar 2014 um 22:22 Uhr

  • @torek Ich liebe deine Antworten immer. F: Ist git merge --strategy=ours gleicht git merge --ours --file_with_conflict1 --file_with_conflict2 ... --file_with_conflict_n wo sind ‘file_with_conflict1’, … ‘file_with_conflict_n’ alle Dateien mit Zusammenführungskonflikten?

    – Diana Vázquez Romo

    22. Januar 2022 um 2:17 Uhr

  • @Diana: git merge nimmt nicht --ours. Denkst du an git merge-file? (Seine Verwendung ist anders, aber es hat --ours.)

    – Torek

    22. Januar 2022 um 2:58 Uhr

  • @torek hoppla! Entschuldigung, formulieren Sie meine Frage hier um: a. git merge --strategy=ours b. git merge dann git checkout --ours --file_with_conflict1 --file_with_conflict2 ... --file_with_conflict_n wo sind ‘file_with_conflict1’, … ‘file_with_conflict_n’ alle Dateien mit Zusammenführungskonflikten? Sind (a) und (b) äquivalent?

    – Diana Vázquez Romo

    24. Januar 2022 um 14:57 Uhr


  • @Diana: Ach. Nein, weil git merge ohne -s ours versucht Zusammenführungen für jede Datei. Einige davon werden konfliktfrei gelingen und so die Arbeit kombinieren. Andere werden Konflikte bekommen; der git checkout --ours denn diese Akten werden ihre Arbeit wegwerfen und nur unsere nehmen. Wir erhalten also eine Mischung: einige Dateien ausschließlich von unseren (wo wir eine Datei geändert haben und sie nicht, oder wo es einen Konflikt gab), einige ausschließlich von ihnen (wo sie eine Datei geändert haben und wir nicht), und einige kombiniert (wo Merge Arbeit ohne Konflikte kombinieren konnte). Aber mit -s unsere, Git wird ignoriere ihre Arbeit.

    – Torek

    24. Januar 2022 um 16:37 Uhr


Benutzeravatar von Ash Wilson
Ash Wilson

Sie können Folgendes verwenden:

git checkout --ours -- path/to/file

Oder:

git checkout --theirs -- path/to/file

…während einer Zusammenführung oder Neubasierung, um eine bestimmte Version einer widersprüchlichen Datei auszuwählen; weil rebasing ist Ein bisschen komisch, --theirs in diesem Fall wäre feature‘s Version, --ours wäre master‘s.

  • Eigentlich du nicht müssen git add, da checkout “durch den Index” schreibt und die Our-or-theirs-Version in “Slot 0” im Index kopiert, bevor sie in den Arbeitsbaum geschrieben wird. (Tun git add ist aber harmlos.)

    – Torek

    31. Januar 2014 um 22:10 Uhr


  • Ach, tatsächlich? Ich dachte, ich hätte es auch inszenieren müssen, um es als Auflösung inszenieren zu lassen. Ich werde die Antwort aktualisieren, danke!

    – AshWilson

    31. Januar 2014 um 22:12 Uhr

Ich glaube, dass das, wonach Sie suchen, alle drei Schritte loswerden wird

git rebase master -X theirs

die automatisch Konflikte zugunsten von lösen wird feature (der aktuell ausgecheckte Zweig), oder

git rebase master -X ours

Der Sinn von ours und theirs ist als Argument für eine Rebasierung kontraintuitiv, wie in der Beschreibung der Option at angegeben http://git-scm.com/docs/git-rebase

  • Wenn es zwei widersprüchliche Dateien gibt, a.txt und b.txt, möchte ich möglicherweise a.txt aus dem Hauptzweig auswählen und b.txt möchte ich möglicherweise manuell zusammenführen. Werden die von Ihnen vorgeschlagenen Befehle auf alle widersprüchlichen Dateien angewendet?

    – ams

    31. Januar 2014 um 22:07 Uhr


  • In diesem Fall ist Ash Wilsons Antwort die richtige 🙂

    – GreenAsJade

    31. Januar 2014 um 22:09 Uhr

1439640cookie-checkWie wähle ich eine Datei aus einem Zweig aus, wenn ich einen Konflikt während der Git-Rebase auflöse?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy