"git pull origin mybranch" pozostawia local Mybranch N commits przed origin. Dlaczego?

Właśnie zauważyłem coś dziwnego w git pull, czego nie rozumiem.

W piątek pracowałem w lokalnym oddziale. nazwijmy to mybranch. Przed wyjściem z biura wcisnąłem go do origin (który jest moim github repo): git push origin mybranch.

Wczoraj w domu, i pulled mybranch do mojego laptopa, zrobiłem trochę więcej kodowania, a następnie przeniósł moje zmiany z powrotem do github (origin).

Teraz znowu jestem w pracy i próbowałem wyciągnąć zmiany z wczoraj na moją maszynę roboczą (nie Zmień cokolwiek w lokalnym repo w moim miejscu pracy w weekend):

git pull origin mybranch

To spowodowało szybkie połączenie do przodu, co jest w porządku. Potem zrobiłem git status, a on powiedział:

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

Huh? Jak to może być 6 commitów przed nami, skoro nawet nie dotknąłem go przez weekend i po prostu ściągnąłem z origin? Więc uruchomiłem git diff origin/mybranch i diffy były dokładnie tymi 6 zmianami, które właśnie wyciągnąłem z pilota.

Mogłem to tylko "naprawić" uruchamiając git fetch origin:

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

Najwyraźniej zaginął mój lokalny Komornik. niektóre obiekty referencyjne, ale jak to możliwe? To znaczy, pull robi już fetch, a ja nie pracowałem na niczym poza tą gałęzią, więc git fetch origin i git fetch origin mybranch powinny mieć taki sam wynik?

Czy powinienem zawsze używać git pull origin zamiast git pull origin branchname?

Jestem zdezorientowany.
Author: Matthias, 2009-11-16

3 answers

git pull wywołania git fetch z odpowiednimi parametrami przed połączeniem jawnie pobranych głowic (lub jeśli nie, zdalnej gałęzi skonfigurowanej do scalania) do bieżącej gałęzi.

Składnia: git fetch <repository> <ref> Gdzie <ref> jest tylko nazwą gałęzi bez dwukropka jest pobieraniem "one shot", które nie wykonuje standardowego pobierania wszystkich śledzonych gałęzi podanego zdalnego, ale zamiast tego pobiera tylko nazwaną gałąź do FETCH_HEAD.

Update: dla wersji Git od 1.8.4, jeśli istnieje zdalna gałąź śledzenia, która śledzi ref, który prosiłeś o pobranie, a następnie gałąź śledzenia zostanie zaktualizowana przez fetch. Zmiana ta została dokonana specjalnie po to, aby uniknąć zamieszania, które spowodowało poprzednie zachowanie.

Kiedy wykonujesz git pull <repository> <ref>, FETCH_HEAD jest aktualizowany jak wyżej, a następnie scalany do Twojej wymeldowanej HEAD, ale żadna ze standardowych gałęzi śledzenia dla zdalnego repozytorium nie zostanie zaktualizowana (Git wygląda jakbyś był przed zdalny oddział, natomiast w rzeczywistości jesteś na bieżąco z nim.

Osobiście zawsze robię git fetch a następnie git merge <remote>/<branch>, ponieważ widzę ostrzeżenia o wymuszonych aktualizacjach przed połączeniem i mogę podglądać, w czym się scalam. Jeśli użyłbym git pull nieco więcej niż ja, zrobiłbym zwykły git pull bez parametrów przez większość czasu, opierając się na branch.<branch>.remote i branch.<branch>.merge, aby "zrobić właściwą rzecz".

 115
Author: CB Bailey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-08 08:27:03

Co git remote -v show zwraca, jeśli chodzi o pochodzenie?

Jeśli origin wskazuje na github, status powinien być aktualny i nie wyprzedzać zdalnego repo. Przynajmniej z Git1.6. 5 używam do szybkiego testu.

W każdym razie, aby tego uniknąć, zdefiniuj jawnie zdalne repo gałęzi master:
$ git config branch.master.remote yourGitHubRepo.git

Następnie a git pull origin master, a następnie a git status powinno zwracać status czysty (no ahead).
Dlaczego? ponieważ get fetch origin master (zawarty w git pull origin master) nie tylko zaktualizowałby FETCH_HEAD (Jak Charles Bailey wyjaśnia w swoją odpowiedź ), ale również zaktualizowałby "zdalną gałąź master" w lokalnym repozytorium Git.
W takim przypadku twój lokalny mistrz nie wydaje się już być "przed" zdalnym mistrzem.


Mogę to przetestować, z git1.6. 5:

Najpierw tworzę 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"

Symuluję repo na Githubie, tworząc goły repo (taki, który może odbierać push z anywhere)

PS D:\git\tests\pullahead\workrepo> cd ..
PS D:\git\tests\pullahead> git clone --bare workrepo github
W związku z tym, że nie jest to możliwe, nie jest to możliwe.]}
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
[[19]}tworzę domowy repo, sklonowany z Githuba, w którym dokonuję kilku modyfikacji, wciśnięty do Githuba:
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
Następnie sklonowałem workrepo do pierwszego eksperymentu.]}
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(-)

W tym repo, git status wspomina master geing przed '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)

Ale to tylko origin nie jest github:

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)

Ale jeśli powtórzę sekwencję w w przypadku repo, które ma pochodzenie do Githuba (lub w ogóle nie ma pochodzenia, tylko zdalny 'github' zdefiniowany), status jest czysty: {]}

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)

Gdybym tylko origin wskazywał na github, status byłoby czyste dla git1. 6. 5.
Może być z ostrzeżeniem "przed" Dla wcześniejszego Gita, ale w każdym razie, zdefiniowana jawnie git config branch.master.remote yourGitHubRepo.git powinna być w stanie się tym zająć, nawet przy wczesnych wersjach Gita.

 3
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:27

Czy jesteś ostrożny, aby dodać wszystkie swoje zdalne (z wyjątkiem origin, który pochodzi z oryginalnego klonu) za pomocą git remote add NAME URL? Widziałem ten błąd, kiedy właśnie zostały dodane do git config.

 2
Author: Pat Notz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-16 14:14:15