Co oznacza FETCH_HEAD w Git?

221

git pull --help mówi:

W trybie domyślnym git pulljest skrótem, git fetchpo którym następuje git merge FETCH_HEAD.

Co to jest FETCH_HEADi co się faktycznie łączy git pull?

Misza Moroszko
źródło
3
Uwaga: ponieważ git 1.8.4 (sierpień 2013), git fetch origin masterbędzie aktualizowany origin/master, nie tylko FETCH_HEAD. Zobacz stackoverflow.com/a/20967347/6309
VonC
Więcej informacji na temat git merge FETCH_HEAD(od Git 2.5, 2 kwartał 2015), patrz stackoverflow.com/a/30425991/6309
VonC

Odpowiedzi:

218

FETCH_HEADjest krótkotrwałym ref, aby śledzić, co właśnie zostało pobrane ze zdalnego repozytorium. git pullnajpierw wywołuje git fetch, w normalnych przypadkach, pobiera gałąź ze zdalnego; FETCH_HEADwskazuje na wierzchołek tej gałęzi (przechowuje SHA1 zatwierdzenia, podobnie jak gałęzie). git pullnastępnie wywołuje git merge, łącząc FETCH_HEADsię z bieżącym oddziałem.

Rezultat jest dokładnie taki, jak można się spodziewać: zatwierdzenie na końcu odpowiedniej zdalnej gałęzi jest scalane z zatwierdzeniem na końcu bieżącej gałęzi.

To trochę jak robienie git fetchbez argumentów (lub git remote update), aktualizowanie wszystkich zdalnych gałęzi, a następnie uruchamianie git merge origin/<branch>, ale używanie FETCH_HEADwewnętrznie zamiast odwoływania się do każdego pojedynczego ref, który został pobrany, zamiast konieczności nazywania rzeczy.

Cascabel
źródło
9
@Jefromi: Przykro mi, że jesteś źle: O ile mi zrozumieć, git fetchaktualizacje (scala) wszystkie dane obiektu z magazynu zdalnego, a nie tylko na brunch. Więc nie rozumiem z twojej odpowiedzi, w jaki sposób git decyduje do końca, którą gałąź wskazać FETCH_HEAD. Nie mogę również znaleźć FETCH_HEADw dokumentacji git (definicji, a nie przykładów). Istnienie FETCH_HEADwydaje mi się bardziej obejściem, aby jakośgit pull pracować .
Alexey,
14
Alexey: FETCH_HEADodpowiada końcówce zdalnej gałęzi określonej branch.<BRANCH>.mergew konfiguracji lokalnego repozytorium. Tak więc, chociaż fetchrzeczywiście pobiera wszystkie dane obiektowe ze zdalnego magazynu, FETCH_HEADsłuży do wskazania, w którym kierunku gałąź zdalna śledzona przez oddział lokalny osiągnęła postęp. Więc jeśli jesteś w lokalnym masteroddziale i uruchom git fetch, i branch.master.mergewskazuje refs/heads/master, to FETCH_HEADbędzie miał taką samą wartość jak origin/masternatychmiast po operacji pobierania.
larsks
4
@alexy FETCH_HEAD jest opisany w drugim akapicie opisu git fetch na stronie podręcznika man. Moja odpowiedź jest poprawna. A git fetch bez argumentów aktualizuje wszystkie zdalne gałęzie dla domyślnego zdalnego ... ale to zdecydowanie nie jest to samo, co scalanie.
Cascabel
4
Co się stanie, FETCH_HEADjeśli pobierzesz wszystkie zdalne gałęzie za pośrednictwem git fetch -a?
stigi,
2
@stigi Końcówka zdalnej gałęzi śledzenia, na którą aktualnie wskazuje gałąź transakcji w git config. Zobacz odpowiedź larsks w powyższym komentarzu.
Ankur Agarwal
19

FETCH_HEAD jest odniesieniem do końcówki ostatniego pobrania, niezależnie od tego, czy to pobieranie zostało zainicjowane bezpośrednio za pomocą polecenia pobierania, czy jako część ściągnięcia. Obecna wartość FETCH_HEAD jest przechowywany w .gitfolderze w pliku o nazwie, zgadliście, FETCH_HEAD.

Więc jeśli wydam:

git fetch https://github.com/ryanmaxwell/Fragaria

FETCH_HEAD może zawierać

3cfda7cfdcf9fb78b44d991f8470df56723658d3        https://github.com/ryanmaxwell/Fragaria

Jeśli mam zdalne repozytorium skonfigurowane jako gałąź zdalnego śledzenia, mogę śledzić moje pobieranie za pomocą scalenia gałęzi śledzenia. Jeśli nie, mogę scalić końcówkę ostatniego pobrania bezpośrednio za pomocą FETCH_HEAD.

git merge FETCH_HEAD
Jonathan Mitchell
źródło
1
Aby dodać moje 5 centów. To, co mnie pomyliło, to fakt, że mój FETCH_HEAD był za najnowszymi zatwierdzeniami, nawet jeśli wykonałem nowe pobieranie, które zwróciło „brak zmian” (w zaćmieniu). Myślę, że powodem jest to, że wszystkie zmiany od mojego ostatniego pobrania są ode mnie i zostały przeze mnie przesłane na serwer. Kolejne pobieranie nie miało więc nic do roboty i nawet nie zaktualizowało FETCH_HEAD. Nie jestem jednak pewien, czy jest to wada implementacji GIT czy Eclipse Git.
Torge
11

Jak wspomniano w odpowiedzi Jonathana , FETCH_HEAD odpowiada plikowi .git/FETCH_HEAD. Zwykle plik wygląda następująco:

71f026561ddb57063681109aadd0de5bac26ada9                        branch 'some-branch' of <remote URL>
669980e32769626587c5f3c45334fb81e5f44c34        not-for-merge   branch 'some-other-branch' of <remote URL>
b858c89278ab1469c71340eef8cf38cc4ef03fed        not-for-merge   branch 'yet-some-other-branch' of <remote URL>

Zwróć uwagę, jak wszystkie gałęzie oprócz jednej są oznaczone not-for-merge. Dziwnym jest gałąź, która została sprawdzona przed pobraniem. Podsumowując: FETCH_HEAD zasadniczo odpowiada zdalnej wersji oddziału, która jest obecnie wypisana.

Carsten Führmann
źródło
9

Właśnie odkryłem i wykorzystałem FETCH_HEAD. Chciałem lokalną kopię oprogramowania z serwera i zrobiłem to

git fetch gitserver release_1

gitserverto nazwa mojej maszyny, która przechowuje repozytoria git. release_1jest tagiem dla wersji oprogramowania. Ku mojemu zaskoczeniu release_1nigdzie nie było mnie na mojej lokalnej maszynie. Musiałem pisać

 git tag release_1 FETCH_HEAD 

aby uzupełnić kopię oznaczonego łańcucha zatwierdzeń (release_1) ze zdalnego repozytorium do lokalnego. Fetch znalazł zdalny znacznik, skopiował zatwierdzenie na mój komputer lokalny, nie utworzył lokalnego znacznika, ale ustawił FETCH_HEADwartość zatwierdzenia, aby móc go znaleźć i użyć. Następnie FETCH_HEADutworzyłem lokalny tag, który pasował do tagu na pilocie. Jest to praktyczna ilustracja tego, co FETCH_HEADjest i jak można go używać, i może być przydatna dla kogoś, kto zastanawia się, dlaczego git fetch nie robi tego, czego naiwnie byś się spodziewał.

Moim zdaniem najlepiej tego unikać, a lepszym sposobem na osiągnięcie tego, co próbowałem zrobić, jest

git fetch gitserver release_1:release_1

tzn. pobrać wersję_1 i nazwać ją lokalnie wersją_1. (Jest to źródło: dest, patrz https://git-scm.com/book/en/v2/Git-Internals-The-Refspec ; na wypadek, gdybyś chciał nadać mu inną nazwę!)

FETCH_HEADCzasem możesz chcieć użyć : -

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

może być dobrym sposobem na użycie poprawki numer 1234 z twojego serwera Git i pozostawienie odśmiecania przez Git, aby pozbyć się kopii z serwera, gdy poprawka zostanie wybrana na twój aktualny oddział. (Zakładam, że istnieje ładny, czysty tag zatwierdzający zawierający całą poprawkę błędu na serwerze!)

Ivan
źródło
Ciekawe opinie +1
VonC
Dzięki. Zredagowałem swój oryginalny post, napisany, gdy kilka lat temu odkryłem FETCH_HEAD, ponieważ wydawało się, że zachęca on do kopiowania tagu za pomocą FETCH_HEAD zamiast składni source: dest dla refspecs. Mam nadzieję, że podałem teraz lepszy przykład wykorzystania FETCH_HEAD.
Ivan
3

git pull jest kombinacją pobrania, a następnie scalenia. Kiedy zdarza się git fetch, odnotowuje zatwierdzenie przez głowę tego, co zostało pobrane w FETCH_HEAD (tylko plik o tej nazwie w .git). Te zatwierdzenia są następnie scalane w twój katalog roboczy.

manojlds
źródło
3
@manjolds, co rozumiesz przez „ zatwierdzenie przez głowę tego, co zostało pobrane”? Git pobiera wszystko z funkcją pobierania.
Alexey,
@Alexey z instrukcji git: git-scm.com/docs/git-fetch : Nazwy
PJ_Finnegan