HEAD y ORIG_HEAD en Git

252

¿A qué se refieren estos símbolos y qué significan?

(No puedo encontrar ninguna explicación en la documentación oficial)

collimarco
fuente
44
Nota: HEADahora es (próximo git1.8.4) ' @'! Vea mi respuesta editada a continuación
VonC
Nota-bis: ' @' (para HEAD) todavía está llegando, pero no para 1.8.4 respuesta editada y modificada .
VonC
1
Nota ter: ' @' para HEADestá de vuelta para git 1.8.5 / 1.9. respuesta editada de nuevo .
VonC
21
HEADy ORIG_HEADen Git son como $PWDy $OLDPWDen Bash. :)
musiphil

Respuestas:

325

HEADes una referencia (directa o indirecta, es decir, simbólica) a la confirmación actual. Es una confirmación que ha verificado en el directorio de trabajo (a menos que haya realizado algunos cambios, o equivalente), y es una confirmación sobre la cual "git commit" haría una nueva. Usualmente HEADes una referencia simbólica a alguna otra rama nombrada; esta rama está actualmente desprotegida o actual. HEADtambién puede apuntar directamente a un commit; Este estado se denomina "CABEZA separada" y puede entenderse como una rama anónima sin nombre.

Y @solo es un atajo para HEAD, ya que Git 1.8.5

ORIG_HEADes un estado anterior HEAD, establecido por comandos que tienen un comportamiento posiblemente peligroso, para que sea fácil revertirlos. Es menos útil ahora que Git tiene reflog: HEAD@{1}es aproximadamente equivalente a ORIG_HEAD( HEAD@{1}siempre es el último valor de HEAD, ORIG_HEADes el último valor HEADantes de la operación peligrosa).

Para obtener más información, lea la página de manual de git (1) , el Manual del usuario de Git , el Libro de la comunidad de Git y el Glosario de Git

Jakub Narębski
fuente
2
Hola jakub +1 para la explicación. ¿Podría detallar la parte "más o menos equivalente" de HEAD @ {1}? Me refiero en mi respuesta al hilo thread.gmane.org/gmane.comp.version-control.git/38379 (estaban en él, en febrero de 2007), y no entendí exactamente la discusión que tenían alrededor. la sintaxis @ {...}.
VonC
19
ORIG_HEAD se establece (creo) solo mediante comandos 'peligrosos', que mueven HEAD más de una confirmación. Entonces ORIG_HEAD no siempre está configurado, mientras que HEAD @ {1} siempre está configurado. @ {1} es $ (git symbolic-ref HEAD) @ {1}, es decir, utiliza reflog para la rama actual, no HEAD reflog.
Jakub Narębski
Riiight ... Lo entiendo ahora :) Gracias por esa aclaración. Por lo que vale, ¡también voté por tu comentario!
VonC
1
"y HEAD es un commit además del cual" git commit "haría uno nuevo." - es bueno recordarlo, ¡gracias! También de @VonC, "Es la compilación" git commit "se construye encima y" git diff --cached "y" git status "se comparan con".
Minqi Pan
1
Las revisiones de ayuda de git muestran git-scm.com/docs/gitrevisions , que describe todas las formas de hacer referencia a los commits (incluyendo HEADy ORIG_HEAD).
dahlbyk
104

Desde git reset

"pull" o "merge" siempre deja la punta original de la rama actual ORIG_HEAD.

git reset --hard ORIG_HEAD

Al restablecerlo de manera difícil, el archivo de índice y el árbol de trabajo vuelven a ese estado, y restablece la punta de la rama a esa confirmación.

git reset --merge ORIG_HEAD

Después de inspeccionar el resultado de la fusión, puede encontrar que el cambio en la otra rama no es satisfactorio. Ejecutar " git reset --hard ORIG_HEAD" le permitirá volver a donde estaba, pero descartará los cambios locales que no desea. " git reset --merge" mantiene sus cambios locales.


Antes de aplicar cualquier parche, ORIG_HEAD se establece en la punta de la rama actual.
Esto es útil si tiene problemas con múltiples confirmaciones, como ejecutar ' git am' en la rama incorrecta o un error en las confirmaciones que se corrige más fácilmente al cambiar el buzón (por ejemplo, + errores en las líneas "De:").

Además, la combinación siempre establece ' .git/ORIG_HEAD' al estado original de HEAD, por lo que se puede eliminar una combinación problemática usando ' git reset ORIG_HEAD'.


Nota: desde aquí

HEAD es un puntero en movimiento. A veces significa la rama actual, a veces no.

Entonces HEAD NO es sinónimo de "rama actual" en todas partes.

HEAD significa "actual" en todas partes en git, pero no necesariamente significa "rama actual" (es decir, HEAD separada).

Pero casi siempre significa el "compromiso actual".
Es el commit " git commit" se construye encima y " git diff --cached" y " git status" se compara con.
Significa la rama actual solo en contextos muy limitados (exactamente cuando queremos que funcione un nombre de rama --- restablecer y aumentar la punta de la rama a través de commit / rebase / etc.).

Reflog es un vehículo para retroceder en el tiempo y las máquinas del tiempo tienen una interacción interesante con la noción de "actual".

HEAD@{5.minutes.ago}podría significar "desreferenciar HEAD symref para averiguar en qué rama estamos AHORA MISMO, y luego averiguar dónde estaba la punta de esa rama hace 5 minutos".
Alternativamente, podría significar "cuál es la confirmación a la que me habría referido como HEAD hace 5 minutos, por ejemplo, si" git show HEAD "en ese entonces".


git1.8.4 (julio de 2013) introduce introdujo una nueva notación!
(en realidad, será para 1.8.5 o 1.9, cuarto trimestre de 2013: reintroducido con commit 9ba89f4 )

En lugar de escribir cuatro letras mayúsculas " HEAD", puede decir " @" ahora,
por ejemplo " git log @".

Ver commit cdfd948

Escribir ' HEAD' es tedioso, especialmente cuando podemos usar ' @' en su lugar.

La razón para elegir " @es que se sigue naturalmente de la ref@opsintaxis (por ejemplo HEAD@{u}), excepto que no tenemos referencia ni operación, y cuando no las tenemos, tiene sentido suponer HEAD".

Así que ahora podemos usar ' git show @~1', y toda esa bondad.

Hasta ahora ' @' era un nombre válido, pero entra en conflicto con esta idea, así que hagámoslo inválido. Probablemente muy pocas personas, si alguna, usaron este nombre.


Una publicación en el blog durante el período 1.8.4-rc3 (14 de agosto de 2013) anunció que esta característica fue revertida y retrasada (Gracias Cupcake por el aviso ).
Nuevamente, se presenta nuevamente con commit 9ba89f4 (septiembre de 2013).

Ver commit 2c2b664 :

Revertir "Agregar nuevo @acceso directo para HEAD"

Esto revierte el compromiso cdfd948 , ya que no solo se aplica a " @" (y a formularios con modificadores similares @{u}), sino que también afecta, por ejemplo, a " refs/heads/@/foo", que no debería.

La idea básica de dar una abreviatura podría ser buena, y el tema se puede volver a tratar más adelante, pero volvamos para evitar afectar los casos de uso existentes por ahora para el próximo lanzamiento.

VonC
fuente
Después de ejecutar git reset ORIG_HEAD y commit. ORIG_HEAD todavía está allí bajo Referencias junto a HEAD. ¿Por qué no se eliminó de la vista?
powder366
@ powder366 pero a git resetgenerará a ORIG_HEAD. Entonces lo necesitas rmmanualmente. Ver stackoverflow.com/a/12418078/6309 por ejemplo.
VonC
1
@VonC el @alias para HEADestá siendo revertida (temporalmente?) Para la versión 1.8.4 de Git ! ¡Se acaba de anunciar hoy!
Disfruté el comentario "heads-up"!
Robino
2

Entiendo que HEAD señala la rama actual, mientras que ORIG_HEAD se usa para almacenar el HEAD anterior antes de realizar operaciones "peligrosas".

Por ejemplo, git-rebase y git-am registran la punta original de la rama antes de que apliquen cualquier cambio.

ínimo
fuente
44
HEAD no siempre apunta a la rama actual (se puede separar)
VonC
1
Entonces, ¿cuál es la "rama actual" cuando HEAD está "desconectado"?
cjs
@ CurtJ.Sampson Eso es "sin sucursal". Es por eso que cuando estás en la cabeza separada, lo haces git branch foo -bpara "crear" una rama para que los huérfanos se comprometan.
Royi Namir
1

De man 7 gitrevisions:

HEAD nombra la confirmación en la que basó los cambios en el árbol de trabajo. FETCH_HEAD registra la rama que obtuvo de un repositorio remoto con su última invocación de obtención de git. ORIG_HEAD se crea mediante comandos que mueven su HEAD de manera drástica, para registrar la posición de la HEAD antes de su operación, de modo que pueda cambiar fácilmente la punta de la rama al estado antes de ejecutarlas. MERGE_HEAD registra las confirmaciones que está fusionando en su rama cuando ejecuta git merge. CHERRY_PICK_HEAD registra la confirmación que está seleccionando cuando ejecuta git cherry-pick.

Nathan Chappell
fuente