Nicht wirklich mit dieser Antwort verbunden, aber ich würde Graben git pull
, die nur läuft, git fetch
gefolgt von git merge
. Sie führen drei Zusammenführungen durch, wodurch Ihr Git drei Abrufvorgänge ausführt, wenn nur ein Abruf erforderlich ist. 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
Kontrolle der schwierigsten Zusammenführung
Der interessanteste Teil hier ist git merge -X theirs
. Wie root545 feststellte , werden die -X
Optionen an die Zusammenführungsstrategie weitergegeben, und sowohl die Standardstrategie recursive
als auch die alternative resolve
Strategie nehmen -X ours
oder -X theirs
(die eine oder andere, aber nicht beide). Um zu verstehen, was sie tun, müssen Sie jedoch wissen, wie Git Konflikte zusammenführt und behandelt .
Ein Zusammenführungskonflikt kann in einigen Dateien 1 auftreten, wenn sich die Basisversion sowohl von der aktuellen (auch als lokale, HEAD- oder --ours
) Version als auch von der anderen (auch als Remote- oder --theirs
) Version derselben Datei bezeichnet wird, unterscheidet. Das heißt, bei der Zusammenführung wurden drei Revisionen (drei Commits) identifiziert: Base, unsere und ihre. Die "Basis" -Version stammt aus der Zusammenführungsbasis zwischen unserem Commit und ihrem Commit, wie im Commit-Diagramm angegeben (mehr dazu in anderen StackOverflow-Postings). Git hat dann zwei Arten von Änderungen gefunden: "Was wir getan haben" und "Was sie getan haben". Diese Änderungen werden (im Allgemeinen) zeilenweise rein textuell gefundenBasis. Git hat kein wirkliches Verständnis für Dateiinhalte; es wird lediglich jede Textzeile verglichen.
Diese Änderungen werden in der git diff
Ausgabe angezeigt und haben wie immer auch einen Kontext . Es ist möglich, dass Dinge, die wir geändert haben, in anderen Zeilen stehen als Dinge, die sie geändert haben, so dass die Änderungen so aussehen, als würden sie nicht kollidieren, aber der Kontext hat sich auch geändert (z. B. weil sich unsere Änderung am oberen oder unteren Rand der Datei befindet). Damit die Datei in unserer Version ausgeht, haben sie in ihrer Version auch oben oder unten mehr Text hinzugefügt.
Wenn die Änderungen in verschiedenen Zeilen erfolgen - zum Beispiel color
in colour
Zeile 17 und fred
in barney
Zeile 71 -, besteht kein Konflikt: Git übernimmt einfach beide Änderungen. 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, es sich jedoch um unterschiedliche Änderungen handelt oder wenn es sich um einen speziellen Fall eines störenden Kontexts handelt, wird ein Änderungs- / Änderungskonflikt angezeigt.
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 verschmelzen demo
(ihre) mit master
(unseren) und möchten die Änderungen von demo
, möchten Sie -X theirs
.
Das blinde Auftragen -X
ist jedoch gefährlich. Nur weil unsere Änderungen nicht zeilenweise in Konflikt standen, heißt das nicht, dass unsere Änderungen nicht tatsächlich in Konflikt stehen! Ein klassisches Beispiel sind 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 sie i
als Schleifenzähler. Wenn wir die beiden Änderungen kombinieren, wird der resultierende Code nicht mehr kompiliert. Die -X
Option ist hier keine Hilfe, da sich die Änderungen in verschiedenen Zeilen befinden .
Wenn Sie über eine automatisierte Testsuite verfügen, müssen Sie die Tests nach dem Zusammenführen am wichtigsten ausführen. Sie können dies nach dem Festschreiben tun und die Probleme später bei Bedarf beheben. oder Sie können dies vor dem Festschreiben tun , indem Sie --no-commit
dem git merge
Befehl hinzufügen . Wir werden die Details für all dies anderen Postings überlassen.
1 Sie können auch Konflikte in Bezug auf "dateiweite" Operationen bekommen, z. B. korrigieren wir möglicherweise die Schreibweise eines Wortes in einer Datei (damit wir eine Änderung haben) und sie löschen die gesamte Datei (so dass sie eine haben) löschen). Git wird diese Konflikte unabhängig von den -X
Argumenten nicht alleine lösen .
Weniger Zusammenführungen und / oder intelligentere Zusammenführungen durchführen und / oder Rebase verwenden
In unseren beiden Befehlssequenzen gibt es drei Zusammenführungen. Das erste ist, origin/demo
in die lokale zu bringen demo
(Ihre Verwendungen, git pull
die, wenn Ihr Git sehr alt ist, nicht aktualisiert origin/demo
werden können, aber das gleiche Endergebnis erzeugen). Das zweite ist , zu bringen origin/master
in master
.
Mir ist nicht klar, wer aktualisiert demo
und / oder master
. Wenn Sie Ihren eigenen Code in Ihren eigenen demo
Zweig schreiben und andere Code schreiben und in den demo
Zweig verschieben origin
, kann diese Zusammenführung im ersten Schritt zu Konflikten führen oder eine echte Zusammenführung bewirken. Meistens ist es besser, Rebase zu verwenden, als zusammenzuführen, um Arbeit zu kombinieren (zugegebenermaßen ist dies eine Frage des Geschmacks und der Meinung). In diesem Fall möchten Sie möglicherweise git rebase
stattdessen verwenden. Auf der anderen Seite, wenn Sie noch nie auf einem Ihren eigenen Commits tun demo
, tun Sie nicht einmal brauchen einen demo
Zweig. Wenn Sie alternativ viel davon automatisieren möchten, aber sorgfältig prüfen können, ob Commits vorliegen, die sowohl Sie als auch andere vorgenommen haben, möchten Sie diese möglicherweise verwendengit merge --ff-only origin/demo
: Dies spult Sie schnell vor demo
, um mit den aktualisierten origin/demo
Daten übereinzustimmen, wenn dies möglich ist, und schlägt einfach fehl, wenn nicht (an diesem Punkt können Sie die beiden Änderungssätze überprüfen und je nach Bedarf eine echte Zusammenführung oder eine Neuausrichtung auswählen).
Die gleiche Logik gilt für master
, obwohl Sie den merge tun auf master
, so dass Sie auf jeden Fall ein brauchen master
. Es ist jedoch noch wahrscheinlicher, dass die Zusammenführung fehlschlagen soll, wenn sie nicht als Nicht-Zusammenführung im Schnellvorlauf durchgeführt werden kann git merge --ff-only origin/master
. Dies sollte also wahrscheinlich auch so sein .
Nehmen wir an, Sie machen niemals Ihre eigenen Verpflichtungen demo
. In diesem Fall können wir den Namen demo
ganz fallen lassen:
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 sich Ihr eigenes tun demo
Zweig Commits, ist dies nicht hilfreich; Sie können die vorhandene Zusammenführung auch --ff-only
beibehalten (aber je nach gewünschtem Verhalten hinzufügen ) oder auf eine Neueinstellung umstellen. Beachten Sie, dass alle drei Methoden möglicherweise fehlschlagen: Das Zusammenführen kann mit einem Konflikt fehlschlagen, das Zusammenführen mit --ff-only
kann möglicherweise nicht schnell vorgespult werden, und das erneute Basieren kann mit einem Konflikt fehlschlagen (das erneute Basieren funktioniert im Wesentlichen durch Cherry-Picking- Commits, bei denen das Zusammenführen verwendet wird Maschinen und können daher einen Zusammenführungskonflikt bekommen).
git push -f origin master