Was ist die genaue Bedeutung von "uns" und "ihnen" in git?

323

Das klingt vielleicht zu einfach für eine Frage, aber ich habe nach Antworten gesucht und bin jetzt verwirrter als zuvor.

Was bedeuten "unsere" und "ihre" in git, wenn mein Zweig mit meinem anderen Zweig zusammengeführt wird? Beide Niederlassungen sind "unsere".

Wird bei einem Zusammenführungskonflikt "unsere" immer die obere der beiden angezeigten Versionen angezeigt?

Bezieht sich "unsere" immer auf den Zweig, auf den HEAD zu Beginn der Zusammenführung zeigte? Wenn ja, warum nicht eine eindeutige Possessivreferenz wie "aktuelle Zweige" verwenden, anstatt ein Possessivpronomen wie "unsere" zu verwenden, das referenziell mehrdeutig ist (da beide Zweige technisch unsere sind)?

Oder verwenden Sie einfach den Filialnamen (anstatt "unser" zu sagen, sagen Sie einfach "lokaler Master" oder so)?

Der verwirrendste Teil für mich ist, wenn ich in der .gitattributes-Datei eines bestimmten Zweigs spezifiziere. Nehmen wir an , ich habe im Testzweig die folgende .gitattributes-Datei:

config.xml merge=ours

Jetzt checke ich aus und zeige HEAD auf Master, um es dann im Test zusammenzuführen . Da Master bei uns, und ist Test ‚ist s .gitattributes nicht ausgecheckt, wird es auch eine Wirkung haben? Wenn es eine Wirkung hat, da der Meister jetzt "unser" ist, was wird dann passieren?

CommaToast
quelle

Antworten:

374

Ich vermute, Sie sind hier verwirrt, weil es grundsätzlich verwirrend ist. Um die Sache noch schlimmer zu machen, wechselt unser gesamtes Zeug die Rollen (wird rückwärts), wenn Sie eine Rebase durchführen.

Letztlich während ein git merge, bezieht sich der „unsere“ Zweig mit dem Zweig Sie verschmelzen in :

git checkout merge-into-ours

und der Zweig "ihnen" bezieht sich auf den (einzelnen) Zweig, den Sie zusammenführen:

git merge from-theirs

und hier machen "unsere" und "ihre" einen Sinn, denn obwohl "ihre" wahrscheinlich sowieso deine sind, ist "ihre" nicht die, auf der du warst, als du gelaufen bist git merge.

Die Verwendung des tatsächlichen Zweignamens mag zwar ziemlich cool sein, fällt jedoch in komplexeren Fällen auseinander. Anstelle der oben genannten Schritte können Sie beispielsweise Folgendes tun:

git checkout ours
git merge 1234567

wo Sie durch rohe Commit-ID zusammenführen. Schlimmer noch, Sie können dies sogar tun:

git checkout 7777777    # detach HEAD
git merge 1234567       # do a test merge

In diesem Fall sind keine Filialnamen beteiligt!

Ich denke, es ist hier wenig hilfreich, aber tatsächlich können Sie in der gitrevisionsSyntax während einer Konfliktzusammenführung auf einen einzelnen Pfad im Index nach Zahlen verweisen

git show :1:README
git show :2:README
git show :3:README

Stufe 1 ist der gemeinsame Vorfahr der Dateien, Stufe 2 ist die Zielverzweigungsversion und Stufe 3 ist die Version, aus der Sie zusammenführen.


Der Grund, warum die Begriffe "unsere" und "ihre" rebasewährenddessen ausgetauscht werden, ist, dass die Rebase durch eine Reihe von Cherry-Picks in einen anonymen Zweig (getrennter HEAD-Modus) funktioniert. Der Zielzweig ist der anonyme Zweig, und der Merge-from-Zweig ist Ihr ursprünglicher Zweig (vor dem Rebase). "--Ours" bedeutet also, dass der anonyme Rebase erstellt wird, während "--theirs" bedeutet, dass "unser Zweig neu basiert". .


Was den Eintrag gatattributes betrifft: Es könnte einen Effekt haben: "unser" bedeutet wirklich "Stufe 2 intern verwenden". Aber wie Sie bemerken, ist es zu diesem Zeitpunkt noch nicht vorhanden, daher sollte es hier keine Auswirkungen haben ... nun, es sei denn, Sie kopieren es in den Arbeitsbaum, bevor Sie beginnen.

Dies gilt übrigens auch für alle Verwendungszwecke von uns und von ihnen, aber einige befinden sich auf der Ebene einer ganzen Datei ( -s oursfür eine Zusammenführungsstrategie; git checkout --ourswährend eines Zusammenführungskonflikts) und einige sind Stück für Stück ( -X oursoder -X theirswährend eines Zusammenführungskonflikts)-s recursive verschmelzen). Was wahrscheinlich bei keiner Verwirrung hilft.

Ich habe mir jedoch nie einen besseren Namen dafür ausgedacht. Und: siehe VonCs Antwort auf eine andere Frage, in git mergetoolder noch weitere Namen für diese eingeführt werden, die als "lokal" und "fern" bezeichnet werden!

torek
quelle
28
+1. Informationen darüber, wie unsere und ihre während der Rebase rückgängig gemacht werden, finden Sie auch unter: stackoverflow.com/a/2960751/6309 und stackoverflow.com/a/3052118/6309
VonC
1
Zwei Dinge "verschmelzen" miteinander. Wenn eine Zusammenführung stattfindet, verschmelzen beide Seiten "in "einander. Ich halte es für falsch zu sagen, dass eine der beiden Seiten "nicht in irgendetwas verschmilzt". Wenn keine Zweigstellennamen beteiligt sind (wie Sie hervorheben), handelt es sich um Festschreibungsnamen (Sie könnten "7777777" und "1234567" anstelle von "unsere" und "ihre" sagen). Ich verstehe, was während einer Rebase passiert, und finde es überhaupt nicht verwirrend. Ich denke, "HEAD's" und "Incoming's" würden besser funktionieren als "unsere" und "ihre", weil es immer einen "HEAD" gibt (ob losgelöst oder nicht).
CommaToast
15
Ich denke, da der Kopf der Sitz des Geistes ist, der die Quelle der Identität ist, der die Quelle des Selbst ist, ist es ein bisschen sinnvoller, sich das, worauf HEAD hinweist, als "mein" ("unser", seitdem) vorzustellen Ich denke ich und der KOPF macht zwei). Wenn nicht mehr, ist das nur ein gutes Gedächtnisgerät.
CommaToast
1
Davon abgesehen mache ich immer noch gerne eine physische Kopie des gesamten Repos, bevor ich etwas wie eine Neugründung mache ...: D
CommaToast
3
"In diesem Fall sind keine Zweigstellennamen beteiligt!" ... Daher sollte stattdessen der Commit-Kommentar / Hash verwendet werden. Was auch immer es in die Hände bekommen kann. Praktisch alles wäre besser als "unser" und "ihr". Ich frage mich, wie viele tausend Entwicklungsstunden diese Verwirrung verflogen ist. gits Antwort auf C ++ 's "ärgerlichste Analyse";)
Jarrod Smith
49

Das ' unsere ' in Git bezieht sich auf den ursprünglichen Arbeitszweig, der einen maßgeblichen / kanonischen Teil der Git-Geschichte hat.

Das " ihre " bezieht sich auf die Version, die das Werk enthält, um neu basiert zu werden (Änderungen, die auf dem aktuellen Zweig wiedergegeben werden sollen).

Dies scheint auf Personen übertragen zu werden, die sich nicht bewusst sind, dass das Umbasieren (z. B. git rebase) Ihre Arbeit tatsächlich auf Eis legt ( was ihnen gehört ), um die kanonische / Hauptgeschichte, die uns gehört , erneut abzuspielen, weil wir unsere umbasieren Änderungen als Arbeit von Drittanbietern.

Die Dokumentation für git-checkoutwurde in Git> = 2.5.1 gemäß f303016Commit weiter präzisiert :

--ours --theirs

Überprüfen Sie beim Auschecken von Pfaden aus dem Index Stufe 2 ('unsere') oder Nr. 3 ('ihre') auf nicht zusammengeführte Pfade.

Beachten Sie, dass während git rebaseund git pull --rebase'unsere' und 'ihre' möglicherweise getauscht erscheinen. --oursGibt die Version aus dem Zweig an, auf die die Änderungen neu basiert, während --theirsdie Version aus dem Zweig angegeben wird, der Ihre Arbeit enthält, die neu basiert wird.

Dies liegt daran rebase, dass in einem Workflow verwendet wird, der den Verlauf auf der Fernbedienung als gemeinsam genutzten kanonischen behandelt und die Arbeit in dem Zweig, den Sie neu gründen, als zu integrierende Drittanbieterarbeit behandelt, und Sie vorübergehend die Rolle von übernehmen der Hüter der kanonischen Geschichte während der Rebase. Als Bewahrer der kanonischen Geschichte müssen Sie die Geschichte von der Ferne als ours(dh "unsere gemeinsame kanonische Geschichte") anzeigen , während das, was Sie auf Ihrer Seite getan haben, als theirs(dh "die Arbeit eines Mitwirkenden darüber").

Denn git-mergees wird folgendermaßen erklärt:

unsere

Diese Option erzwingt, dass widersprüchliche Hunks automatisch automatisch aufgelöst werden, indem unsere Version bevorzugt wird. Änderungen gegenüber dem anderen Baum, die nicht mit unserer Seite in Konflikt stehen, werden im Zusammenführungsergebnis berücksichtigt. Bei einer Binärdatei wird der gesamte Inhalt von unserer Seite übernommen.

Dies sollte nicht mit unserer Zusammenführungsstrategie verwechselt werden, bei der nicht einmal berücksichtigt wird, was der andere Baum überhaupt enthält. Es verwirft alles, was der andere Baum getan hat, und erklärt, dass unsere Geschichte alles enthält, was darin passiert ist.

ihre

Dies ist das Gegenteil von uns.

Außerdem wird hier erklärt, wie man sie benutzt:

Der Zusammenführungsmechanismus ( git mergeund die git pullBefehle) ermöglichen die Auswahl der Backend-Zusammenführungsstrategien mit -sOption. Einige Strategien können auch ihre eigenen Optionen wählen, die durch -X<option>Argumente an git mergeund / oder übergeben werden können git pull.


So kann es manchmal verwirrend sein, zum Beispiel:

  • git pull origin masterWo -Xoursist unsere lokale, -Xtheirsist ihre (entfernte) Niederlassung
  • git pull origin master -rWo -Xoursist ihre (abgelegen), -Xtheirsist unsere

Das zweite Beispiel ist also dem ersten entgegengesetzt, da wir unseren Zweig über dem entfernten neu aufbauen, sodass unser Ausgangspunkt der entfernte ist und unsere Änderungen als extern behandelt werden.

Ähnliches gilt für git mergeStrategien ( -X oursund -X theirs).

Kenorb
quelle
2
Diese Antwort scheint veraltet zu sein => "git merge --ours" ist keine gültige Option
Alexander Mills
@AlexanderMills Die Antwort sprach nicht darüber git merge, aber git pullund git checkoutals Beispiel. Wenn Sie diesen Parameter mit verwenden möchten git merge, sollten Sie verwenden -X ours. Sie können weiterhin die --oursSyntax für verwenden git checkout. Ich habe die Antwort weiter geklärt.
Kenorb
46

Ich weiß, dass dies beantwortet wurde, aber dieses Problem hat mich so oft verwirrt, dass ich eine kleine Referenz-Website eingerichtet habe, um mich daran zu erinnern: https://nitaym.github.io/ourstheirs/

Hier sind die Grundlagen:

Zusammenführungen:

$ git checkout master 
$ git merge feature

Wenn Sie die Version auswählen möchten in master:

$ git checkout --ours codefile.js

Wenn Sie die Version auswählen möchten in feature:

$ git checkout --theirs codefile.js

Rebases:

$ git checkout feature 
$ git rebase master 

Wenn Sie die Version auswählen möchten in master:

$ git checkout --ours codefile.js

Wenn Sie die Version auswählen möchten in feature:

$ git checkout --theirs codefile.js

(Dies ist natürlich für vollständige Dateien)

Nitay
quelle
1
Diese Website ist sehr hilfreich. Der Flussdiagrammstil und die farbcodierten Wörter machen die Website viel einfacher zu verstehen als die SO-Antworten. Vielen Dank.
Ron
10
  • Unsere : Dies ist der Zweig, in dem Sie sich gerade befinden.
  • Ihre : Dies ist der andere Zweig, der in Ihrer Aktion verwendet wird.

Also , wenn Sie auf dem Zweig Release / 2.5 und Sie fusionieren Zweig Funktion / new-Tasten hinein, dann den Inhalt wie in gefunden Release / 2.5 ist das, was uns betrifft und den Inhalt als auch gefunden Funktion / new-Tasten ist das, was ihnen bezieht sich zu. Während einer Zusammenführungsaktion ist dies ziemlich einfach.

Das einzige Problem, auf das die meisten Menschen hereinfallen, ist der Rebase-Fall . Wenn Sie anstelle einer normalen Zusammenführung eine Neubasis durchführen, werden die Rollen vertauscht. Wie ist das? Nun, das liegt ausschließlich an der Art und Weise, wie das Rebasieren funktioniert. Denken Sie an Rebase, um so zu arbeiten:

  1. Alle Commits, die Sie seit Ihrem letzten Pull ausgeführt haben, werden in einen eigenen Zweig verschoben . Nennen wir ihn BranchX .
  2. Sie checken den Kopf Ihres aktuellen Zweigs aus und verwerfen alle lokalen Änderungen, die Sie vorgenommen haben. Auf diese Weise rufen Sie jedoch alle Änderungen ab, die andere für diesen Zweig vorgenommen haben.
  3. Jetzt wird jedes Commit auf BranchX ausgewählt, um alt bis neu in Ihrem aktuellen Zweig zu sein.
  4. BranchX wird erneut gelöscht und wird daher in keinem Verlauf angezeigt .

Natürlich ist das nicht wirklich so, aber es ist ein schönes Denkmodell für mich. Und wenn Sie sich 2 und 3 ansehen, werden Sie verstehen, warum die Rollen jetzt vertauscht werden. Ab 2 ist Ihr aktueller Zweig jetzt der Zweig vom Server ohne Ihre Änderungen. Dies ist also unser Zweig (der Zweig, in dem Sie sich befinden). Die Änderungen, die Sie vorgenommen haben, befinden sich jetzt in einem anderen Zweig, der nicht Ihr aktueller ist ( BranchX ). Daher sind diese Änderungen (obwohl es sich um die von Ihnen vorgenommenen Änderungen handelt) ihre (der andere Zweig, der in Ihrer Aktion verwendet wird).

Das bedeutet, wenn Sie zusammenführen und möchten, dass Ihre Änderungen immer gewinnen, würden Sie git anweisen, immer "unsere" zu wählen. Wenn Sie jedoch neu festlegen und möchten, dass alle Ihre Änderungen immer gewinnen, weisen Sie git an, immer "ihre" zu wählen.

Mecki
quelle
3

Ich weiß, dass es die Bedeutung nicht erklärt, aber ich habe mir ein kleines Bild gemacht, um daran zu erinnern, welches ich verwenden soll:

Geben Sie hier die Bildbeschreibung ein

Ich hoffe es hilft!

PS - Überprüfen Sie auch den Link in Nitays Antwort 🙂

Kamafeather
quelle
3

Ich werde mein Memo hier posten, weil ich immer wieder hierher zurückkommen muss.

SZENARIO 1. Normaler Entwickler: Sie sind Entwickler, die nicht mastermit featureZweigen zusammengeführt werden können und nur mit diesen spielen müssen .

Fall 1: Meister ist ein König. Sie möchten Ihren featureZweig aktualisieren (= Basis neu erstellen master), da er masterneue Aktualisierungen von Abhängigkeiten enthält und Sie Ihre bescheidenen Änderungen überschreiben möchten.

git checkout master
git pull

git checkout feature
git rebase -X ours master

Fall 2: Du bist ein König. Sie möchten Ihren featureZweig auf masterÄnderungen zurücksetzen . Aber Sie haben mehr getan als Ihre Kollegen und möchten Ihre eigenen Änderungen vorrangig nutzen.

git checkout master
git pull

git checkout feature
git rebase -X theirs master

WICHTIG: Wie Sie sehen können, sollten normale Entwickler es vorziehen rebaseund jeden Morgen wie Übungen / Kaffee wiederholen.

SZENARIO 2. Merging-Sensei: Sie sind ein Teamleiter und möchten andere Zweige zusammenführen und ein zusammengeführtes Ergebnis direkt an einen Master senden . masterist ein Zweig, den Sie ändern werden.

Fall 1: Meister ist ein König Sie möchten einen Zweig mastereines Drittanbieters zusammenführen, haben jedoch Priorität. featureist ein Zweig, den Ihr Senior gemacht hat.

git checkout feature
git pull

git checkout master
git merge -X ours master

Fall 2: Neue Änderungen sind ein König Wenn Ihr leitender Entwickler eine coole Version veröffentlicht hat featureund Sie die alten Änderungen in der masterBranche überschreiben möchten .

git checkout feature
git pull

git checkout master
git merge -X theirs master

ERINNERUNG: Um in einem Mitternacht zu erinnern , die man wählen: masterist oursIMMER. Und theirsist eine feature, die ihre getan haben.

DenisKolodin
quelle
2

Aus git checkoutder Verwendung:

-2, --ours            checkout our version for unmerged files
-3, --theirs          checkout their version for unmerged files
-m, --merge           perform a 3-way merge with the new branch

Wenn Merge Konflikte zu lösen, können Sie tun git checkout --theirs some_file, und git checkout --ours some_filedie Datei auf die aktuelle Version und die eingehenden Versionen jeweils zurückgesetzt werden .

Wenn Sie die Datei auf die 3-Wege-Zusammenführungsversion der Datei zurückgesetzt haben git checkout --ours some_fileoder git checkout --theirs some_filezurücksetzen möchten, können Sie dies tun git checkout --merge some_file.

Joshua Ryan
quelle