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^3y 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-parsedocumentació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~2significa 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^2etc., según corresponda. La misma sección de lagit rev-parsedocumentación lo define comoEjemplos
Estos especificadores o selectores se pueden encadenar arbitrariamente, por ejemplo ,
topic~3^2en 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-parsedocumentació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 lolygit lolapara 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-parsedocumentació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 89e4fcb0ddindica con la línea de encabezado Merge que muestra los nombres de objeto de los antepasados inmediatos.Podemos confirmar el pedido pidiendo
git rev-parseque 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
%Ppara los hashes completoso
%ppara 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 PARENTy así sucesivamente. Y~ == ~1 == LEFTMOST PARENT,~2 == LEFTMOST PARENTS LEFTMOST PARENT == LEFTMOST GRANDPARENT. Por extensión,~2^2 == LEFTMOST GRANDPARENTS SECOND LEFTMOST PARENTAmbos
~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:~2significa dos niveles en la jerarquía , a través del primer padre si una confirmación tiene más de un padre^2significa 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^3significaHEADel compromiso del tercer padre del compromiso del abuelo.fuente
^^era lo mismo^2pero no lo es.Mis dos centavos...
fuente
H=A~2^2noH=A~2^1?A,B,D,Gestán en la misma rama y el envío de datosDes una fusión deGyH, 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~2indica A2HEAD~3indica A1^indica el enésimo padre, entoncesHEAD^indica A3HEAD^2indica B3HEAD^3indica C3El siguiente uso de
~o^uno al lado del otro es en el contexto del compromiso designado por los caracteres anteriores.Aviso 1 :
HEAD~3siempre es igual a:HEAD~~~y a:HEAD^^^(cada indica A1 ),y en general :
HEAD~nsiempre es igual a:HEAD~...~( n veces~) y a:HEAD^...^( n veces^).Aviso 2 :
HEAD^3no es lo mismo queHEAD^^^(el primero indica C3 y el segundo indica A1 ),y en general :
HEAD^1es la misma queHEAD^,HEAD^nsiempre 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