Vous voyez la documentation de Git disant des choses comme
La branche doit être complètement fusionnée dans HEAD.
Mais qu'est-ce que Git HEAD
exactement?
Vous voyez la documentation de Git disant des choses comme
La branche doit être complètement fusionnée dans HEAD.
Mais qu'est-ce que Git HEAD
exactement?
Réponses:
Vous pouvez considérer la HEAD comme la "branche actuelle". Lorsque vous changez de branche avec git checkout
, la révision HEAD change pour pointer vers la pointe de la nouvelle branche.
Vous pouvez voir ce que HEAD pointe en faisant:
cat .git/HEAD
Dans mon cas, la sortie est:
$ cat .git/HEAD
ref: refs/heads/master
Il est possible que HEAD fasse référence à une révision spécifique qui n'est pas associée à un nom de branche. Cette situation est appelée une tête détachée .
Pour citer d' autres personnes :
Une tête est simplement une référence à un objet commit. Chaque tête a un nom (nom de branche ou nom de tag, etc.). Par défaut, il y a une tête dans chaque référentiel appelé master. Un référentiel peut contenir n'importe quel nombre de têtes. À tout moment, une tête est sélectionnée comme «tête actuelle». Cette tête est aliasée à HEAD, toujours en majuscules ".
Notez cette différence: une «tête» (en minuscules) fait référence à l'une des têtes nommées dans le référentiel; «HEAD» (majuscule) se réfère exclusivement à la tête actuellement active. Cette distinction est fréquemment utilisée dans la documentation Git.
Une autre bonne source qui couvre rapidement le fonctionnement interne de git (et donc une meilleure compréhension des têtes / HEAD) peut être trouvée ici . Les références (ref :) ou les têtes ou les branches peuvent être considérées comme des notes post-it collées sur les commits dans l'historique des commit. Habituellement, ils pointent vers la pointe d'une série de validations, mais ils peuvent être déplacés avec git checkout
ou git reset
etc.
git checkout HEAD~2
), qui n'est pas l'ID de validation d'une tête connue. Voir l'article sur eagain.net/articles/git-for-computer-scientists pour une explication plus approfondie.
git revert
n'est pas un bon exemple de déplacer une branche pour qu'elle ne soit pas à la pointe, car elle git revert
crée simplement de nouveaux commits et laisse toujours la branche actuelle à la (nouvelle) pointe.
commit
s, reset
s, etc.
Je recommande cette définition du développeur de github Scott Chacon [ référence vidéo ]:
Head est votre branche actuelle. C'est une référence symbolique. C'est une référence à une branche. Vous avez toujours HEAD, mais HEAD pointera vers l'un de ces autres pointeurs, vers l'une des branches sur lesquelles vous vous trouvez. C'est le parent de votre prochain commit. C'est ce qui devrait être le dernier extrait dans votre répertoire de travail ... C'est le dernier état connu de votre répertoire de travail.
La vidéo entière donnera une introduction équitable à l'ensemble du système git, donc je vous recommande également de tout regarder si vous en avez le temps.
HEAD est juste un pointeur spécial qui pointe vers la branche locale sur laquelle vous vous trouvez actuellement.
Dans le livre Pro Git , chapitre 3.1 Git Branching - Branches in a Nutshell , dans la section Création d'une nouvelle branche :
Que se passe-t-il si vous créez une nouvelle succursale? Eh bien, cela crée un nouveau pointeur pour vous déplacer. Supposons que vous créez une nouvelle branche appelée testing. Pour ce faire, utilisez la commande git branch:
$ git branch testing
Cela crée un nouveau pointeur au même commit que vous êtes actuellement
Comment Git sait-il dans quelle branche vous vous trouvez actuellement? Il garde un pointeur spécial appelé HEAD. Notez que cela est très différent du concept de HEAD dans d'autres VCS auxquels vous pouvez être habitué, tels que Subversion ou CVS. Dans Git, il s'agit d'un pointeur vers la branche locale sur laquelle vous vous trouvez actuellement. Dans ce cas, vous êtes toujours maître. La commande git branch n'a créé qu'une nouvelle branche - elle n'a pas basculé vers cette branche.
34ac2
exemple ci-dessus, maintenant HEAD pointerait vers ce commit et il s'appelle un HEAD détaché. Dans cet état, vous pouvez également apporter des modifications, expérimenter et valider des modifications, mais une fois que vous avez extrait une branche différente, vous perdriez toutes vos modifications, à moins bien sûr de créer une nouvelle branche.
git log
et obtenu quelque chose comme commit ad0265... HEAD -> foo ...
ça, la foo
branche est une référence pour valider l'ID ad0265
. Faire une extraction de la référence de texte foo
n'est pas une tête détachée. Faire une extraction de l'ID de validation ad0265
entraînerait une tête détachée. Peut-être que je manque une subtilité de ce que vous communiquez. J'espère que ce mur de texte permet de découvrir où je suis perdu.
En supposant qu'il ne s'agit pas d'un cas spécial appelé "tête détachée", alors, comme indiqué dans le livre O'Reilly Git, 2e édition, p.69, HEAD
signifie:
HEAD
fait toujours référence au commit le plus récent sur la branche actuelle. Lorsque vous changez de branche,HEAD
est mis à jour pour faire référence au dernier commit de la nouvelle branche.
donc
HEAD
est la "pointe" de la branche actuelle .
Notez que nous pouvons utiliser HEAD
pour faire référence au commit le plus récent, et utiliser HEAD~
comme commit avant la pointe, et HEAD~~
ou HEAD~2
comme commit encore plus tôt, et ainsi de suite.
Il y a une idée fausse, peut-être subtile, mais importante dans un certain nombre de ces réponses. J'ai pensé ajouter ma réponse pour clarifier les choses.
Qu'est-ce que c'est
HEAD
?
HEAD
est une référence symbolique pointant où que vous soyez dans votre historique de commit. Il vous suit partout où vous allez, quoi que vous fassiez, comme une ombre. Si vous faites un commit,HEAD
se déplacera. Si vous réglez quelque chose, HEAD
se déplacera. Quoi que vous fassiez, si vous avez déménagé quelque part de nouveau dans votre historique de commit, HEAD
vous avez déménagé avec vous. Pour remédier à une idée fausse commune: vous ne pouvez pas vous en détacher HEAD
. Ce n'est pas ce qu'est un état HEAD détaché. Si vous vous retrouvez à penser: "oh non, je suis dans un état de TÊTE détaché! J'ai perdu ma TÊTE!" Rappelez-vous, c'est votre tête. HEAD c'est vous. Vous ne vous êtes pas détaché de la TÊTE, vous et votre TÊTE vous êtes détachés d'autre chose.
HEAD
peut pointer vers un commit, oui, mais ce n'est généralement pas le cas. Permettez-moi de le répéter. Ne pointe généralement HEAD
pas vers une validation. Il pointe vers une référence de branche. Elle est attachée à cette branche, et lorsque vous faites certaines choses (par exemple, commit
ou reset
), la branche attachée se déplace avecHEAD
. Vous pouvez voir ce qu'il indique en regardant sous le capot.
cat .git/HEAD
Normalement, vous obtiendrez quelque chose comme ceci:
ref: refs/heads/master
Parfois, vous obtiendrez quelque chose comme ceci:
a3c485d9688e3c6bc14b06ca1529f0e78edd3f86
C'est ce qui arrive quand HEAD
pointe directement sur un commit. C'est ce qu'on appelle un HEAD détaché, car il HEAD
pointe vers autre chose qu'une référence de branche. Si vous faites un commit dans cet état, master
n'étant plus attaché à HEAD
, vous ne bougerez plus avec vous. Peu importe où se trouve cet engagement.Vous pouvez être sur le même commit que votre branche principale, mais si HEAD
pointe sur le commit plutôt que sur la branche, il est détaché et un nouveau commit ne sera pas associé à une référence de branche.
Vous pouvez regarder ceci graphiquement si vous essayez l'exercice suivant. À partir d'un référentiel git, exécutez ceci. Vous obtiendrez quelque chose de légèrement différent, mais les bits clés seront là. Quand il est temps de vérifier le commit directement, utilisez simplement le hachage abrégé que vous obtenez de la première sortie (le voici a3c485d
).
git checkout master
git log --pretty=format:"%h: %d" -1
# a3c485d: (HEAD -> master)
git checkout a3c485d -q # (-q is for dramatic effect)
git log --pretty=format:"%h: %d" -1
# a3c485d: (HEAD, master)
OK, il y a donc une petite différence dans la sortie ici. Vérifier directement le commit (au lieu de la branche) nous donne une virgule au lieu d'une flèche. Que pensez-vous, sommes-nous dans un état détaché HEAD? HEAD fait toujours référence à une révision spécifique associée à un nom de branche. Nous sommes toujours sur la branche maître, n'est-ce pas?
Maintenant essaye:
git status
# HEAD detached at a3c485d
Nan. Nous sommes dans un état de «tête détachée».
Vous pouvez voir la même représentation de (HEAD -> branch)
vs (HEAD, branch)
avec git log -1
.
HEAD
est toi. Il indique ce que vous avez vérifié, où que vous soyez. Ce n'est généralement pas un commit, c'est une branche. Si le HEAD
fait le point à un commit (ou tag), même si elle est la même commit (ou tag) qu'une branche aussi des points à, vous (et HEAD
) ont été détachés de cette branche. Comme vous n'avez pas de branche attachée à vous, la branche ne vous suivra pas lorsque vous effectuez de nouveaux commits. HEAD
cependant.
.git/HEAD
est ce que le logiciel considère comme HEAD.
HEAD
fait référence à la validation actuelle vers laquelle pointe votre copie de travail, c'est-à-dire la validation que vous avez actuellement extraite. De la documentation officielle du noyau Linux sur la spécification des révisions Git :
HEAD
nomme la validation sur laquelle vous avez basé les modifications dans l'arborescence de travail.
Notez, cependant, que dans la prochaine version 1.8.4 de Git, @
peut également être utilisé comme raccourci pourHEAD
, comme l'a noté le contributeur Git Junio C Hamano dans son blog Git Blame :
Au lieu de taper "HEAD", vous pouvez dire "@" à la place, par exemple "git log @".
L'utilisateur de Stack Overflow VonC a également trouvé des informations intéressantes sur les raisons@
été choisi comme raccourci dans sa réponse à une autre question .
Il est également intéressant de noter que dans certains environnements, il n'est pas nécessaire de capitaliser HEAD
, en particulier dans les systèmes d'exploitation qui utilisent des systèmes de fichiers insensibles à la casse, en particulier Windows et OS X.
Jetez un œil à Créer et jouer avec les branches
HEAD est en fait un fichier dont le contenu détermine où la variable HEAD fait référence:
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
35ede5c916f88d8ba5a9dd6afd69fcaf773f70ed
Dans ce référentiel, le contenu du fichier HEAD fait référence à un second fichier nommé refs / heads / master . Le fichier refs / heads / master contient le hachage du commit le plus récent sur la branche master.
Le résultat est que HEAD pointe vers la validation de la branche master à partir du fichier .git / refs / heads / master .
Je voudrais juste détailler certaines choses dans la réponse acceptée de Greg Hewgil. Selon le Git Pocket Guide
Branche:
la branche elle-même est définie comme tous les points accessibles dans le graphe de commit à partir du commit nommé (le «tip» de la branche).
TETE: Un type spécial de Réf
La référence spéciale HEAD détermine sur quelle branche vous vous trouvez ...
Réfs
Git définit deux types de références, ou pointeurs nommés, qu'il appelle «refs»:
- Une référence simple, qui pointe directement vers un ID d'objet (généralement une validation ou une balise)
- Une référence symbolique (ou symref), qui pointe vers une autre référence (simple ou symbolique)
Comme Greg l'a mentionné, HEAD peut être dans un "état détaché". Ainsi, HEAD peut être soit une simple référence (pour une HEAD détachée), soit une symref.
si HEAD est une référence symbolique pour une branche existante, alors vous êtes «sur» cette branche. Si, d'un autre côté, HEAD est une simple référence nommant directement un commit par son ID SHA-1, alors vous n'êtes pas «sur» une branche, mais plutôt en mode «HEAD détaché», ce qui se produit lorsque vous en vérifiez quelques-uns plus tôt s'engager à examiner.
Je pense que "HEAD" est le check-out actuel. En d'autres termes, 'HEAD' pointe vers le commit qui est actuellement extrait.
Si vous venez de cloner et de ne pas avoir vérifié, je ne sais pas à quoi cela correspond, probablement un emplacement non valide.
master
branche - donc HEAD pointera vers master.
master
, mais ce n'est pas toujours le cas. Voirremote set-head
remote set-head
, qui n'impacte que la branche par défaut locale et ne changera pas la valeur par défaut sur le serveur.
Head pointe vers la pointe de la branche actuellement extraite.
Dans votre référentiel, il y a un dossier .git. Ouvrez le fichier à cet emplacement: .git \ refs \ heads. Le code (de hachage sha-1) dans ce fichier (maître dans la plupart des cas) sera le commit le plus récent, c'est-à-dire celui vu dans la sortie de la commande git log
. Plus d'informations sur le dossier .git: http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html
git reset HEAD^
, et le dernier commit (l'ancien tip) n'est plus pointé par le tip de la branche.
Après avoir lu toutes les réponses précédentes, je voulais toujours plus de clarté. Ce blog sur le site officiel de git http://git-scm.com/blog m'a donné ce que je cherchais:
Le HEAD dans Git est le pointeur vers la référence de branche actuelle, qui est à son tour un pointeur vers le dernier commit que vous avez fait ou le dernier commit qui a été extrait dans votre répertoire de travail. Cela signifie également que ce sera le parent du prochain commit que vous ferez. Il est généralement plus simple de penser à cela car HEAD est l'instantané de votre dernier commit.
HEAD
n'est pas un commit; il en indique un.
checkout HEAD^
, maintenant, HEAD ne pointe même pas vers le dernier instantané de validation sur une branche.
commit
, merge
, rebase
, log
, etc. Mais sur le plan conceptuel peut - être « (pointeur) la position actuelle » est un bon résumé.
C'est comme ça HEAD
soit juste une balise pour le dernier commit que vous avez extrait.
Cela peut être la pointe d'une branche spécifique (telle que "maître") ou une validation intermédiaire d'une branche ("tête détachée")
En plus de toutes les définitions, la chose qui m'est restée à l'esprit était que lorsque vous effectuez une validation, GIT crée un objet de validation dans le référentiel. Les objets de validation doivent avoir un parent (ou plusieurs parents s'il s'agit d'une validation de fusion). Maintenant, comment git connaît-il le parent du commit actuel? Donc, HEAD est un pointeur vers la (référence du) dernier commit qui deviendra le parent du commit actuel.
Ces deux peuvent vous dérouter:
tête
Pointant vers des références nommées, une branche a récemment soumis. Sauf si vous utilisez la référence du package, les têtes sont généralement stockées dans $ GIT_DIR / refs / heads /.
TÊTE
La branche actuelle ou votre arbre de travail est généralement généré à partir de l'arborescence vers laquelle pointe HEAD. HEAD doit pointer vers une tête, sauf que vous utilisez une tête détachée.
Jetez un œil à http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is
Figure 3-5. Fichier HEAD pointant vers la branche sur laquelle vous vous trouvez.
HEAD
fait référence dépend de si vous parlez d'un dépôt nu vs non repo. Dans le contexte d'un dépôt non nu, il fait effectivement référence à la validation actuellement extraite, qui ne nécessite pas qu'une branche lui soit attachée (c'est-à-dire lorsqu'il est à l' HEAD
état détaché ).
Une branche est en fait un pointeur qui contient un ID de validation tel que 17a5 . HEAD est un pointeur sur une branche sur laquelle l'utilisateur travaille actuellement.
HEAD a un filw de référence qui ressemble à ceci:
réf:
Vous pouvez vérifier ces fichiers en accédant à ceux .git/HEAD
.git/refs
qui se trouvent dans le référentiel dans lequel vous travaillez.
Git
est une question de commits.
Et Head
pointe sur le commit que vous avez actuellement extrait.
$ git cat-file -t HEAD
commit
Chaque fois que vous extrayez une branche, le HEAD pointe vers le dernier commit sur cette branche. Le contenu de HEAD peut être vérifié comme ci-dessous (pour la branche principale):
$ cat .git/refs/heads/master
b089141cc8a7d89d606b2f7c15bfdc48640a8e25
En tant que concept, la tête est la dernière révision d'une branche. Si vous avez plus d'une tête par branche nommée, vous l'avez probablement créée lorsque vous effectuez des validations locales sans fusionner, créant ainsi une branche sans nom.
Pour avoir un référentiel "propre", vous devez avoir une tête par branche nommée et toujours fusionner avec une branche nommée après avoir travaillé localement.
Cela est également vrai pour Mercurial .