Jaka jest różnica między HEAD, drzewem roboczym a indeksem w Git?

487

Czy ktoś może mi powiedzieć różnicę między HEAD, drzewem roboczym a indeksem w Git?

Z tego, co rozumiem, wszystkie są nazwami różnych gałęzi. Czy moje założenie jest prawidłowe?


Edytować

znalazłem to

Pojedyncze repozytorium git może śledzić dowolną liczbę gałęzi, ale twoje drzewo robocze jest powiązane tylko z jedną z nich (gałąź „bieżąca” lub „wyewidencjonowana”), a HEAD wskazuje na tę gałąź.

Czy to oznacza, że ​​HEAD i działające drzewo są zawsze takie same?

Joyce Babu
źródło
26
W odniesieniu do twojej edycji: absolutnie nie. HEADjest zatwierdzeniem na końcu bieżącej gałęzi. Jeśli właśnie sprawdziłeś gałąź, tj. Nie masz zmodyfikowanych plików, to jej zawartość odpowiada działającemu drzewu. Gdy tylko coś zmodyfikujesz, nie będzie już pasować.
Cascabel,
6
Myślę, że musisz to przeczytać: think-like-a-git.net
Andrzej Duś
5
Dodałbym również Staging Areado tej listy. Co to jest HEAD, Working Tree, IndexorazStaging Area
Zielona
2
Ostatnie zdanie @ Jefromi byłoby bardziej jasne:> Gdy tylko cokolwiek zmodyfikujesz, działające drzewo nie będzie już zgodne z zatwierdzeniem HEAD
starscream_disco_party
3
Przy każdym czytaniu tego w przyszłości najlepszym sposobem, aby naprawdę zrozumieć niektóre z tych odpowiedzi, jest zobaczenie, odczucie i wizualna koncepcja tego, co się dzieje: jest to najlepsze narzędzie do nauki git w historii: onlywei.github.io/explain-git-with -d3 / # fetchrebase
BKSpurgeon

Odpowiedzi:

577

Kilka innych dobrych referencji na te tematy:

alternatywny tekst

Używam tego indeksu jako punktu kontrolnego .

Kiedy mam zamiar dokonać zmiany, która może pójść nie tak - kiedy chcę odkryć jakiś kierunek, nie jestem pewien, czy mogę kontynuować, czy nawet to dobry pomysł, na przykład koncepcyjnie wymagające refaktoryzacji lub zmiany typ prezentacji - sprawdzam moją pracę w indeksie. Jeśli jest to pierwsza zmiana, którą wprowadziłem od czasu ostatniego zatwierdzenia, mogę użyć lokalnego repozytorium jako punktu kontrolnego, ale często mam jedną koncepcyjną zmianę, którą wdrażam jako zestaw małych kroków. Chcę punkt kontrolny po każdym kroku, ale zapisz zatwierdzenie, dopóki nie wrócę do działającego, przetestowanego kodu.

Uwagi:

  1. roboczy jest drzewo katalogu (źródło) plików, które można zobaczyć i edytować.

  2. Wskaźnik jest pojedynczy, duży plik binarny w <baseOfRepo>/.git/index, który zawiera listę wszystkich plików w bieżącym gałęzi, ich SHA1 sum kontrolnych, datowników i nazwę pliku - nie ma innego katalogu z kopią plików w nim.

  3. Lokalnym repozytorium jest ukrytym katalogu ( .git) w tym objectskatalogu zawierającego wszystkie wersje każdego pliku w repo (lokalne oddziały i kopie zdalnych oddziałów) jako skompresowanego pliku „blob”.

Nie myśl o czterech „dyskach” przedstawionych na powyższym obrazku jako osobnych kopiach plików repo.

alternatywny tekst

Są to w zasadzie nazwane referencje dla zatwierdzeń Git. Istnieją dwa główne typy referencji: tagi i głowice.

  • Znaczniki to stałe odniesienia, które zaznaczają określony punkt w historii, na przykład v2.6.29.
  • Przeciwnie, głowy są zawsze poruszane, aby odzwierciedlić obecną pozycję rozwoju projektu.

alternatywny tekst

(uwaga: jak skomentował przez Timo Huovinen te strzały nie dopuszcza, co wskazuje na to, że to rozkaz workflow , w zasadzie jak pokazano strzałkami 1 -> 2 -> 3 -> 4, gdzie 1jest pierwszym popełnić i 4jest ostatni)

Teraz wiemy, co dzieje się w projekcie.
Ale żeby wiedzieć, co się dzieje tutaj, teraz jest specjalne odniesienie o nazwie HEAD. Służy dwóm głównym celom:

  • mówi Gitowi, z którego programu należy pobrać pliki, kiedy kasujesz, oraz
  • mówi Gitowi, gdzie umieścić nowe zatwierdzenia podczas zatwierdzania.

Po uruchomieniu git checkout refwskazuje HEADwskazaną referencję i wyodrębnia z niej pliki. Po uruchomieniu git committworzy nowy obiekt zatwierdzenia, który staje się potomkiem prądu HEAD. Zwykle HEADwskazuje jedną z głowic, więc wszystko działa dobrze.

alternatywny tekst

VonC
źródło
20
Po wielokrotnym czytaniu o git nigdy nie rozumiem go całkowicie, jestem naprawdę sfrustrowany n Chcę użyć słowa f; Ale jestem w społeczności! Wspominałeś już o głowach, ale na powyższych zdjęciach zawsze jest jedna GŁOWA, gdzie są pozostałe głowy? „Zwykle HEAD wskazuje na jedną z głowic, więc wszystko działa dobrze”. Błagam, wytłumacz mi to, oświadczenie Ur.
Necktwi
12
@neckTwi HEAD jest bieżącym zatwierdzeniem, z którym pracujesz ( stackoverflow.com/a/964927/6309 ). Zwykle jest to jedna z „głów gałęzi” (jedna z rewizji, do której odnoszą się gałęzie, reprezentujących wierzchołek wspomnianych gałęzi). Ale możesz pobrać (i popracować) każdy zatwierdzenie. Jeśli kasujesz zatwierdzenie, które nie jest jedną z głowic (gałęzi), jesteś w trybie „odłączonej głowicy”: stackoverflow.com/a/3965714/6309
VonC
1
@Imray Zgadzam się, ale tak znalazłem te zdjęcia 5 lat temu ( hades.name/blog/2010/01/28/... )
VonC
11
Jeśli chodzi o indeks, myślę, że najbardziej użyteczną rzeczą, którą można powiedzieć, jest: „Indeks jest po prostu inną nazwą obszaru przejściowego”, jak powiedział @ ashraf-alam. Wydaje mi się, że przez większość czasu w dyskusji jest on nazywany obszarem inscenizacji, dlatego nie utworzyłem automatycznie połączenia, że ​​było to to samo, co indeks.
Pete
1
@Pete Zgadzam się. Aby uzyskać więcej informacji na temat różnicy między pamięcią podręczną a indeksem, zobacz moją inną odpowiedź stackoverflow.com/a/6718135/6309
VCC
136

Różnica między HEAD (bieżąca gałąź lub ostatni zatwierdzony stan w bieżącej gałęzi), indeksem (zwanym także obszarem przejściowym ) a drzewem roboczym (stan plików w kasie) jest opisana w sekcji „Trzy stany” w rozdziale „1.3 Podstawy Git ” rozdział książki Pro Git autorstwa Scott Chacon (licencja Creative Commons).

Oto obraz ilustrujący to z tego rozdziału:

Operacje lokalne - katalog roboczy vs. obszar pomostowy (indeks) vs repozytorium git (HEAD)

W powyższym obrazie „katalog roboczy” jest taki sam jak „drzewo robocze”, „obszar przejściowy” to alternatywna nazwa git „index”, a HEAD wskazuje na aktualnie wypisaną gałąź, która wskazuje punkty do ostatniego zatwierdzenia w „ katalog git (repozytorium) ”

Zauważ, git commit -aże wprowadzi zmiany i zatwierdzi w jednym kroku.

Jakub Narębski
źródło
1
"Obraz jest wart tysiąca słów". Dzięki, Jakub .. I dzięki za link.
Joyce Babu,
5
Uwaga: working treewydaje się być preferowane working directoryobecnie. Zobacz github.com/git/git/commit/…
VonC
2
To zdjęcie nie jest dokładnie dokładne, ponieważ Obszar przejściowy jest zawarty w jednym pliku o nazwie „indeks” - a ten plik indeksu znajduje się w katalogu głównym katalogu .git. Jeśli więc zdefiniujesz repozytorium jako katalog .git, obszar przemieszczania jest technicznie wewnątrz repozytorium. Trzecia kolumna byłaby lepiej oznaczona jako „Obiekt drzewa głównego HEAD”, aby wskazać, że pobrane pliki pochodzą z obiektu zatwierdzenia i że zatwierdzenie zapisuje nowe drzewo w obiekcie zatwierdzenia - HEAD wskazuje oba obiekty zatwierdzenia.
Jazimov
@Jazimov Prawdopodobnie masz rację, ale jak napisał, wziął to zdjęcie ze znanej książki Pro Git i podał link. Tak więc, jeśli obraz mógłby zostać poprawiony lub nawet niesłuszny, ktoś powinien powiedzieć autorom tej książki ... Ogólnie rzecz biorąc, chciałbym to zrobić, ale szczerze mówiąc, wciąż jestem początkującym początkującym i jeszcze tego nie zrobiłem zrozumiałem, co powiedziałeś, więc zdecydowanie jestem niewłaściwą osobą w tym przypadku.
Binarus,
@Binarus: Niebezpieczeństwo przy hurtowej reprodukcji takich obrazów polega na tym, że służy ono propagowaniu „fałszywego przedstawienia” jednego autora / książki. Myślę, że jest to przypadek interpretacji dosłownej kontra funkcjonalnej: w dosłownym sensie indeks jest zawarty W repozytorium, jeśli zdefiniujesz repo jako wszystko w folderze .git. Jednak w sensie funkcjonalnym indeks pomaga Gitowi utrzymać DAG w repozytorium i można go traktować jako osobę zewnętrzną.
Jazimov,
64

Twoje drzewo robocze znajduje się w plikach, nad którymi obecnie pracujesz.

HEADjest wskaźnikiem do gałęzi lub zatwierdzenia, które ostatnio wypisałeś, i który będzie rodzicem nowego zatwierdzenia, jeśli go wykonasz. Na przykład, jeśli jesteś w mastergałęzi, wtedy HEADwskaże master, a kiedy zatwierdzisz, to nowe zatwierdzenie będzie potomkiem rewizji, która masterwskazała, i masterzostanie zaktualizowane, aby wskazywało na nowe zatwierdzenie.

Wskaźnik jest obszarem, gdzie nowa inscenizacja jest gotów popełnić. Zasadniczo zawartość indeksu jest tym, co przejdzie do nowego zatwierdzenia (jeśli to zrobisz git commit -a, spowoduje to automatyczne dodanie wszystkich zmian do plików, o których Git wie o indeksie przed zatwierdzeniem, więc zatwierdzi bieżącą zawartość twojego drzewa roboczego ). git adddoda lub zaktualizuje pliki z drzewa roboczego do twojego indeksu.

Brian Campbell
źródło
Wielkie dzięki za wyjaśnienie, Brian. Więc działające drzewo zawiera wszystkie niezatwierdzone zmiany. Jeśli zatwierdzę moje zmiany za pomocą git commit -a, wówczas w tym samym czasie moje Drzewo Robocze i Indeks będą takie same. Kiedy przejdę do centralnego repozytorium, wszystkie trzy będą takie same. Mam rację?
Joyce Babu,
3
@Vinod Całkiem. Możesz mieć w swoim roboczym drzewie pliki, o których Git nie wie, i nie zostaną one zatwierdzone git commit -a(musisz je dodać git add), więc twoje drzewo robocze może zawierać dodatkowe pliki, które Twój indeks, lokalne repozytorium lub Twoje zdalne repozytorium nie ma.
Brian Campbell,
2
@Vinod: Działające drzewo i indeks mogą stać się takie same bez zatwierdzenia (git add aktualizuje indeks z drzewa roboczego, a git checkout <ścieżka> aktualizuje drzewo robocze z indeksu). HEADodnosi się do ostatniego zatwierdzenia, więc kiedy zatwierdzasz, aktualizujesz HEADdo nowego zatwierdzenia, które odpowiada indeksowi. Pchanie nie ma z tym wiele wspólnego - powoduje, że oddziały w oddziałach zdalnego dopasowywania w lokalnym repozytorium.
Cascabel,
45

Drzewo robocze

Twoje drzewo robocze to pliki, nad którymi obecnie pracujesz.

Indeks Git

  • „Indeks” git to miejsce, w którym umieszczasz pliki, które chcesz zatwierdzić w repozytorium git.

  • Indeks jest również znany jako pamięci podręcznej , pamięci podręcznej katalogu , aktualnego katalogu pamięci podręcznej , obszaru przemieszczania , wystawił plików .

  • Przed „zatwierdzeniem” (zameldowaniem) plików do repozytorium git, musisz najpierw umieścić pliki w „indeksie” git.

  • Indeks nie jest katalogiem roboczym: możesz wpisać polecenie takie jak git status, a git powie ci, jakie pliki w katalogu roboczym zostały dodane do indeksu git (na przykład za pomocą git add filenamepolecenia).

  • Indeks nie jest repozytorium git: pliki w indeksie git to pliki, które git zatwierdziłby w repozytorium git, jeśli użyto komendy git commit.

Ashraf Alam
źródło
1
Pamiętaj, że Git 2.5 przyniesie wiele działających drzew ( stackoverflow.com/a/30185564/6309 ). +1
VonC
3
Nie jestem pewien, czy „Indeks nie jest katalogiem roboczym” jest w 100% poprawny. Powinien to być „Indeks nie jest katalogiem roboczym, ale zawiera cały katalog roboczy + zmiany, które chcesz następnie zatwierdzić”. Dowód? przejdź do repozytorium git, reset --hard HEADaby upewnić się, że twój indeks == twoje drzewo robocze. a następnie: mkdir history && git checkout-index --prefix history/ -aWynikiem jest powielenie całego drzewa roboczego w twoim history/katalogu. Ergo git index> = katalog roboczy git
Adam Kurkiewicz
3
Indeks nie jest katalogiem roboczym i nie musi zawierać katalogu roboczego. Indeks to po prostu plik w repozytorium git, który przechowuje informacje o tym, co chcesz zatwierdzić.
Boon,
3
„Indeks” zawiera migawkę zawartości drzewa roboczego, i to właśnie ta migawka jest brana jako zawartość następnego zatwierdzenia. Zatem po wprowadzeniu jakichkolwiek zmian w katalogu roboczym i przed uruchomieniem polecenia zatwierdzenia, należy użyć polecenia dodaj, aby dodać nowe lub zmodyfikowane pliki do indeksu”( git-scm.com/docs/git-add )
anth
3
@AdamKurkiewicz: dowód nie powiedzie się, jeśli najpierw echo untracked-data > untracked-file, przed lub po krokach git reset --HARDi git checkout-index. Przekonasz się, że nieśledzonego pliku nie ma w historykatalogu. Możesz także niezależnie modyfikować zarówno indeks, jak i drzewo robocze, chociaż modyfikowanie indeksu bez uprzedniego dotknięcia drzewa roboczego jest trudne (wymaga użycia git update-index --index-info).
torek