2009-11-16 5 views
91

Ich habe gerade etwas seltsam über git pull beobachtet, was ich nicht verstehe.'git pull Herkunft mybranch' verlässt lokale mybranch N Commits vor dem Ursprung. Warum?

Am Freitag arbeitete ich in einer lokalen Niederlassung. nennen wir es mybranch. Bevor ich das Büro verließ, schob ich es zum Ursprung (das ist mein GitHub Repo): git push origin mybranch.

Gestern zu Hause, ich pull ed mybranch zu meinem Laptop, tat etwas mehr Codierung, und schob dann meine Änderungen zurück zu github (Herkunft).

Jetzt habe ich bei der Arbeit bin wieder und versuchte, die Änderungen von gestern zu meiner Arbeit Maschine zu ziehen (ich habe nichts in meinem Arbeitsplatz lokalen Repo über das Wochenende aus):

git pull origin mybranch 

dass verursachte eine schnelle Vorwärtszusammenführung, die in Ordnung ist. Ich habe dann ein git status, und es wird gesagt:

# On branch mybranch 
# Your branch is ahead of 'origin/mybranch' by 6 commits. 
# 
nothing to commit (working directory clean) 

Huh? Wie kann es 6 Commits voraus sein, wenn ich es nicht über das Wochenende berührte, UND nur vom Ursprung gezogen? So lief ich eine git diff origin/mybranch und die Diffs waren genau die 6 Änderungen, die ich gerade aus der Ferne zog.

Ich konnte nur „reparieren“ diese git fetch origin durch Ausführen von:

From [email protected]:me/project 
af8be00..88b0738 mybranch -> origin/mybranch 

Offenbar meinem lokalen Repo einige Referenzobjekte fehlte, aber wie kann das sein? Ich meine, ein Pull holt bereits, und ich habe an nichts außer diesem Zweig gearbeitet, also sollten git fetch origin und git fetch origin mybranch dasselbe Ergebnis haben?

Sollte ich immer git pull origin anstelle von git pull origin branchname verwenden?

Ich bin verwirrt.

+0

Ich habe das auch bemerkt; ein "git push" scheint es auch zu lösen ("alles auf dem neuesten Stand"). –

+4

'git config --get-regexp br. *' Kann Ihnen sagen, ob Ihre Konfiguration einen lokalen Zweig hat, der einen anderen Zweig verfolgt – VonC

+3

Kannst du 'git config branch.master.remote yourGitHubRepo.git' in deine workRepo eingeben und check (at der nächste 'git Pull-Ursprung'), wenn der Status mit einer" Voraus "Warnung bleibt? – VonC

Antwort

113

git pull Aufrufe git fetch mit den entsprechenden Parametern vor dem Zusammenführen der explizit abgerufene Köpfe (oder wenn keine Remote-Zweig für die Zusammenführung konfiguriert) in den aktuellen Zweig.

Die Syntax: git fetch <repository> <ref> wo <ref> ohne Doppelpunkt nur einen Zweig Namen ist ein ‚One Shot‘, dass holen macht keinen Standard aller verfolgten Zweige der angegebenen Remote holen, sondern holt nur den benannten Zweig in FETCH_HEAD.

Update: für Git-Versionen seit 1.8.4, wenn es ein Remote-Tracking-Zweig, der die Referee Spuren, die Sie dann der Tracking-Zweig holen gefragt wird nun fetch aktualisiert werden. Diese Änderung wurde speziell vorgenommen, um die Verwirrung zu vermeiden, die das vorherige Verhalten verursacht hat.

Wenn Sie ausführen git pull <repository> <ref>, FETCH_HEAD wie oben aktualisiert wird, dann in die fusionierte HEAD checkt, aber keine der Standard-Tracking-Zweige für das Remote-Repository aktualisiert werden (Git < 1.8.4).Dies bedeutet, dass es lokal aussieht wie Sie vor der Remote-Zweig sind, während in der Tat Sie auf dem neuesten Stand sind.

persönlich immer ich tun git fetch von git merge <remote>/<branch> gefolgt, weil ich über Zwangs Updates alle Warnungen erhalten, um zu sehen, bevor ich zusammenführen, und ich kann eine Vorschau, was ich verschmelzenden in. Wenn ich git pull ein bisschen mehr verwendet als ich, würde ich tun Sie eine Ebene git pull ohne Parameter die meiste Zeit, sich auf branch.<branch>.remote und branch.<branch>.merge verlassen, um 'das Richtige zu tun'.

+4

+1 Das ist wirklich eine gute Erklärung! Ich wusste, dass die Erklärung sich irgendwo in "git help fetch" versteckte, aber ich konnte es nicht verstehen ... –

+1

+1. Guter Beitrag, mit einem ähnlichen Ansatz wie http://gitster.livejournal.com/28309.html – VonC

+1

Also würde ein 'git fetch' nach einem' git ziehen 'das Problem beheben, da der Abruf die Standard-Tracking-Zweige aktualisieren würde? Auch, danke für diese Antwort, angefangen Sinn zu machen :) –

3

Was gibt git remote -v show zurück, wenn es um Ursprung geht?

Wenn der Ursprung auf github zeigt, sollte der Status auf dem neuesten Stand sein und nicht vor einem Remote-Repo. Zumindest benutze ich mit dem Git1.6.5 einen schnellen Test.

Wie auch immer, dies zu vermeiden, definiert explizit die Remote-Repo-Master-Zweig:

$ git config branch.master.remote yourGitHubRepo.git 

dann ein git pull origin master, gefolgt von einem git status sollte einen sauberen Zustand zurück (nicht vor).
Warum? weil der get fetch origin master (im git pull origin master enthalten) nicht nur FETCH_HEAD (wie Charles Bailey erklärt in his answer) aktualisiert, sondern es würde auch aktualisieren die "remote master branch" innerhalb Ihrer lokalen Git-Repository.
In diesem Fall würde Ihr lokaler Master nicht mehr dem Remote-Master voraus zu sein scheinen.


Ich kann dies testen, mit einem Git1.6.5:

Zuerst erstelle ich eine workrepo:

PS D:\git\tests> cd pullahead 
PS D:\git\tests\pullahead> git init workrepo 
Initialized empty Git repository in D:/git/tests/pullahead/workrepo/.git/ 
PS D:\git\tests\pullahead> cd workrepo 
PS D:\git\tests\pullahead\workrepo> echo firstContent > afile.txt 
PS D:\git\tests\pullahead\workrepo> git add -A 
PS D:\git\tests\pullahead\workrepo> git commit -m "first commit" 

ich simulieren ein Repo GitHub von einem nackten Repo zu schaffen (eine, die Push von überall empfangen kann)

PS D:\git\tests\pullahead\workrepo> cd .. 
PS D:\git\tests\pullahead> git clone --bare workrepo github 

Ich füge ein modif zu meine Arbeits Repo, dass ich auf gitHub Repo-Push (als Remote hinzugefügt)

PS D:\git\tests\pullahead> cd workrepo 
PS D:\git\tests\pullahead\workrepo> echo aModif >> afile.txt 
PS D:\git\tests\pullahead\workrepo> git ci -a -m "a modif to send to github" 
PS D:\git\tests\pullahead\workrepo> git remote add github d:/git/tests/pullahead/github 
PS D:\git\tests\pullahead\workrepo> git push github 

ich ein Haus Repo, geklontes o erstellen f GitHub, in dem ich ein paar Änderungen vornehmen, auf GitHub geschoben:

PS D:\git\tests\pullahead\workrepo> cd .. 
PS D:\git\tests\pullahead> git clone github homerepo 
PS D:\git\tests\pullahead> cd homerepo 
PS D:\git\tests\pullahead\homerepo> type afile.txt 
firstContent 
aModif 

PS D:\git\tests\pullahead\homerepo> echo aHomeModif1 >> afile.txt 
PS D:\git\tests\pullahead\homerepo> git ci -a -m "a first home modif" 
PS D:\git\tests\pullahead\homerepo> echo aHomeModif2 >> afile.txt 
PS D:\git\tests\pullahead\homerepo> git ci -a -m "a second home modif" 
PS D:\git\tests\pullahead\homerepo> git push github 

ich klonen workrepo dann für ein erstes Experiment

PS D:\git\tests\pullahead\workrepo4> cd .. 
PS D:\git\tests\pullahead> git clone workrepo workrepo2 
Initialized empty Git repository in D:/git/tests/pullahead/workrepo2/.git/ 
PS D:\git\tests\pullahead> cd workrepo2 
PS D:\git\tests\pullahead\workrepo2> git remote add github d:/git/tests/pullahead/github 
PS D:\git\tests\pullahead\workrepo2> git pull github master 
remote: Counting objects: 8, done. 
remote: Compressing objects: 100% (4/4), done. 
remote: Total 6 (delta 1), reused 0 (delta 0) 
Unpacking objects: 100% (6/6), done. 
From d:/git/tests/pullahead/github 
* branch   master  -> FETCH_HEAD 
Updating c2763f2..75ad279 
Fast forward 
afile.txt | Bin 46 -> 98 bytes 
1 files changed, 0 insertions(+), 0 deletions(-) 

In diesem Repo, tut git status Master geing erwähnen vor 'origin':

PS D:\git\tests\pullahead\workrepo5> git status 
# On branch master 
# Your branch is ahead of 'origin/master' by 2 commits. 
# 
nothing to commit (working directory clean) 

Aber das ist nur origin ist Github nicht:

PS D:\git\tests\pullahead\workrepo2> git remote -v show 
github d:/git/tests/pullahead/github (fetch) 
github d:/git/tests/pullahead/github (push) 
origin D:/git/tests/pullahead/workrepo (fetch) 
origin D:/git/tests/pullahead/workrepo (push) 

Aber wenn ich wiederholen Sie die Sequenz in einem Repo, die einen Ursprung auf Github (oder keine Herkunft überhaupt, nur eine entfernte ‚Github‘ definiert ist), Status ist sauber hat:

PS D:\git\tests\pullahead\workrepo2> cd .. 
PS D:\git\tests\pullahead> git clone workrepo workrepo4 
PS D:\git\tests\pullahead> cd workrepo4 
PS D:\git\tests\pullahead\workrepo4> git remote rm origin 
PS D:\git\tests\pullahead\workrepo4> git remote add github d:/git/tests/pullahead/github 
PS D:\git\tests\pullahead\workrepo4> git pull github master 
remote: Counting objects: 8, done. 
remote: Compressing objects: 100% (4/4), done. 
remote: Total 6 (delta 1), reused 0 (delta 0) 
Unpacking objects: 100% (6/6), done. 
From d:/git/tests/pullahead/github 
* branch   master  -> FETCH_HEAD 
Updating c2763f2..75ad279 
Fast forward 
afile.txt | Bin 46 -> 98 bytes 
1 files changed, 0 insertions(+), 0 deletions(-) 
PS D:\git\tests\pullahead\workrepo4> git status 
# On branch master 
nothing to commit (working directory clean) 

Wenn ich nur origin zeigt auf github, status wäre sauber für git1.6.5.
Es kann mit einer 'ahead' Warnung für frühere git, aber auf jeden Fall eine explizit definierte git config branch.master.remote yourGitHubRepo.git sollte in der Lage sein, dies zu tun, auch mit frühen Versionen von Git.

+0

Danke, dass Sie sich die Zeit genommen haben, sich das anzuschauen. Die Ursprungs-Fernbedienung zeigt bereits auf mein GitHub Repo. Ich habe dieses Projekt von einer GitHub-URL geklont und mein lokaler Master-Zweig verfolgt den Ursprung/Master. Wie für die Mybranch, ich bin mir ziemlich sicher, dass ich es aus dem Ursprung/mybranch Zweig erstellt, der es automatisch verfolgen sollte. Aber trotzdem, vielleicht ist das das Problem? Dass die lokale Mybranch nicht wirklich Herkunft/Mybranch verfolgt? PS: Ich benutze git 1.6.1 (über MacPorts). – Matthias

+0

Gibt es einen Git-Befehl, mit dem ich sehen kann, ob ein lokaler Zweig einen anderen Zweig verfolgt? Ich kann es nicht in den Manpages finden. – Matthias

+0

Sie können sehen, welche Remote-Zweige mit 'git remote show origin 'verfolgt werden. –

2

Sind Sie vorsichtig, alle Ihre Fernbedienung (außer origin, die mit Ihrem ursprünglichen Klon kommt) mit git remote add NAME URL? Ich habe diesen Fehler gesehen, als er gerade zur git config hinzugefügt wurde.

+0

Ich habe dies beim Klonen des Repo getan. Ich habe das aber nicht mit jedem Zweig gemacht. Für z.B. mybranch würde ich zuerst vom Ursprung holen, dann 'git checkout -b mybranch origin/mybranch'. Laut der man-Seite von git-branch ist der Ursprung/meinbranch der Startpunkt, und außerdem heißt es für --track: "... Verwenden Sie dies, wenn Sie immer vom gleichen Upstream-Zweig in den neuen Zweig ziehen, und Wenn Sie "git pull " nicht explizit verwenden möchten. Dieses Verhalten ist die Standardeinstellung, wenn der Startpunkt eine Remoteverzweigung ist. " – Matthias