Jak wykonać „git fetch” i „git merge” z Remote Tracking Branch (np. „Git pull”)

111

Skonfigurowałem kilka gałęzi zdalnego śledzenia w git, ale wydaje mi się, że nigdy nie jestem w stanie scalić ich z lokalnym oddziałem po zaktualizowaniu ich za pomocą „git fetch”.

Na przykład załóżmy, że mam zdalną gałąź o nazwie „an-other-branch”. Skonfigurowałem to lokalnie jako gałąź śledzenia przy użyciu

git branch --track an-other-branch origin/an-other-branch

Na razie w porządku. Ale jeśli ta gałąź zostanie zaktualizowana (zwykle przez przeniesienie maszyny i zatwierdzenie z tej maszyny), a chcę ją zaktualizować na oryginalnej maszynie, mam problem z pobieraniem / scalaniem:

git fetch origin an-other-branch
git merge origin/an-other-branch

Za każdym razem, gdy to robię, otrzymuję komunikat „Już aktualny” i nic się nie łączy.

Jednak plik

git pull origin an-other-branch

zawsze aktualizuje go zgodnie z oczekiwaniami.

Uruchomienie git diff

git diff origin/an-other-branch

pokazuje, że istnieją różnice, więc wydaje mi się, że mam błędną składnię.

Co ja robię źle?

EDYCJA [2010-04-09]: Sprawdziłem kilka razy i na pewno nie jestem na innej gałęzi. Czy moje „pobieranie git”, po którym następuje „git merge” (jak pokazano powyżej), powinno zrobić dokładnie to samo, co polecenie git pull? Otrzymam przepływ pracy pokazujący wyniki statusu gita itp.

kaybenleroll
źródło

Odpowiedzi:

170

Nie pobierasz oddziału, pobierasz całego pilota:

git fetch origin
git merge origin/an-other-branch
Gareth
źródło
8
Więcej szczegółów: git fetch origin an-other-branchprzechowuje pobraną wskazówkę FETCH_HEAD, ale nie origin/an-other-branch(tj. Zwykła „gałąź zdalnego śledzenia”). Można by to zrobić git fetch origin an-other-branch && git merge FETCH_HEAD, ale robienie tego tak, jak mówi @Gareth, jest lepsze (lub po prostu użyj git pull ).
Chris Johnsen,
więc jeśli źródło ma 1000 oddziałów, czy chcesz mieć zdalną gałąź dla nich wszystkich?
Gauthier
4
Pewnie. Jeśli dodałem zdalne repozytorium z 1000 gałęzi do mojego i zapytam, jakie gałęzie ma pilot, to cholera lepiej daj mi wszystko 1000
Gareth
będzie git merge origin/an-other-branchłączyć origin/an-other-branchdo wszystkich lokalnych oddziałów, które są ustawione, aby ją śledzić? jak mogę połączyć się tylko z jednym lokalnym oddziałem?
amfibia
1
Co więc robi git pull(bez argumentów) - którą gałąź łączy? Czy łączy gałąź zdalnego śledzenia odpowiadającą bieżącej gałęzi?
The Red Pea
69

Wybór tylko jednej gałęzi: fetch/ merge vs. pull

Ludzie często radzą ci oddzielić „pobieranie” od „scalania”. Zamiast tego mówią:

    git pull remoteR branchB

Zrób to:

    git fetch remoteR
    git merge remoteR branchB

Nie wspominają o tym, że takie polecenie pobierania faktycznie pobierze wszystkie gałęzie ze zdalnego repozytorium, co nie jest tym, co robi to polecenie pull. Jeśli masz tysiące oddziałów w zdalnym repozytorium, ale nie chcesz widzieć ich wszystkich, możesz uruchomić to niejasne polecenie:

    git fetch remoteR refs/heads/branchB:refs/remotes/remoteR/branchB
    git branch -a  # to verify
    git branch -t branchB remoteR/branchB

Oczywiście jest to absurdalnie trudne do zapamiętania, więc jeśli naprawdę chcesz uniknąć pobierania wszystkich gałęzi, lepiej zmienić swoje, .git/configjak opisano w ProGit.

Co?

Najlepsze wyjaśnienie tego wszystkiego znajduje się w rozdziale 9-5 programu ProGit, Git Internals - The Refspec ( lub przez github ). To niezwykle trudne do znalezienia w Google.

Najpierw musimy wyjaśnić pewną terminologię. W przypadku śledzenia oddziałów zdalnych istnieją zazwyczaj 3 różne gałęzie, o których należy pamiętać:

  1. Gałąź w repozytorium zdalnym: refs/heads/branchBwewnątrz drugiego repozytorium
  2. Twoja gałąź zdalnego śledzenia : refs/remotes/remoteR/branchBw Twoim repozytorium
  3. Twój własny oddział: refs/heads/branchBwewnątrz swojej repo

Gałęzie zdalnego śledzenia (in refs/remotes) są tylko do odczytu. Nie modyfikujesz ich bezpośrednio. Modyfikujesz własną gałąź, a następnie wypychasz ją do odpowiedniej gałęzi w zdalnym repozytorium. Wynik nie jest odzwierciedlany w twoim, refs/remotesdopóki nie nastąpi odpowiednie wyciągnięcie lub pobranie. To rozróżnienie było dla mnie trudne do zrozumienia na podstawie stron podręcznika git, głównie dlatego, że lokalna gałąź ( refs/heads/branchB) "śledzi" gałąź zdalnego śledzenia podczas .git/configdefiniowania branch.branchB.remote = remoteR.

Pomyśl o „referencjach” jak o wskaźnikach C ++. Fizycznie są to pliki zawierające skróty SHA, ale w zasadzie są tylko wskaźnikami do drzewa zatwierdzeń. git fetchdoda wiele węzłów do twojego drzewa zatwierdzeń, ale to, jak git decyduje, które wskaźniki przenieść, jest nieco skomplikowane.

Jak wspomniano w innej odpowiedzi , też nie

    git pull remoteR branchB

ani

    git fetch remoteR branchB

ruszyłby się refs/remotes/branches/branchB, a ten drugi z pewnością nie może się poruszyć refs/heads/branchB. Jednak obaj się ruszają FETCH_HEAD. (Można catkażdy z tych plików wewnątrz .git/, aby zobaczyć, kiedy się zmieniają.) I git mergebędzie odnosić się do FETCH_HEAD, natomiast ustawienie MERGE_ORIG, etc.

cdunn2001
źródło
1
Czy wiesz, że Twój link do Git Internals jest linkiem do tego samego pytania?
Shahbaz
9

Czy na pewno jesteś w lokalnej sieci an-other-branchpodczas łączenia?

git fetch origin an-other-branch
git checkout an-other-branch
git merge origin/an-other-branch

Inne wyjaśnienie :

wszystkie zmiany z gałęzi, którą próbujesz scalić, zostały już scalone z gałęzią, z której aktualnie korzystasz.
Mówiąc dokładniej, oznacza to, że gałąź, którą próbujesz scalić, jest nadrzędna w stosunku do bieżącej gałęzi

jeśli wyprzedzasz zdalne repozytorium o jedno zatwierdzenie, to zdalne repozytorium jest nieaktualne, a nie ty.

Ale w twoim przypadku, jeśli git pulldziała, oznacza to po prostu, że nie jesteś na właściwej gałęzi.

VonC
źródło
3

Git pull jest w rzeczywistości narzędziem combo: uruchamia git fetch (pobieranie zmian) i git merge (scalanie ich z bieżącą kopią)

Czy na pewno jesteś we właściwej gałęzi?

RDL
źródło
Myślę, że OP jest w różnicy. gałąź, przytrafia mi się.
Chaklader Asfak Arefe
1

oto polecenia:

git fetch origin
git merge origin/somebranch somebranch

jeśli zrobisz to w drugiej linii:

git merge origin somebranch

spróbuje połączyć lokalny master z twoją bieżącą gałęzią.

Pytanie, jak to zrozumiałem, czy zostało już pobrane lokalnie i chcesz teraz połączyć swój oddział z najnowszym z tego samego oddziału.

user1524957
źródło