¿Qué es HEAD en Git?

Respuestas:

775

Puedes pensar en HEAD como la "rama actual". Cuando cambia de rama con git checkout, la revisión HEAD cambia para apuntar a la punta de la nueva rama.

Puedes ver lo que HEAD señala haciendo:

cat .git/HEAD

En mi caso, el resultado es:

$ cat .git/HEAD
ref: refs/heads/master

Es posible que HEAD haga referencia a una revisión específica que no está asociada con un nombre de sucursal. Esta situación se llama CABEZA separada .

Greg Hewgill
fuente
53
Entonces git HEAD depende del contexto en qué RAMA estás, ¿correcto? Aún más, usted como desarrollador? Supongo que estoy preguntando: ¿Git HEAD va a ser una cosa global en todo el repositorio, o individual para cada desarrollador?
bobobobo
9191
@bobobobo: Así es, HEAD es como un puntero que apunta a la rama actual. Cuando finaliza la compra de una rama diferente, HEAD cambia para apuntar a la nueva. El HEAD actual es local para cada repositorio y, por lo tanto, es individual para cada desarrollador.
Greg Hewgill
16
@Meng Este me ayudó, espero que ayude: marklodato.github.com/visual-git-guide/index-en.html
raphael
54
@ 動靜 能量: HEAD puede apuntar a cualquier confirmación, no es necesario que sea la última confirmación en ninguna rama. (Cuando HEAD apunta a un commit que no es el último commit en una rama, ese es un "HEAD separado").
Greg Hewgill
127
HEAD no es "la rama actual". Is es el nombre dado al commit desde el cual se inicializó el estado actual del árbol de trabajo. En términos más prácticos, puede considerarse como una referencia simbólica al commit desprotegido.
Ben Collins
184

Para citar a otras personas :

Una cabeza es simplemente una referencia a un objeto de confirmación. Cada cabeza tiene un nombre (nombre de rama o nombre de etiqueta, etc.). Por defecto, hay un encabezado en cada repositorio llamado maestro. Un repositorio puede contener cualquier cantidad de cabezas. En cualquier momento, se selecciona una cabeza como la "cabeza actual". Esta cabeza tiene alias HEAD, siempre en mayúsculas ".

Tenga en cuenta esta diferencia: un "encabezado" (minúscula) se refiere a cualquiera de los encabezados nombrados en el repositorio; "CABEZA" (mayúscula) se refiere exclusivamente a la cabeza actualmente activa. Esta distinción se usa con frecuencia en la documentación de Git.

Aquí se puede encontrar otra buena fuente que cubre rápidamente el funcionamiento interno de git (y, por lo tanto, una mejor comprensión de las cabezas / CABEZA) . Las referencias (ref :) o encabezados o ramas pueden considerarse como notas post-it pegadas en commits en el historial de commit. Por lo general, apuntan a la punta de una serie de confirmaciones, pero se pueden mover con git checkouto git resetetc.

Silfheed
fuente
De esto: "Cada cabeza tiene un nombre". Y "una cabeza se selecciona como la" cabeza actual ". Esta cabeza tiene alias HEAD ". Entonces concluyo de esto que "CABEZA" no se refiere a la situación del estado "CABEZA separada".
gxyd
1
@gxyd si es el caso de que HEAD no apunta a una 'cabeza', es una HEAD separada. Está apuntando a la identificación de confirmación de la confirmación que ha especificado (usando, por ejemplo, git checkout HEAD~2), que no es la identificación de confirmación de un encabezado conocido. Consulte el artículo en eagain.net/articles/git-for-computer-scientists para obtener una explicación más detallada.
Silfheed
1
@Silfheed: en general, creo que esta respuesta es conceptualmente más sólida que la aceptada (aunque el uso de "cabeza" en minúscula para referirse a una rama confunde a muchas personas). Sin embargo, git revertno es un buen ejemplo de mover una rama para que no esté en la punta, porque git revertsolo crea algunas confirmaciones nuevas y aún deja la rama actual en la punta (nueva).
LarsH
1
"que no es la identificación de confirmación de una cabeza conocida": en realidad, una CABEZA separada puede apuntar a una identificación de confirmación que también es la identificación de confirmación de una cabeza conocida (o varias cabezas). Lo que lo distingue es que HEAD apunta directamente a la ID de confirmación, no a una cabeza. Esto afectará el comportamiento de futuros commits, resets, etc.
LarsH
1
@LarsH: Buen punto en un HEAD separado que apunta a una ID de confirmación en lugar de una referencia. En realidad, puede verificar esto mirando .git / HEAD. Si está separado, contendrá el hash de una confirmación, incluso si es la misma confirmación que una cabeza conocida. Si está adjunto, contendrá la ruta a la cabeza (es decir, 'ref: refs / heads / bob'). En cuanto al comando revertir, después de 8 años, nunca entendí ese error tipográfico. El restablecimiento de Git es lo que le permite ajustar una cabeza particular para apuntar a una confirmación particular.
Silfheed
62

Recomiendo esta definición del desarrollador de github Scott Chacon [ referencia de video ]:

Head es tu rama actual. Es una referencia simbólica. Es una referencia a una rama. Siempre tienes HEAD, pero HEAD señalará a uno de estos otros punteros, a una de las ramas en las que estás. Es el padre de su próximo compromiso. Es lo que debería ser lo que se verificó por última vez en su directorio de trabajo ... Este es el último estado conocido de cuál era su directorio de trabajo.

Todo el video dará una introducción justa a todo el sistema git, por lo que también te recomiendo que lo veas todo si tienes tiempo para hacerlo.

jasoares
fuente
34
Así que la verdadera definición es "el padre de tu próximo commit"
nicolas
1
y también "lo que apunta a la próxima rama que se moverá"
nicolas
@nicolas - No creo que sea cierto. HEAD puede apuntar a cualquier confirmación, no necesariamente tiene que apuntar a una rama; cuando no lo hace, está en modo "HEAD separado".
scubbo
23
El video es excelente, pero desafortunadamente, es una respuesta inadecuada para Stack Overflow. ¿Qué pasa si el video se elimina en algún momento en el futuro? Entonces su enlace no apuntará a nada. Una mejor respuesta incluiría una transcripción de lo que Scott dice en el video.
2
Scott dice que HEAD es un puntero a una rama. Pero HEAD también puede señalar viejos compromisos. Esto es muy confuso.
Fixee
60

HEAD es solo un puntero especial que apunta a la rama local en la que se encuentra actualmente.

Del libro Pro Git , capítulo 3.1 Git Branching - Branches in a Nutshell , en la sección Crear una nueva rama :

¿Qué sucede si creas una nueva sucursal? Bueno, hacerlo crea un nuevo puntero para que te muevas. Supongamos que crea una nueva rama llamada prueba. Lo haces con el comando git branch:

$ git branch testing 

Esto crea un nuevo puntero en el mismo commit en el que estás actualmente

ingrese la descripción de la imagen aquí

¿Cómo sabe Git en qué rama estás actualmente? Mantiene un puntero especial llamado HEAD. Tenga en cuenta que esto es muy diferente al concepto de HEAD en otros VCS a los que puede estar acostumbrado, como Subversion o CVS. En Git, este es un puntero a la rama local en la que se encuentra actualmente. En este caso, todavía estás en master. El comando git branch solo creó una nueva rama, no cambió a esa rama.

ingrese la descripción de la imagen aquí

Alexandr
fuente
44
Agradable, podría usar una imagen que muestra el caso HEAD separado
Don Hatch
@DonHatch, buena explicación de HEAD separado stackoverflow.com/a/35301963/1074179
Alexandr
3
Buena respuesta. Las ramas no son más que confirmaciones etiquetadas, cuando realiza nuevas confirmaciones, esta etiqueta se mueve a la nueva confirmación nueva. Cuando revisa un commit que no tiene una etiqueta, está en estado HEAD separado. Eso significa que HEAD está apuntando a una confirmación que no tiene una etiqueta de rama. Si realiza el pago 34ac2en el ejemplo anterior, ahora HEAD apuntaría a ese compromiso y se llama HEAD separado. En este estado, también puede realizar cambios, experimentar y confirmar los cambios, pero una vez que realice el pago de una rama diferente, perderá todos sus cambios, a menos que, por supuesto, cree una nueva rama.
sleepwalkerfx
1
@sleepwalkerfx, pero puede verificar una confirmación que tiene una etiqueta de rama y aún estar en estado de cabecera separada porque su CABEZA ya no está apuntando a la etiqueta de la rama sino a la identificación de confirmación de la rama
Marc
1
@sleepwalkerfx Creo que estamos hablando de semántica en este momento. Estás en lo correcto, una etiqueta de rama es una referencia de texto a una confirmación particular. Sin embargo, no es un compromiso. Entonces si hiciste ungit log y obtuviste algo así commit ad0265... HEAD -> foo ..., la foorama es una referencia para confirmar la identificación ad0265. Hacer un pago de la referencia de texto foono es una cabeza separada. Hacer un pago de la identificación de confirmación ad0265daría como resultado una cabeza separada. Puede ser que me falta algo de sutileza de lo que estás comunicando. Espero que este muro de texto ayude a descubrir dónde estoy perdido.
Marc
40

Suponiendo que no es un caso especial llamado "CABEZA separada", entonces, como se indica en el libro de O'Reilly Git, segunda edición, p.69, HEADsignifica:

HEADsiempre se refiere a la confirmación más reciente en la rama actual. Cuando cambia de sucursales, HEADse actualiza para referirse a la última confirmación de la nueva sucursal.

entonces

HEADes la "punta" de la rama actual .

Tenga en cuenta que podemos usar HEADpara referirnos a la confirmación más reciente, y usar HEAD~como confirmación antes de la sugerencia, HEAD~~o HEAD~2como confirmación incluso antes, y así sucesivamente.

nonopolaridad
fuente
27

Hay una idea errónea, quizás sutil, pero importante en un número de estas respuestas. Pensé agregar mi respuesta para aclararlo.

¿Qué es HEAD?

La cabeza es usted

HEADes una referencia simbólica que apunta a donde sea que esté en su historial de confirmaciones. Te sigue donde quiera que vayas, hagas lo que hagas, como una sombra. Si realiza una confirmación, HEADse moverá. Si pagas algo, HEADse moverá. Hagas lo que hagas, si te has mudado a un lugar nuevo en tu historial de commit, se HEADha movido contigo. Para abordar un error común: no puedes desapegarte de ti HEAD. Eso no es lo que es un estado HEAD separado. Si alguna vez te encuentras pensando: "¡oh no, estoy en estado de CABEZA separada! ¡He perdido la CABEZA!" Recuerda, es tu CABEZA. CABEZA eres tú. No se ha separado de la CABEZA, usted y su CABEZA se han separado de otra cosa.

¿A qué se puede unir HEAD?

HEADpuede apuntar a un commit, sí, pero generalmente no lo hace. Déjame decirlo de nuevo. Por HEADlo general , no apunta a una confirmación. Apunta a una referencia de rama. Se adjunta a esa rama, y ​​cuando haces ciertas cosas (por ejemplo, commito reset), la rama adjunta se moverá junto con HEAD. Puedes ver a qué apunta mirando debajo del capó.

cat .git/HEAD

Normalmente obtendrás algo como esto:

ref: refs/heads/master

A veces obtendrás algo como esto:

a3c485d9688e3c6bc14b06ca1529f0e78edd3f86

Eso es lo que sucede cuando HEADapunta directamente a un commit. Esto se llama un HEAD separado, porque HEADapunta a algo más que una referencia de rama. Si realiza una confirmación en este estado, masterya no se adjuntará HEAD, ya no se moverá junto con usted. No importa dónde esté ese compromiso. Podría estar en el mismo compromiso que su rama maestra, pero si HEADestá apuntando a la confirmación en lugar de a la rama, se desconecta y una nueva confirmación no se asociará con una referencia de rama.

Puede ver esto gráficamente si intenta el siguiente ejercicio. Desde un repositorio git, ejecute esto. Obtendrá algo ligeramente diferente, pero los bits clave estarán allí. Cuando llegue el momento de pagar el commit directamente, simplemente use cualquier hash abreviado que obtenga de la primera salida (aquí está 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, entonces hay una pequeña diferencia en la salida aquí. Revisar el commit directamente (en lugar de la rama) nos da una coma en lugar de una flecha. ¿Qué piensas, estamos en un estado HEAD separado? HEAD todavía se está refiriendo a una revisión específica que está asociada con un nombre de sucursal. Todavía estamos en la rama maestra, ¿no?

Ahora intenta:

git status
# HEAD detached at a3c485d

No Estamos en estado de "CABEZA separada".

Puede ver la misma representación de (HEAD -> branch)vs. (HEAD, branch)con git log -1.

En conclusión

HEADeres tu. Apunta a lo que haya verificado, esté donde esté. Por lo general, eso no es una confirmación, es una rama. Si HEAD lo hace el punto de una confirmación (o etiqueta), incluso si es el mismo commit (o etiqueta) de que una rama también señala, usted (y HEAD) se han desprendido de esa rama. Como no tiene una rama adjunta, la rama no lo seguirá junto con usted cuando realice nuevas confirmaciones. HEAD, sin embargo, lo hará.

De Novo
fuente
1
Me gusta esta respuesta, porque mientras la documentación describe la verdad, el software define la verdad. .git/HEADes lo que el software considera como HEAD.
Don Branson el
2
Solo por su definición conceptual, esta debería ser la respuesta aceptada.
ata
22

HEADse refiere a la confirmación actual a la que apunta su copia de trabajo, es decir, la confirmación que actualmente ha extraído. De la documentación oficial de Linux Kernel sobre la especificación de revisiones de Git :

HEAD nombra la confirmación en la que basó los cambios en el árbol de trabajo.

Sin embargo, tenga en cuenta que en la próxima versión 1.8.4 de Git, @también se puede usar como una abreviatura para HEAD, como señaló el colaborador de Git, Junio ​​C Hamano, en su blog Git Blame :

En lugar de escribir "HEAD", puede decir "@", por ejemplo, "git log @".

El usuario de Stack Overflow VonC también encontró información interesante sobre por qué@ fue elegido como abreviatura en su respuesta a otra pregunta .

También es interesante, en algunos entornos no es necesario capitalizar HEAD, específicamente en sistemas operativos que usan sistemas de archivos que no distinguen entre mayúsculas y minúsculas, específicamente Windows y OS X.

Comunidad
fuente
17

Echa un vistazo a Crear y jugar con ramas

HEAD es en realidad un archivo cuyo contenido determina a dónde se refiere la variable HEAD:

$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
35ede5c916f88d8ba5a9dd6afd69fcaf773f70ed

En este repositorio, el contenido del archivo HEAD se refiere a un segundo archivo llamado refs / heads / master . El archivo refs / heads / master contiene el hash del commit más reciente en la rama master.

El resultado es HEAD apunta a la confirmación de la rama maestra desde el archivo .git / refs / heads / master .

ingrese la descripción de la imagen aquí

onmyway133
fuente
1
Cuidado: el enlace gitguys.com parece apuntar a un dominio estacionado.
MKesper
14

Solo me gustaría detallar algunas cosas en la respuesta aceptada de Greg Hewgil. De acuerdo con la guía de bolsillo Git

Rama:

la rama en sí se define como todos los puntos alcanzables en el gráfico de confirmación desde la confirmación nombrada (la "punta" de la rama).

CABEZA: Un tipo especial de referencia

La referencia especial HEAD determina en qué rama estás ...

Refs

Git define dos tipos de referencias, o punteros con nombre, a los que llama "referencias":

  • Una referencia simple, que apunta directamente a una ID de objeto (generalmente una confirmación o etiqueta)
  • Una referencia simbólica (o symref), que apunta a otra referencia (ya sea simple o simbólica)

Como Greg mencionó, HEAD puede estar en un "estado separado". Entonces HEAD puede ser una simple referencia (para una HEAD separada) o un symref.

si HEAD es una referencia simbólica para una rama existente, entonces usted está "en" esa rama. Si, por otro lado, HEAD es una referencia simple que nombra directamente un commit por su ID SHA-1, entonces no está "en" ninguna rama, sino más bien en el modo "HEAD separado", lo que sucede cuando comprueba algunos antes comprometerse a examinar.

Miguel
fuente
¡Gracias, @mike! Esta es la primera respuesta que aclara lo que sucede cuando revisa una confirmación anterior. Al mirar el libro en el sitio web de git, tuve la impresión de que una "CABEZA desprendida" era un estado patológico en el que solo te encontrabas si hacías algo extraño. Pero verificar una confirmación anterior no es algo extraño, y cuando haces eso, HEAD no es "la punta de la rama actual". Así que esta es la primera vez que siento que realmente entiendo.
Nat Kuhn
7

Creo que 'HEAD' es la confirmación de salida actual. En otras palabras, 'HEAD' apunta al commit que está actualmente desprotegido.

Si acaba de clonar y no ha desprotegido, no sé a qué apunta, probablemente alguna ubicación no válida.

Nataraj
fuente
Sí, la referencia especial HEADes cualquier confirmación que haya verificado actualmente. Consulte el manual para obtener detalles (el párrafo correspondiente sigue inmediatamente a la Fig. 3.4).
Calrion
1
Si clonas un repositorio, git verificará por defecto la masterrama, por lo que HEAD apuntará a master.
sleske
1
@sleske si clonas un repositorio sin opciones especiales, git revisará el cabezal remoto. suele ser master, pero no siempre es así. Verremote set-head
De Novo
Mi comentario anterior fue correcto, excepto por la referencia a remote set-head, que solo afecta la rama local predeterminada y no cambiará la predeterminada en el servidor.
De Novo
5

La cabeza apunta a la punta de la rama actualmente desprotegida.

ingrese la descripción de la imagen aquí

En su repositorio, hay una carpeta .git. Abra el archivo en esta ubicación: .git \ refs \ heads. El código (sha-1 hash) en ese archivo (maestro en la mayoría de los casos) será el commit más reciente, es decir, el que se ve en la salida del comando git log. Más información sobre la carpeta .git: http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html

stack1
fuente
1
Es un error común pensar que la punta de la rama actual apunta a la confirmación más reciente. Por lo general, eso es cierto, pero tampoco es infrecuente git reset HEAD^, y luego la confirmación más reciente (el consejo anterior) ya no es señalada por la punta de la rama.
LarsH
4

Una excelente manera de conducir a casa el punto señalado en las respuestas correctas es correr git reflog HEAD, obtener un historial de todos los lugares que HEAD ha señalado.

tjb
fuente
4

Después de leer todas las respuestas anteriores, aún quería más claridad. Este blog en el sitio web oficial de git http://git-scm.com/blog me dio lo que estaba buscando:

La CABEZA: Puntero para la última instantánea de confirmación, el próximo padre

El HEAD en Git es el puntero a la referencia de rama actual, que a su vez es un puntero a la última confirmación que realizó o la última confirmación que se desprotegió en su directorio de trabajo. Eso también significa que será el padre de la próxima confirmación que hagas. En general, es más simple pensar que HEAD es la instantánea de su último commit.

usuario3751385
fuente
1
El HEAD: última instantánea de confirmación, el próximo padre no es exacto. HEADno es un commit; que apunta a uno.
jub0bs
No hay necesidad de sarcasmo; antes de su edición, a pesar de que la cita era precisa, las grandes letras en negrita eran una simplificación y un poco engañosas. Ahora es mejor.
jub0bs
1
SI lee la siguiente línea: HEAD en Git es el puntero a la referencia de rama actual, que a su vez es un puntero a la última confirmación que realizó o la última confirmación que se verificó en su directorio de trabajo. - Tenga en cuenta el uso de la palabra "puntero" allí.
user3751385
Si bien la descripción de la "última instantánea de confirmación" da una idea conceptual de cómo se supone que se debe usar HEAD, en realidad no es precisa. Si hago una confirmación, luego cambio a otra rama, HEAD ya no señala la última instantánea de confirmación. Apunta a la última instantánea de confirmación en la rama a la que acabo de cambiar. Si yo checkout HEAD^, ahora HEAD ni siquiera apunta a la última instantánea de confirmación en ninguna rama.
LarsH
"El padre de su próxima confirmación (si tuviera que comprometerse ahora)" es más preciso, pero hay muchas otras operaciones en git además de la confirmación que se ven afectadas por HEAD. En realidad, al final, la cabeza es la cabeza, y su naturaleza es definida por la forma en que afecta a los comandos como commit, merge, rebase, log, etc, pero conceptualmente tal vez "(puntero a) la posición actual" es un resumen bien.
LarsH
3

Parece que eso HEADes solo una etiqueta para la última confirmación que verificó.

Esto puede ser la punta de una rama específica (como "maestro") o alguna confirmación intermedia de una rama ("cabeza separada")

Vertexwahn
fuente
1

Además de todas las definiciones, lo que se me quedó grabado en la mente fue que, cuando realiza una confirmación, GIT crea un objeto de confirmación dentro del repositorio. Los objetos de confirmación deben tener un elemento primario (o varios elementos principales si es una confirmación de fusión). Ahora, ¿cómo sabe git el padre de la confirmación actual? Entonces HEAD es un puntero a la (referencia del) último commit que se convertirá en el padre del commit actual.

Anwar Husain
fuente
0

Estos dos pueden confundirte:

cabeza

Apuntando a referencias nombradas que una rama envió recientemente. A menos que use la referencia del paquete, los encabezados generalmente se almacenan en $ GIT_DIR / refs / heads /.

CABEZA

Rama actual, o su árbol de trabajo generalmente se genera a partir del árbol al que apunta HEAD. HEAD debe apuntar a una cabeza, excepto que esté usando una HEAD separada.

Marcus Thornton
fuente
0

Echa un vistazo a http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is

Figura 3-5. Archivo HEAD que apunta a la rama en la que se encuentra.

Ting Wang
fuente
44
Las respuestas de solo enlace generalmente están mal vistas en Stackoverflow, por favor, incluya la información relevante en su respuesta.
HaskellElephant
2
Esto no es del todo correcto. Lo que se HEADrefiere depende de si estás hablando de un repositorio desnudo o no. En el contexto de un repositorio no descubierto, se refiere efectivamente al commit actualmente desprotegido, que no requiere que haya una rama adjunta (es decir, cuando está en HEADestado separado ).
0

Una rama es en realidad un puntero que contiene una ID de confirmación como 17a5 . HEAD es un puntero a una rama en la que el usuario está trabajando actualmente.

HEAD tiene un archivo de referencia que se ve así:

árbitro:

Puede verificar estos archivos accediendo a los .git/HEAD .git/refsque están en el repositorio en el que está trabajando.

Okd
fuente
0

GitSe trata de commits.
Y Headseñala la confirmación que actualmente verificó.

$ git cat-file -t HEAD
commit

Cada vez que realiza el pago de una rama, el HEAD señala la última confirmación en esa rama. El contenido de HEAD puede verificarse de la siguiente manera (para la rama maestra):

$ cat .git/refs/heads/master
  b089141cc8a7d89d606b2f7c15bfdc48640a8e25
SR Chaitanya
fuente
-5

Como concepto, la cabeza es la última revisión en una rama. Si tiene más de un encabezado por rama con nombre, probablemente lo haya creado al hacer confirmaciones locales sin fusionar, creando efectivamente una rama sin nombre.

Para tener un repositorio "limpio", debe tener un encabezado por rama con nombre y siempre combinarse con una rama con nombre después de trabajar localmente.

Esto también es cierto para Mercurial .

dukeofgaming
fuente
44
Esto es cierto para Mercurial, pero no para Git.
Restablece a Monica - notmaynard