Cuando especifico un objeto de confirmación de ancestro en Git, estoy confundido entre HEAD^
y HEAD~
.
Ambos tienen una versión "numerada" como HEAD^3
y HEAD~2
.
Me parecen muy similares o iguales, pero ¿hay alguna diferencia entre la tilde y el caret?
Respuestas:
Reglas de juego
~
mayor parte del tiempo: para retroceder varias generaciones, generalmente lo que desea^
en confirmaciones de combinación, porque tienen dos o más padres (inmediatos)Mnemotécnica:
~
es casi lineal en apariencia y quiere ir hacia atrás en línea recta.^
sugiere un segmento interesante de un árbol o una bifurcación en el caminoTilde
La sección "Especificación de revisiones" de la
git rev-parse
documentación define~
comoPuede llegar a los padres de cualquier compromiso, no solo
HEAD
. También puede retroceder de generación en generación: por ejemplo,master~2
significa el abuelo de la punta de la rama maestra, favoreciendo al primer padre en los compromisos de fusión.Signo de intercalación
El historial de Git es no lineal: un gráfico acíclico dirigido (DAG) o un árbol. Para un compromiso con un solo padre,
rev~
yrev^
significa lo mismo. El selector de intercalación se vuelve útil con los compromisos de fusión porque cada uno es hijo de dos o más padres, y daña el lenguaje tomado de la biología.HEAD^
significa el primer padre inmediato de la punta de la rama actual.HEAD^
es la abreviatura deHEAD^1
, y también puede abordar,HEAD^2
etc., según corresponda. La misma sección de lagit rev-parse
documentación lo define comoEjemplos
Estos especificadores o selectores se pueden encadenar arbitrariamente, por ejemplo ,
topic~3^2
en inglés es el segundo padre de la confirmación de fusión que es el bisabuelo (tres generaciones atrás) de la punta actual de la ramatopic
.La sección de la
git rev-parse
documentación mencionada anteriormente traza muchos caminos a través de una historia git nocional. El tiempo fluye generalmente hacia abajo. Los commits D, F, B y A son commits de fusión.Ejecute el siguiente código para crear un repositorio git cuyo historial coincida con la ilustración citada.
Se agrega alias de la nueva operación de usar y tirar sólo por
git lol
ygit lola
para que puedas ver la historia como enTenga en cuenta que en su máquina los nombres de los objetos SHA-1 diferirán de los anteriores, pero las etiquetas le permiten abordar las confirmaciones por nombre y verificar su comprensión.
La sección "Especificación de revisiones" en la
git rev-parse
documentación está llena de gran información y merece una lectura en profundidad. Vea también Herramientas Git - Selección de revisión del libro Pro Git .Orden de los padres se comprometen
El commit 89e4fcb0dd del propio historial de git es un commit de fusión, como se
git show 89e4fcb0dd
indica con la línea de encabezado Merge que muestra los nombres de objeto de los antepasados inmediatos.Podemos confirmar el pedido pidiendo
git rev-parse
que se muestren en secuencia los padres inmediatos de 89e4fcb0dd.Consultar al cuarto padre inexistente da como resultado un error.
Si solo desea extraer los padres, use un formato bonito
%P
para los hashes completoso
%p
para padres abreviados.fuente
^^^^^^^
lugar de~7
, ¿verdad? Por eso~
es útilLa diferencia entre
HEAD^
yHEAD~
está bien descrita en la ilustración (por Jon Loeliger) que se encuentra en http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html .Esta documentación puede ser un poco oscura para los principiantes, así que he reproducido la siguiente ilustración:
fuente
F = A^2^
.^ == ^1 == LEFTMOST PARENT
,^2 == SECOND LEFTMOST PARENT
y así sucesivamente. Y~ == ~1 == LEFTMOST PARENT
,~2 == LEFTMOST PARENTS LEFTMOST PARENT == LEFTMOST GRANDPARENT
. Por extensión,~2^2 == LEFTMOST GRANDPARENTS SECOND LEFTMOST PARENT
Ambos
~
y^
por sí solos se refieren al padre del compromiso (~~
y^^
ambos se refieren al compromiso de los abuelos, etc.) Pero difieren en significado cuando se usan con números:~2
significa dos niveles en la jerarquía , a través del primer padre si una confirmación tiene más de un padre^2
significa el segundo padre donde un commit tiene más de un padre (es decir, porque es una fusión)Estos se pueden combinar, por lo que
HEAD~2^3
significaHEAD
el compromiso del tercer padre del compromiso del abuelo.fuente
^^
era lo mismo^2
pero no lo es.Mis dos centavos...
fuente
H=A~2^2
noH=A~2^1
?A
,B
,D
,G
están en la misma rama y el envío de datosD
es una fusión deG
yH
, por lo tanto, tener dos padres. Entonces el commit (H
) de otra rama es referenciado por^2
.Aquí hay una muy buena explicación tomada textualmente de http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde :
fuente
El
^<n>
formato le permite seleccionar el enésimo padre de la confirmación (relevante en las fusiones). El~<n>
formato le permite seleccionar la enésima confirmación de antepasado, siempre siguiendo al primer padre. Consulte la documentación de git-rev-parse para ver algunos ejemplos.fuente
Vale la pena señalar que git también tiene una sintaxis para rastrear "de donde viniste" / "querer volver ahora", por ejemplo,
HEAD@{1}
hará referencia al lugar desde donde saltaste a la nueva ubicación de confirmación.Básicamente, las
HEAD@{}
variables capturan la historia del movimiento de HEAD, y puede decidir usar una cabeza en particular buscando en los registros de git usando el comandogit reflog
.Ejemplo:
Un ejemplo podría ser que hice commits locales a-> b-> c-> d y luego volví descartando 2 commits para verificar mi código
git reset HEAD~2
- y luego quiero mover mi HEAD de nuevo a d -git reset HEAD@{1}
.fuente
Simplista :
~
especifica antepasados^
especifica padresPuede especificar una o más ramas al fusionar. Entonces un commit tiene dos o más padres y luego
^
es útil para indicar padres.Supongamos que usted está en la rama A y tiene dos ramas más: B y C .
En cada rama las tres últimas confirmaciones son:
Si ahora en la rama A ejecuta el comando:
entonces está combinando tres ramas juntas (aquí su compromiso de fusión tiene tres padres)
y
~
indica el enésimo antepasado en la primera rama, entoncesHEAD~
indica A3HEAD~2
indica A2HEAD~3
indica A1^
indica el enésimo padre, entoncesHEAD^
indica A3HEAD^2
indica B3HEAD^3
indica C3El siguiente uso de
~
o^
uno al lado del otro es en el contexto del compromiso designado por los caracteres anteriores.Aviso 1 :
HEAD~3
siempre es igual a:HEAD~~~
y a:HEAD^^^
(cada indica A1 ),y en general :
HEAD~n
siempre es igual a:HEAD~...~
( n veces~
) y a:HEAD^...^
( n veces^
).Aviso 2 :
HEAD^3
no es lo mismo queHEAD^^^
(el primero indica C3 y el segundo indica A1 ),y en general :
HEAD^1
es la misma queHEAD^
,HEAD^n
siempre es lo mismo queHEAD^...^
( n veces~
).fuente
TLDR
~ es lo que quieres la mayor parte del tiempo, hace referencia a confirmaciones anteriores a la rama actual
^ referencias padres (git-merge crea un segundo padre o más)
A ~ es siempre lo mismo que A ^
A ~~ es siempre lo mismo que A ^^, y así sucesivamente
A ~ 2 no es lo mismo que A ^ 2,
porque ~ 2 es una abreviatura de ~~
mientras que ^ 2 no lo es abreviatura de cualquier cosa, significa el segundo padre
fuente
HEAD ^^^ es lo mismo que HEAD ~ 3, seleccionando el tercer commit antes de HEAD
HEAD ^ 2 especifica la segunda cabeza en un commit de fusión
fuente
HEAD ~ especifica el primer padre en una "rama"
HEAD ^ le permite seleccionar un padre específico de la confirmación
Un ejemplo:
Si desea seguir una rama lateral, debe especificar algo como
fuente
ejemplo real de la diferencia entre HEAD ~ y HEAD ^
fuente
En pocas palabras, para el primer nivel de parentesco (ascendencia, herencia, linaje, etc.) HEAD ^ y HEAD ~ ambos apuntan al mismo commit, que está (ubicado) un padre encima del HEAD (commit).
Además, HEAD ^ = HEAD ^ 1 = HEAD ~ = HEAD ~ 1. Pero HEAD ^^! = HEAD ^ 2! = HEAD ~ 2. Sin embargo, HEAD ^^ = HEAD ~ 2. Sigue leyendo.
Más allá del primer nivel de paternidad, las cosas se ponen más complicadas, especialmente si la rama de trabajo / rama maestra ha tenido fusiones (de otras ramas). También está la cuestión de la sintaxis con el cursor, HEAD ^^ = HEAD ~ 2 (son equivalentes) PERO HEAD ^^! = HEAD ^ 2 (son dos cosas completamente diferentes).
Cada / el cursor se refiere al primer padre de la CABEZA, razón por la cual los cuidados unidos entre sí son equivalentes a las expresiones tilde, porque se refieren a los primeros padres del primer padre (primer padre), etc., etc., basados estrictamente en el número de cuidados conectados o en el número que sigue a la tilde (de cualquier manera, ambos significan lo mismo), es decir, quedarse con el primer padre y subir x generaciones.
HEAD ~ 2 (o HEAD ^^) se refiere al commit que es dos niveles de ascendencia arriba / arriba del commit actual (HEAD) en la jerarquía, lo que significa el commit de los abuelos de HEAD.
HEAD ^ 2, por otro lado, no se refiere al commit del segundo padre del primer padre, sino simplemente al commit del segundo padre. Esto se debe a que el símbolo de intercalación significa el padre del compromiso, y el número siguiente significa a qué / qué compromiso primario se refiere (el primer padre, en el caso de que el número no siga al símbolo de intercalación [porque es la abreviatura del número siendo 1, que significa el primer padre]). A diferencia del símbolo de intercalación, el número que sigue después no implica otro nivel de jerarquía hacia arriba, sino que implica cuántos niveles de lado, dentro de la jerarquía, uno necesita ir a buscar el padre correcto (commit). A diferencia del número en una expresión tilde, solo está un padre arriba en la jerarquía, independientemente del número (inmediatamente) que procede del cursor. En lugar de hacia arriba, la preocupación
Entonces HEAD ^ 3 es igual al tercer padre de HEAD commit (NO el bisabuelo, que es lo que HEAD ^^^ Y HEAD ~ 3 serían ...).
fuente
~
Esto significa padre.^
si tiene padres de dos o más, como merge commit, podemos seleccionar el segundo padre u otro.así que si solo una cosa como (HEAD ~ o HEAD ^), tiene los mismos resultados.
fuente