2014-04-21 11 views
35

Ich habe dieses Projekt, wo der Remote-Repo den Hauptentwicklungszweig hat, und ich habe eine Verzweigung, die den experimentellen Zweig enthält. Ich bin verpflichtet, rebase wechselt von der Entwicklung Zweig zu meinem experimentellen Zweig, bevor ich zu meiner Gabel schieben. So geht es:Git Rebasekonflikt: Wer ist HEAD?

git checkout experimentalbranch 
git fetch remoterepo 
git rebase remoterepo/developmentbranch 

Zu dieser Zeit habe ich Konflikte getroffen. Jedoch, Ich bin nicht vertraut mit irgendwelchen dieser Änderungen (Ich bin Wochen Änderungen der Woche, weil sie meine Änderungen nicht sofort zusammengeführt haben). Außerdem ist es das erste Mal, dass ich rebase mache. Ich bin mehr an merge gewöhnt.

In der Regel ist es wie <<LOCAL||REMOTE>> für merge, die sehr intuitiv klingt. Aber in rebase ist es <<HEAD||COMMIT MESSAGE>>. Wer ist HEAD? Ist es die HEAD der Entwicklungsbranche? Ist es der neueste Code in der Entwicklungsbranche oder woanders?

Antwort

52

Beim Zusammenführen (einschließlich des Umbasierens, bei dem es sich um einen Spezialfall des wiederholten internen "Mergens" handelt), sind zwei "Köpfe" (zwei spezielle Zweigspitzen) beteiligt. Lassen Sie uns diese your-branch anrufen und origin/their-branch:

   G - H --------  <-- HEAD=your-branch 
      /    \ 
... - E - F     M <-- desired merge commit [requires manual merge] 
      \    /
       I - J - K - L  <-- origin/their-branch 

Dieser Punkt häufig ist (und wenig überraschend) verwirrend, obwohl, wenn wie dies markiert deutlich genug.

machen es noch schlimmer, aber git verwendet --ours und --theirs an den beiden Kopf beziehen verpflichtet bei einer Zusammenführung, mit „uns“ ist diejenige, die Sie auf waren (Commit H), wenn Sie git merge lief, und „ihre“ zu sein , nun, ihre (commit L). Aber wenn du eine Rebase machst, sind die beiden Köpfe umgedreht, so dass "unser" der Kopf ist, den du auf-zu-ie, ihren aktualisierten Code, umnimmst - und "ihr" das Commit ist, das du gerade umlegst, dh dein eigener Code.

Dies ist, weil Rebase tatsächlich eine Reihe von Cherry-Pick-Operationen verwendet. Sie beginnen mit der gleichen Bild:

   G - H   <-- HEAD=your-branch 
      /
... - E - F 
      \ 
       I - J - K - L <-- origin/their-branch 

Was git hier tun muss, ist zu Kopie die Wirkung von Commits G und H, das heißt, begehen git cherry-pickG, dann es wieder tun mit H zu begehen. Aber um das zu tun, git muss SchalterL zunächst intern zu begehen (mit „frei stehenden HEAD“ -Modus):

   G - H   <-- your-branch 
      /
... - E - F 
      \ 
       I - J - K - L <-- HEAD, origin/their-branch 

Jetzt kann es beginnen, das Fütterungsmaterial Operation durch die Bäume zu vergleichen für verpflichtet F und G (Um zu sehen, was Sie geändert haben), dann vergleichen Sie F vs L (um zu sehen, ob einige Ihrer Arbeit bereits in L ist) und nehmen Sie alle Änderungen nicht bereits in L und fügen Sie es hinzu. Dies ist intern eine "Merge" -Operation.

   G - H   <-- your-branch 
      /
... - E - F     G' <-- HEAD 
      \    /
       I - J - K - L <-- origin/their-branch 

Wenn die Zusammenführung nicht gut gehen, bleibt HEAD noch bei L begehen (weil G' existiert begehen noch nicht). Also, ja, HEAD ist der Chef ihrer Entwicklungsbranche - zumindest ist es gerade jetzt.

Sobald die Kopie G existiert, obwohl, HEAD bewegt zu G' und git versucht, die Änderungen von H, auf die gleiche Weise zu kopieren (diff G vs H, dann F vs G' diff und die Ergebnisse zusammenführen):

   G - H   <-- your-branch 
      /
... - E - F     G' - H' <-- HEAD 
      \    /
       I - J - K - L <-- origin/their-branch 

noch einmal, wenn die Zusammenführung versagt und braucht Hilfe, sind Sie links mit HEAD deutete auf G' statt H' als H' existiert noch nicht.

Sobald die alle Merges erfolgreich zu sein und verpflichtet G' und H'tun existieren, git entfernt das Etikett your-branch von H zu begehen, und macht es H' anstatt zu begehen Punkt:

   G - H 
      /
... - E - F     G' - H' <-- HEAD=your-branch 
      \    /
       I - J - K - L <-- origin/their-branch 

und Sie sind jetzt indexiert und HEAD ist wieder einmal das, was Sie erwarten würden. Aber während der Rebase, HEAD ist entweder ihre Verzweigung-Tipp (commit L), oder eine der neuen Commits kopiert und hinter ihrer Verzweigung Spitze angehängt; und --ours bedeutet, dass die Verzweigung am Ende von L gezüchtet wird, während --theirs bedeutet, dass die Festschreibung kopiert wird (G oder H oben).

(Dies ist im Grunde git den rohen Mechanismus des aussetzt, wie es tut, was es tut, was ziemlich viel in git passiert.)

+1

Also im Grunde 'HEAD', in der ersten Operation„their- Branch "'s" HEAD', und in den folgenden Operationen ist 'HEAD' nun die neu angehängten Commits von mir? – Joseph

+1

Ja; aber es kann ziemlich verwirrend sein, weil sie neu angehängt sind - Commits in dem Zweig, den du "wachsst", der noch keinen Namen hat. In den obigen Zeichnungen befinden sie sich in der mittleren Reihe und nicht in der oberen oder unteren Reihe. – torek

+1

danke für die Erklärung. Mein Chef gab mir diesen Blick, als ich ihm erklärte, dass ich verwirrt war mit dem, was HEAD war. Ich denke, er lebt im Rebase-Universum und ich lebte im Merge-Universum. – dtc