1141 Stimmen

Gibt es eine "ihre" Version von "git merge -s unsere"?

Beim Zusammenführen des Themenzweigs "B" in "A" unter Verwendung von git merge bekomme ich einige Konflikte. Ich weiß, dass alle Konflikte mit der Version in "B" gelöst werden können.

Ich bin mir bewusst, dass git merge -s ours . Aber was ich will, ist etwas wie git merge -s theirs .

Warum gibt es sie nicht? Wie kann ich das gleiche Ergebnis nach der kollidierenden Zusammenführung mit bestehenden git Befehle? ( git checkout jede nicht gemischte Datei von B)

Die "Lösung", einfach alles aus Zweig A (dem Punkt der Zusammenführungsübergabe an die Version B des Baums) zu verwerfen, ist nicht das, wonach ich suche.

1 Stimmen

Siehe auch diese Antwort: stackoverflow.com/questions/928646/ - ist es trivial, das Beispiel so zu ändern, dass Version B anstelle von A verwendet wird.

13 Stimmen

Siehe Antwort SO git-Befehl, um einen Zweig wie einen anderen zu machen pour todo die derzeitigen Möglichkeiten, um simulieren. git merge -s their .

6 Stimmen

Sie sind also nicht wirklich auf der Suche nach einem git merge -s theirs (das lässt sich leicht erreichen mit git merge -s ours und einem temporären Zweig), da unser -s die Änderungen des merge-from-Zweigs komplett ignoriert...

1302voto

Alan W. Smith Punkte 23071

Eine ähnliche Alternative ist die --strategy-option (Kurzform -X ), die die Option theirs . Zum Beispiel:

git checkout branchA
git merge -X theirs branchB

Dies ist jedoch eher gleichbedeutend mit -X ours als -s ours . Der Hauptunterschied besteht darin, dass -X führt eine reguläre rekursive Zusammenführung durch und löst alle Konflikte mit der gewählten Seite auf, während -s ours ändert die Verschmelzung so, dass die andere Seite einfach völlig ignoriert wird.

In einigen Fällen ist das Hauptproblem bei der -X theirs anstelle des hypothetischen -s theirs sind gelöschte Dateien. In diesem Fall führen Sie einfach git rm mit den Namen der gelöschten Dateien:

git rm {DELETED-FILE-NAME}

Danach wird die -X theirs kann wie erwartet funktionieren.

Natürlich ist die eigentliche Entfernung mit dem git rm Der Befehl verhindert, dass der Konflikt überhaupt entsteht.

7 Stimmen

Siehe andere Antwort unten für eine bessere Lösung (Paul Pladijs) auf die ursprüngliche Frage.

260 Stimmen

Es ist zu beachten, dass dies nicht dasselbe ist wie "Merge-Strategie theirs ". -Xtheirs ist die Strategie Option angewendet auf rekursive Strategie . Das bedeutet, dass die rekursive Strategie immer noch alles zusammenführt, was sie kann, und nur im Falle von Konflikten auf "ihre" Logik zurückgreift. Auch wenn dies in den meisten Fällen wie oben der Fall ist, ist dies nicht dasselbe wie "einfach alles aus Zweig B übernehmen, wie es ist". Es führt stattdessen die eigentliche Zusammenführung durch.

2 Stimmen

Es funktioniert auch mit anderen Befehlen. Ich habe gerade ein "git cherry-pick sha1 -X theirs" ausgeführt. Danke!

263voto

Paul Pladijs Punkte 16370

Eine mögliche und getestete Lösung für das Zusammenführen von ZweigB mit unserem ausgecheckten ZweigA:

# in case branchA is not our current branch
git checkout branchA

# make merge commit but without conflicts!!
# the contents of 'ours' will be discarded later
git merge -s ours branchB    

# make temporary branch to merged commit
git branch branchTEMP         

# get contents of working tree and index to the one of branchB
git reset --hard branchB

# reset to our merged commit but 
# keep contents of working tree and index
git reset --soft branchTEMP

# change the contents of the merged commit
# with the contents of branchB
git commit --amend

# get rid off our temporary branch
git branch -D branchTEMP

# verify that the merge commit contains only contents of branchB
git diff HEAD branchB

Um es zu automatisieren, können Sie es in ein Skript packen und branchA und branchB als Argumente verwenden.

Bei dieser Lösung bleiben das erste und zweite Elternteil der Zusammenführungsübergabe erhalten, genau wie man es von git merge -s theirs branchB .

0 Stimmen

F: Warum brauchen Sie branchTEMP? Könnten Sie nicht einfach git reset --soft branchA ?

4 Stimmen

@cdunn2001: Irgendwie dachte ich das Gleiche, aber nein. Beachte das git reset --hard Änderungen, die verbindlich sind branchA zeigt auf.

0 Stimmen

@tsuyoshi-ito: Ich verstehe. Stimmt. Aber die ganze Sache ist einfacher, wenn Sie einfach zusammenführen branchA in branchB . Es ist einfach, A vorzuspulen und B zurückzusetzen, falls gewünscht. Der einzige Nachteil ist, dass ^ y ^^ umgedreht werden würde. Mir gefällt die Antwort von Shyam aquí .

102voto

Pat Notz Punkte 196406

Ältere Versionen von git erlaubten die Verwendung der "theirs"-Merge-Strategie:

git pull --strategy=theirs remote_branch

Dies wurde jedoch inzwischen entfernt, wie in dieser Nachricht von Junio Hamano (der Git-Maintainer). Wie in dem Link erwähnt, würden Sie stattdessen dies tun:

git fetch origin
git reset --hard origin

Beachten Sie jedoch, dass dies etwas anderes ist als eine tatsächliche Zusammenführung. Ihre Lösung ist wahrscheinlich die Option, nach der Sie wirklich suchen.

0 Stimmen

Danke, ich bin nicht ganz zufrieden mit meiner Antwort aber, es fehlte das Auschecken von anderen Dateien in alt. es war ungerade, ich fügen Sie checkout sie... zu begehen - ändern Sie dann.

13 Stimmen

Ich verstehe die Erklärung von Junio Hamano überhaupt nicht. Wie ist git reset --hard origin eine Lösung für eine Zusammenführung im Stil von theirs? Wenn ich ZweigB in ZweigA zusammenführen möchte (wie in der Antwort von Alan W. Smith), wie würde ich das mit dem reset Methode?

5 Stimmen

@James McMahon: Junio C Hamanos Argument ist nicht git reset --hard führt eine Zusammenführung im Stil von "theirs" durch. Ja, natürlich, git reset --hard erzeugt keinen Merge-Commit oder überhaupt einen Commit. Sein Punkt ist, dass wir sollten keine Zusammenführung verwenden das, was in HEAD steht, durch etwas anderes zu ersetzen. Ich bin allerdings nicht unbedingt einverstanden.

101voto

siegi Punkte 5139

Es ist nicht ganz klar, was das gewünschte Ergebnis ist, so dass in den Antworten und Kommentaren eine gewisse Verwirrung über die "richtige" Vorgehensweise herrscht. Ich versuche, einen Überblick zu geben und sehe die folgenden drei Möglichkeiten:

Versuchen Sie die Zusammenführung und verwenden Sie B für Konflikte

Dies ist pas die "ihre Version für git merge -s ours ", sondern die "ihre Version für git merge -X ours "(das ist die Abkürzung für git merge -s recursive -X ours ) :

git checkout branchA
# also uses -s recursive implicitly
git merge -X theirs branchB

Dies ist z. B. der Fall. Alan W. Smiths Antwort tut.

Nur Inhalte aus B verwenden

Dies erzeugt einen Merge Commit für beide Zweige, verwirft aber alle Änderungen aus branchA und behält nur die Inhalte von branchB .

# Get the content you want to keep.
# If you want to keep branchB at the current commit, you can add --detached,
# else it will be advanced to the merge commit in the next step.
git checkout branchB

# Do the merge an keep current (our) content from branchB we just checked out.
git merge -s ours branchA

# Set branchA to current commit and check it out.
git checkout -B branchA

Beachten Sie, dass der erste übergeordnete Merge-Commit nun derjenige von branchB und nur der zweite ist von branchA . Das ist es, was z.B. Gandalf458's Antwort tut.

Verwenden Sie nur den Inhalt von B und behalten Sie die korrekte Reihenfolge der Eltern bei.

Dies ist die echte "ihre Version für git merge -s ours ". Sie hat den gleichen Inhalt wie die vorherige Option (d. h. nur den von branchB ), aber die Reihenfolge der Eltern ist korrekt, d. h. der erste Elternteil stammt von branchA und die zweite von branchB .

git checkout branchA

# Do a merge commit. The content of this commit does not matter,
# so use a strategy that never fails.
# Note: This advances branchA.
git merge -s ours branchB

# Change working tree and index to desired content.
# --detach ensures branchB will not move when doing the reset in the next step.
git checkout --detach branchB

# Move HEAD to branchA without changing contents of working tree and index.
git reset --soft branchA

# 'attach' HEAD to branchA.
# This ensures branchA will move when doing 'commit --amend'.
git checkout branchA

# Change content of merge commit to current index (i.e. content of branchB).
git commit --amend -C HEAD

Das ist es, was Paul Pladijs' Antwort tut (ohne dass eine temporäre Verzweigung erforderlich ist).

Besondere Fälle

Wenn die Übergabe von branchB ist ein Vorfahre von branchA , git merge funktioniert nicht (er beendet sich mit einer Meldung wie " Bereits auf dem neuesten Stand. ").

In diesem oder anderen ähnlichen/erweiterten Fällen kann der Low-Level-Befehl git commit-tree verwendet werden können.

3 Stimmen

Eine sauberere Version von Option 3: git checkout branchA; git merge -s ours --no-commit branchB; git read-tree -um @ branchB; git commit

0 Stimmen

@jthill: Ihre Version ist zwar prägnanter, verwendet aber auch den Low-Level-Befehl ("plumbing") read-tree die der durchschnittliche Git-Benutzer vielleicht nicht gewohnt ist (zumindest bin ich das nicht ;-) ). Die Lösungen in der Antwort verwenden nur die High-Level-Befehle ("Porzellan"), die die meisten Git-Benutzer kennen sollten. Ich bevorzuge sie, aber ich danke Ihnen trotzdem für Ihre Version!

0 Stimmen

Können Sie den vorletzten Schritt (checkout branchA) erklären? Es scheint, als ob er dort nicht sein sollte.

73voto

musicmatze Punkte 3850

Ich verwende seither die Antwort von Paul Pladijs. Ich habe herausgefunden, dass man einen "normalen" Merge machen kann, Konflikte auftreten, also macht man

git checkout --theirs <file>

um den Konflikt durch Verwendung der Revision des anderen Zweigs zu lösen. Wenn Sie dies für jede Datei tun, haben Sie das gleiche Verhalten, wie Sie es von

git merge <branch> -s theirs

Auf jeden Fall ist der Aufwand größer als bei der Merge-Strategie! (Dies wurde mit Git Version 1.8.0 getestet)

1 Stimmen

Es wäre schön, wenn die Liste der Dateien abgerufen werden könnte. Zum Beispiel, git ls-files --modified | xargs git add Ich wollte dies tun, um auf beiden Seiten zu fusionieren :/

0 Stimmen

Eigentlich gibt git die auf beiden Seiten hinzugefügten Dateien mit git ls-files --modified Ich denke also, dass dies auch eine praktikable Lösung ist.

1 Stimmen

Danke, dass Sie auch dies hinzugefügt haben. Meistens wird es auf Dateibasis benötigt. Außerdem zeigt der Git-Status ganz unten "Unmerged Paths" an. Um die Liste der nicht aufgelösten Pfade zu erhalten, verwende ich diesen Alias: git config --global alias.unresolved '!git status --short|egrep "^([DAU])\1"'

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X