Ves la documentación de Git que dice cosas como
La rama debe estar completamente fusionada en HEAD.
Pero, ¿qué es HEAD
exactamente Git ?
Ves la documentación de Git que dice cosas como
La rama debe estar completamente fusionada en HEAD.
Pero, ¿qué es HEAD
exactamente Git ?
Respuestas:
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 .
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 checkout
o git reset
etc.
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.
git revert
no es un buen ejemplo de mover una rama para que no esté en la punta, porque git revert
solo crea algunas confirmaciones nuevas y aún deja la rama actual en la punta (nueva).
commit
s, reset
s, etc.
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.
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
¿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.
34ac2
en 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.
git log
y obtuviste algo así commit ad0265... HEAD -> foo ...
, la foo
rama es una referencia para confirmar la identificación ad0265
. Hacer un pago de la referencia de texto foo
no es una cabeza separada. Hacer un pago de la identificación de confirmación ad0265
darí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.
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, HEAD
significa:
HEAD
siempre se refiere a la confirmación más reciente en la rama actual. Cuando cambia de sucursales,HEAD
se actualiza para referirse a la última confirmación de la nueva sucursal.
entonces
HEAD
es la "punta" de la rama actual .
Tenga en cuenta que podemos usar HEAD
para referirnos a la confirmación más reciente, y usar HEAD~
como confirmación antes de la sugerencia, HEAD~~
o HEAD~2
como confirmación incluso antes, y así sucesivamente.
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
?
HEAD
es 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, HEAD
se moverá. Si pagas algo, HEAD
se moverá. Hagas lo que hagas, si te has mudado a un lugar nuevo en tu historial de commit, se HEAD
ha 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.
HEAD
puede apuntar a un commit, sí, pero generalmente no lo hace. Déjame decirlo de nuevo. Por HEAD
lo 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, commit
o 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 HEAD
apunta directamente a un commit. Esto se llama un HEAD separado, porque HEAD
apunta a algo más que una referencia de rama. Si realiza una confirmación en este estado, master
ya 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 HEAD
está 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
.
HEAD
eres 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á.
.git/HEAD
es lo que el software considera como HEAD.
HEAD
se 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.
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 .
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.
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.
master
rama, por lo que HEAD apuntará a master.
master
, pero no siempre es así. Verremote set-head
remote set-head
, que solo afecta la rama local predeterminada y no cambiará la predeterminada en el servidor.
La cabeza apunta a la punta de la rama actualmente desprotegida.
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
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.
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:
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.
HEAD
no es un commit; que apunta a uno.
checkout HEAD^
, ahora HEAD ni siquiera apunta a la última instantánea de confirmación en ninguna rama.
commit
, merge
, rebase
, log
, etc, pero conceptualmente tal vez "(puntero a) la posición actual" es un resumen bien.
Parece que eso HEAD
es 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")
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.
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.
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.
HEAD
refiere 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 HEAD
estado separado ).
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/refs
que están en el repositorio en el que está trabajando.
Git
Se trata de commits.
Y Head
señ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
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 .