Quelle est la différence entre HEAD, arbre de travail et index, dans Git?

488

Quelqu'un peut-il me dire la différence entre HEAD, arbre de travail et index, dans Git?

D'après ce que je comprends, ce sont tous des noms de branches différentes. Mon hypothèse est-elle correcte?


Éditer

j'ai trouvé ça

Un seul référentiel git peut suivre un nombre arbitraire de branches, mais votre arbre de travail n'est associé qu'à une seule d'entre elles (la branche "actuelle" ou "extraite"), et HEAD pointe vers cette branche.

Est-ce à dire que la TÊTE et l'arbre de travail sont toujours les mêmes?

Joyce Babu
la source
26
En ce qui concerne votre montage: absolument pas. HEADest le commit à la pointe de la branche courante. Si vous venez de vérifier la branche, c'est-à-dire que vous n'avez pas de fichiers modifiés, son contenu correspond à l'arborescence de travail. Dès que vous modifiez quelque chose, il ne correspond plus.
Cascabel
6
Je pense que vous devez lire ceci: think-like-a-git.net
Andrzej Duś
5
J'ajouterais également un Staging Areaà cette liste. Ce qui est HEAD, Working Tree, IndexetStaging Area
Vert
2
La dernière phrase de @ Jefromi serait plus claire:> Dès que vous modifiez quoi que ce soit, l'arborescence de travail ne correspond plus au commit HEAD
starscream_disco_party
3
Pour toute lecture à l'avenir, la meilleure façon de vraiment comprendre certaines de ces réponses est de voir et de ressentir et de conceptualiser visuellement ce qui se passe: c'est le meilleur outil pour apprendre git jamais: onlywei.github.io/explain-git-with -d3 / # fetchrebase
BKSpurgeon

Réponses:

579

Quelques autres bonnes références sur ces sujets:

texte alternatif

J'utilise l'index comme point de contrôle .

Quand je suis sur le point de faire un changement qui pourrait aller de travers - quand je veux explorer une direction que je ne suis pas sûr de pouvoir suivre ou même si c'est une bonne idée, comme une refactorisation exigeante sur le plan conceptuel ou changer un type de représentation - je vérifie mon travail dans l'index. S'il s'agit du premier changement que j'ai effectué depuis mon dernier commit, je peux utiliser le référentiel local comme point de contrôle, mais j'ai souvent un changement conceptuel que j'implémente comme un ensemble de petites étapes. Je veux vérifier après chaque étape, mais enregistrez la validation jusqu'à ce que je sois revenu au code testé et fonctionnel.

Remarques:

  1. l' espace de travail est l'arborescence de répertoires des fichiers (source) que vous voyez et modifiez.

  2. L' index est un fichier binaire unique, volumineux, <baseOfRepo>/.git/indexqui répertorie tous les fichiers de la branche actuelle, leurs sommes de contrôle sha1 , les horodatages et le nom du fichier - il ne s'agit pas d'un autre répertoire contenant une copie des fichiers.

  3. Le référentiel local est un répertoire caché ( .git) comprenant un objectsrépertoire contenant toutes les versions de chaque fichier du référentiel (branches locales et copies de branches distantes) sous forme de fichier "blob" compressé.

Ne pensez pas aux quatre «disques» représentés dans l'image ci-dessus comme des copies distinctes des fichiers repo.

texte alternatif

Ce sont essentiellement des références nommées pour les validations Git. Il existe deux principaux types de références: les balises et les têtes.

  • Les balises sont des références fixes qui marquent un point spécifique de l'historique, par exemple v2.6.29.
  • Au contraire, les têtes sont toujours déplacées pour refléter la position actuelle du développement du projet.

texte alternatif

(note: comme commenté par Timo Huovinen , ces flèches ne sont pas ce que les commits indiquent, il est l' ordre de workflow , montrant essentiellement des flèches comme 1 -> 2 -> 3 -> 41est la première commettras et 4est le dernier)

Nous savons maintenant ce qui se passe dans le projet.
Mais pour savoir ce qui se passe ici, en ce moment il y a une référence spéciale appelée HEAD. Il sert deux objectifs principaux:

  • il indique à Git qui s'engage à prendre des fichiers lorsque vous passez à la caisse, et
  • il indique à Git où placer de nouveaux commits lorsque vous vous engagez.

Lorsque vous l'exécutez, git checkout refil pointe HEADvers la référence que vous avez désignée et en extrait des fichiers. Lorsque vous l'exécutez, git commitil crée un nouvel objet commit, qui devient un enfant de current HEAD. Pointe normalement HEADvers l'une des têtes, donc tout fonctionne très bien.

texte alternatif

VonC
la source
20
Après avoir lu sur git beaucoup de fois, je ne l'ai jamais complètement compris. Je suis vraiment frustré. Je veux utiliser le mot f; Mais je suis en communauté! Vous avez mentionné des têtes mais dans les images ci-dessus, il y a toujours une seule tête où sont les f ** ng têtes restantes? "Normalement, HEAD pointe vers l'une des têtes, donc tout fonctionne très bien." Je vous prie d'expliquer cela, déclaration d'Ur.
Necktwi
12
@neckTwi HEAD est le commit actuel avec lequel vous travaillez ( stackoverflow.com/a/964927/6309 ). Il s'agit généralement d'une des "têtes de branche" (l'un des commits référencés par des branches, représentant la pointe desdites branches). Mais vous pouvez extraire (et travailler) n'importe quel commit. Si vous extrayez un commit qui ne fait pas partie des têtes (de branche), vous êtes en mode "HEAD détaché": stackoverflow.com/a/3965714/6309
VonC
1
@Imray Je suis d'accord, mais c'est ainsi que j'ai trouvé ces photos il y a 5 ans ( hades.name/blog/2010/01/28/… )
VonC
11
En ce qui concerne l'index, je pense que la chose la plus utile qui puisse être dite est "L'index est juste un autre nom pour la zone de transit", comme l'a dit @ ashraf-alam. J'ai l'impression que la plupart du temps dans la discussion, c'est ce qu'on appelle la zone de transit, c'est pourquoi je n'ai pas établi automatiquement la connexion que c'était la même chose que l'index.
Pete
1
@Pete, je suis d'accord. Pour en savoir plus sur la différence entre le cache et l'index, voir mon autre réponse stackoverflow.com/a/6718135/6309
VonC
137

La différence entre HEAD (branche actuelle ou dernier état validé sur la branche actuelle), l' index (aka. Zone de transit) et l' arborescence de travail (l'état des fichiers en cours de paiement) est décrite dans la section "Les trois états" de la section "1.3 Git Basics " chapitre du livre Pro Git de Scott Chacon (licence Creative Commons).

Voici l'image l'illustrant de ce chapitre:

Opérations locales - répertoire de travail vs zone de transit (index) vs référentiel git (HEAD)

Dans l'image ci-dessus, "répertoire de travail" est identique à "arbre de travail", la "zone de transit" est un autre nom pour git "index" et HEAD pointe vers la branche actuellement extraite, qui pointe pour la dernière validation dans le " répertoire git (référentiel) "

Notez que cela git commit -amettrait en place des changements et s'engagerait en une seule étape.

Jakub Narębski
la source
1
"Une image vaut mieux que mille mots". Merci Jakub .. Et merci pour le lien.
Joyce Babu
5
Remarque: working treesemble être préféré à working directorynos jours. Voir github.com/git/git/commit/…
VonC
3
Cette image n'est pas exactement précise car la zone de transit est contenue dans un seul fichier appelé "index" - et ce fichier d'index se trouve à la racine du répertoire .git. Donc, si vous définissez le référentiel comme le répertoire .git, la zone de transfert est techniquement à l'intérieur du référentiel. La troisième colonne serait mieux intitulée "Objet d'arborescence racine de HEAD" pour indiquer que les fichiers extraits proviennent d'un objet commit et que la validation écrit une nouvelle arborescence dans un objet commit - les deux objets commit sont pointés par HEAD.
Jazimov
@Jazimov Vous avez probablement raison, mais comme il l'a écrit, il a pris cette photo du célèbre livre Pro Git, et il a fourni un lien. Ainsi, si l'image pouvait être améliorée ou même erronée, quelqu'un devrait en informer les auteurs de ce livre ... En général, je serais prêt à le faire, mais pour être honnête, je suis toujours un débutant et je n'ai pas encore compris ce que vous avez dit, donc je ne suis certainement pas la bonne personne dans ce cas.
Binarus
@Binarus: Le danger dans la reproduction en gros d'images comme celle-ci est qu'elle sert à propager une "fausse déclaration" faite par un auteur / livre. Je pense que c'est un cas d'interprétations littérales contre fonctionnelles ici: au sens littéral, l'index est en fait contenu dans le référentiel si vous définissez le référentiel comme tout dans le dossier .git. Dans le sens fonctionnel, cependant, l'indice aide Git à maintenir le DAG dans le référentiel et peut être considéré comme un être extérieur à celui-ci.
Jazimov
64

Votre arborescence de travail est ce qui se trouve réellement dans les fichiers sur lesquels vous travaillez actuellement.

HEADest un pointeur sur la branche ou le commit que vous avez extrait en dernier, et qui sera le parent d'un nouveau commit si vous le faites. Par exemple, si vous êtes sur la masterbranche, alors HEADpointera vers master, et lorsque vous validerez, ce nouveau commit sera un descendant de la révision qui masterpointait vers, et mastersera mis à jour pour pointer vers le nouveau commit.

L' index est une zone intermédiaire dans laquelle le nouveau commit est préparé. Essentiellement, le contenu de l'index est ce qui ira dans la nouvelle validation (bien que si vous le faites git commit -a, cela ajoutera automatiquement toutes les modifications des fichiers que Git connaît à l'index avant de valider, donc il validera le contenu actuel de votre arborescence de travail ). git addajoutera ou mettra à jour des fichiers de l'arborescence de travail dans votre index.

Brian Campbell
la source
Merci beaucoup pour l'explication Brian. Ainsi, l'arborescence de travail contient toutes les modifications non validées. Si je valide mes modifications avec git commit -a, à ce moment précis, mon arbre de travail et mon index seront les mêmes. Quand je pousse vers mon référentiel central, les trois seront les mêmes. Ai-je raison?
Joyce Babu
3
@Vinod À peu près. Vous pouvez avoir des fichiers dans votre arborescence de travail que Git ne connaît pas, et ceux-ci ne seront pas validés git commit -a(vous devez les ajouter avec git add), donc votre arborescence de travail peut avoir des fichiers supplémentaires que votre index, votre référentiel local ou votre repo à distance ne dispose pas.
Brian Campbell
2
@Vinod: L'arbre de travail et l'index peuvent devenir les mêmes sans validation (git add met à jour l'index à partir de l'arbre de travail, et git checkout <path> met à jour l'arbre de travail à partir de l'index). HEADfait référence à la validation la plus récente, donc lorsque vous validez, vous mettez à jour HEADvotre nouvelle validation, qui correspond à l'index. Pousser n'a pas grand-chose à voir avec cela - cela fait des branches dans les branches de correspondance distantes dans votre référentiel local.
Cascabel
45

Arbre de travail

Votre arborescence de travail sont les fichiers sur lesquels vous travaillez actuellement.

Index Git

  • Le git "index" est l'endroit où vous placez les fichiers que vous souhaitez valider dans le référentiel git.

  • L'indice est également connu sous le nom cache , cache de répertoire , cache du répertoire courant , la zone de mise en scène , les fichiers mis en scène .

  • Avant de «valider» (archiver) des fichiers dans le référentiel git, vous devez d'abord placer les fichiers dans «l'index» git.

  • L'index n'est pas le répertoire de travail: vous pouvez taper une commande telle que git status, et git vous dira quels fichiers de votre répertoire de travail ont été ajoutés à l'index git (par exemple, en utilisant la git add filenamecommande).

  • L'index n'est pas le référentiel git: les fichiers de l'index git sont des fichiers que git validerait dans le référentiel git si vous utilisiez la commande git commit.

Ashraf Alam
la source
1
Notez que Git 2.5 apportera plusieurs arborescences de travail ( stackoverflow.com/a/30185564/6309 ). +1
VonC
3
Je ne suis pas sûr que "l'index n'est pas le répertoire de travail" est 100% correct. Il doit s'agir de "L'index n'est pas le répertoire de travail, mais il inclut le répertoire de travail entier + les modifications que vous souhaitez enregistrer ensuite". Preuve? allez dans un dépôt git, reset --hard HEADpour vous assurer que votre index == votre arbre de travail. an then: mkdir history && git checkout-index --prefix history/ -aLe résultat est une duplication de tout votre arbre de travail dans votre history/répertoire. Ergo git index> = répertoire de travail git
Adam Kurkiewicz
3
L'index n'est pas le répertoire de travail et ne doit pas inclure le répertoire de travail. L'index est juste un fichier dans le référentiel git qui stocke les informations que vous souhaitez valider.
Boon
3
"L'index" contient un instantané du contenu de l'arborescence de travail, et c'est cet instantané qui est pris comme contenu du prochain commit. Ainsi, après avoir apporté des modifications au répertoire de travail et avant d'exécuter la commande commit, vous doit utiliser la commande add pour ajouter tout fichier nouveau ou modifié à l'index "( git-scm.com/docs/git-add )
anth
3
@AdamKurkiewicz: la preuve échoue si vous commencez echo untracked-data > untracked-file, avant ou après les étapes git reset --HARDet git checkout-index. Vous constaterez que le fichier non suivi ne se trouve pas dans le historyrépertoire. Vous pouvez également modifier à la fois l'index et l'arbre de travail indépendamment, bien que la modification de l'index sans toucher d'abord l'arbre de travail soit difficile (nécessite l'utilisation git update-index --index-info).
torek