Ich habe einen Zweig namens demo
, den ich mit dem Zweig master
zusammenführen muss. Mit folgenden Befehlen kann ich das gewünschte Ergebnis erzielen:
git pull Origin demo
git checkout master
git pull Origin master
git merge demo
git Push Origin master
Meine einzige Sorge ist, wenn es irgendwelche Zusammenführungsprobleme gibt, ich möchte git
anweisen, Änderungen in der master
-Verzweigung zu überschreiben, ohne mir die Aufforderung zum Zusammenführen zu geben. Änderungen im Zweig demo
sollten daher Änderungen im Zweig master
automatisch überschreiben.
Ich habe mich umgesehen, dass es mehrere Optionen gibt, aber ich möchte kein Risiko beim Zusammenführen eingehen.
Nicht wirklich mit dieser Antwort verwandt, aber ich würde git pull
Fallen lassen, das nur git fetch
Gefolgt von git merge
Ausführt. Sie führen drei Zusammenführungen durch, wodurch Ihr Git drei Abrufvorgänge ausführt, wenn Sie nur einen Abruf benötigen. Daher:
git fetch Origin # update all our Origin/* remote-tracking branches
git checkout demo # if needed -- your example assumes you're on it
git merge Origin/demo # if needed -- see below
git checkout master
git merge Origin/master
git merge -X theirs demo # but see below
git Push Origin master # again, see below
Der interessanteste Teil hier ist git merge -X theirs
. Als root545 notiert werden die Optionen -X
An die Zusammenführungsstrategie und sowohl die Standardstrategie recursive
als auch die Alternativstrategie resolve
übergeben nimm -X ours
oder -X theirs
(das eine oder andere, aber nicht beide). Um zu verstehen, was sie tun, müssen Sie wissen, wie Git Konflikte findet und behandelt .
In einigen Dateien kann ein Zusammenführungskonflikt auftreten1 wenn sich die Basisversion von der aktuellen Version (auch als lokal, HEAD oder --ours
bezeichnet) unterscheidet und die andere (auch remote oder --theirs
genannte) Version derselben Datei. Das heißt, der Zusammenschluss hat drei Revisionen (drei Commits) identifiziert: base, our und their. Die "Basis" -Version ist von der Merge-Basis zwischen unserem Commit und ihrem Commit, wie im Commit-Diagramm zu sehen (mehr dazu in anderen StackOverflow-Beiträgen). Git hat dann zwei Arten von Änderungen gefunden: "Was wir getan haben" und "Was sie getan haben". Diese Änderungen werden (im Allgemeinen) zeilenweise auf rein textueller Basis vorgenommen. Git hat kein wirkliches Verständnis für den Inhalt von Dateien. es wird lediglich jede Textzeile verglichen.
Diese Änderungen werden in der Ausgabe von git diff
Angezeigt und haben wie immer auch den Kontext . Es ist möglich, dass Dinge, die wir geändert haben, sich in einer anderen Zeile befinden als Dinge, die sie geändert haben, so dass die Änderungen nicht kollidieren, sondern sich auch der Kontext geändert hat (z. B. weil sich unsere Änderung am oberen oder unteren Rand der Datei befindet, Damit die Datei in unserer Version nicht mehr angezeigt wird, haben sie oben oder unten mehr Text hinzugefügt.
Wenn die Änderungen in verschiedenen Zeilen vorkommen, ändern wir beispielsweise color
in colour
in Zeile 17 und sie ändern fred
bis barney
in Zeile 71 - dann liegt kein Konflikt vor: Git nimmt einfach beide Änderungen an. Wenn die Änderungen in denselben Zeilen erfolgen, aber identische Änderungen sind, nimmt Git eine Kopie der Änderung. Nur wenn sich die Änderungen in derselben Zeile befinden, sich jedoch in unterschiedlichen Änderungen befinden oder wenn es sich um einen Sonderfall handelt, bei dem der Kontext gestört wird, tritt ein Konflikt zwischen Ändern und Ändern auf.
Die Optionen -X ours
Und -X theirs
Teilen Git mit, wie dieser Konflikt gelöst werden kann, indem nur eine der beiden Änderungen ausgewählt wird: unsere oder ihre. Da Sie sagten, Sie mischen demo
(ihre) mit master
(unsere) und möchten die Änderungen von demo
, möchten Sie -X theirs
.
Das blinde Anwenden von -X
Ist jedoch gefährlich. Nur weil unsere Änderungen nicht Zeile für Zeile in Konflikt standen, heißt das nicht, dass unsere Änderungen tatsächlich nicht in Konflikt standen! Ein klassisches Beispiel findet sich in Sprachen mit Variablendeklarationen. Die Basisversion deklariert möglicherweise eine nicht verwendete Variable:
int i;
In unserer Version löschen wir die nicht verwendete Variable, damit eine Compiler-Warnung verschwindet. In ihrer Version fügen sie einige Zeilen später eine Schleife hinzu und verwenden dabei i
. als Schleifenzähler. Wenn wir die beiden Änderungen kombinieren, wird der resultierende Code nicht mehr kompiliert. Die Option -X
Ist hier keine Hilfe, da sich die Änderungen in verschiedenen Zeilen befinden.
Wenn Sie über eine automatisierte Testsuite verfügen, ist es am wichtigsten, die Tests nach dem Zusammenführen auszuführen. Sie können dies nach dem Festschreiben tun und die Probleme bei Bedarf später beheben. oder Sie können dies vor dem Festschreiben tun, indem Sie --no-commit
zum Befehl git merge
hinzufügen. Die Details dazu überlassen wir anderen Beiträgen.
1Sie können auch Konflikte in Bezug auf "dateiweite" Vorgänge bekommen, z. B. wenn wir die Schreibweise eines Wortes in einer Datei korrigieren (damit wir eine Änderung haben) und sie löschen die gesamte Datei (damit sie einen Löschvorgang haben). Git wird diese Konflikte unabhängig von -X
- Argumenten nicht alleine lösen.
Es gibt drei Zusammenführungen in unseren beiden Befehlssequenzen. Das erste ist, Origin/demo
In das lokale demo
zu bringen (Ihr verwendet git pull
, Das, wenn Ihr Git sehr alt ist, Origin/demo
Aber nicht aktualisieren kann wird das gleiche Endergebnis erzeugen). Die zweite ist, Origin/master
In master
zu bringen.
Mir ist nicht klar, wer demo
und/oder master
aktualisiert. Wenn Sie Ihren eigenen Code in Ihrem eigenen demo
-Zweig schreiben, schreiben und andere Code und verschieben ihn in den demo
-Zweig in Origin
, dann kann diese Zusammenführung im ersten Schritt Konflikte verursachen oder eine echte Zusammenführung hervorrufen. In den meisten Fällen ist es besser, die Arbeit mithilfe von Rebase zu kombinieren, als sie zusammenzuführen (zugegebenermaßen ist dies eine Frage des Geschmacks und der Meinung). In diesem Fall möchten Sie möglicherweise stattdessen git rebase
Verwenden. Wenn Sie jedoch niemals eigene Commits für demo
ausführen, benötigen Sie nicht einmal einen demo
-Zweig . Alternativ können Sie git merge --ff-only Origin/demo
Verwenden, wenn Sie vieles davon automatisieren möchten, aber sorgfältig prüfen können, ob es Commits gibt, die sowohl Sie als auch andere vorgenommen haben. Dadurch wird Ihr demo
, um den aktualisierten Origin/demo
- Wert nach Möglichkeit zu ermitteln. Andernfalls schlägt dies einfach fehl (an diesem Punkt können Sie die beiden Änderungssätze überprüfen und gegebenenfalls eine echte Zusammenführung oder eine erneute Basis auswählen).
Dieselbe Logik gilt für master
, obwohl Sie die Zusammenführung für master
durchführen, sodass Sie definitiv eine master
. Es ist jedoch noch wahrscheinlicher, dass Sie möchten, dass die Zusammenführung fehlschlägt, wenn sie nicht als Nichtzusammenführung im Schnellvorlauf ausgeführt werden kann. Daher sollte dies wahrscheinlich auch git merge --ff-only Origin/master
Sein.
Nehmen wir an, Sie machen niemals eigene Commits für demo
. In diesem Fall können wir den Namen demo
komplett weglassen:
git fetch Origin # update Origin/*
git checkout master
git merge --ff-only Origin/master || die "cannot fast-forward our master"
git merge -X theirs Origin/demo || die "complex merge conflict"
git Push Origin master
Wenn Sie eigene demo
-Verzweigungs-Commits ausführen , ist dies nicht hilfreich. Sie können auch die vorhandene Zusammenführung beibehalten (aber je nach gewünschtem Verhalten --ff-only
hinzufügen) oder eine Neuzusammenführung durchführen. Beachten Sie, dass alle drei Methoden fehlschlagen können: Zusammenführen schlägt möglicherweise mit einem Konflikt fehl, Zusammenführen mit --ff-only
Kann möglicherweise nicht schnell vorwärts ausgeführt werden, und erneutes Ausführen schlägt möglicherweise mit einem Konflikt fehl (erneutes Ausführen funktioniert im Wesentlichen mit Cherry-Picking Commits, die die Merge-Maschinerie verwenden und daher einen Merge-Konflikt verursachen können).
Sie können "unsere" Option in Git Merge versuchen,
git merge branch -X ours
Diese Option erzwingt eine automatische Bereinigung widersprüchlicher Hunks, indem unsere Version bevorzugt wird. Änderungen von dem anderen Baum, die nicht mit unserer Seite in Konflikt stehen, werden in das Zusammenführungsergebnis übernommen. Bei einer Binärdatei wird der gesamte Inhalt von unserer Seite übernommen.
Ich hatte ein ähnliches Problem, bei dem ich alle Dateien, die Änderungen/Konflikte mit einem anderen Zweig aufwiesen, effektiv ersetzen musste.
Die Lösung, die ich gefunden habe, war die Verwendung von git merge -s ours branch
.
Beachten Sie, dass die Option -s
Und nicht -X
Ist. -s
Bezeichnet die Verwendung von ours
als Mergestrategie der obersten Ebene. -X
Würde die Option ours
auf die Mergestrategie recursive
anwenden , was ich (oder wir) in diesem Fall nicht wollen.
Schritte, bei denen oldbranch
der Zweig ist, den Sie mit newbranch
überschreiben möchten.
git checkout newbranch
Checkt den Zweig aus, den Sie behalten möchtengit merge -s ours oldbranch
Wird im alten Zweig zusammengeführt, behält aber alle unsere Dateien bei.git checkout oldbranch
Checkt den Zweig aus, den Sie überschreiben möchtenget merge newbranch
Wird im neuen Zweig zusammengeführt und überschreibt den alten Zweig