ref^
se refiere a la confirmación antes ref
, ¿qué pasa con la confirmación después ref
?
Por ejemplo, si yo, git checkout 12345
¿cómo verifico el próximo commit?
Gracias.
PD Sí, git es un árbol de estructura de puntero de nodo DAG. ¿Cómo encuentro el commit después de este?
git
version-control
Schwern
fuente
fuente
git children-of
"!Respuestas:
Para enumerar todas las confirmaciones, comenzando por la actual, y luego su hijo, y así sucesivamente, básicamente el registro de git estándar, pero yendo hacia el otro lado en el tiempo, use algo como
donde 894e8b4e93d8f3 es la primera confirmación que desea mostrar.
fuente
HEAD^
a894e8b4e93d8f3^
....
,^..
falla en silenciofatal: unrecognized argument: --ancestry-path
en git versión 1.7.1master
está en la ruta de ascendencia de la confirmación actual. Vea el segundo fragmento de código de mi respuesta para obtener una solución que funcione en todos los casos.El creador de Hudson (ahora Jenkins) Kohsuke Kawaguchi acaba de publicar (noviembre de 2013):
kohsuke / git-children-of :
Como lo ilustra este hilo , en un VCS basado en el historial representado por un DAG (Gráfico Acíclico Dirigido) , no hay "un padre" o "un hijo".
El pedido de commits se realiza por "topo-order" o "date-order" (ver el libro de GitPro )
Pero desde Git1.6.0 , puede enumerar los elementos secundarios de una confirmación.
Nota: para las confirmaciones principales , tiene el mismo problema, con el sufijo
^
de un parámetro de revisión que significa el primer elemento primario de ese objeto de confirmación.^<n>
significa el<n>
padre th (rev^
es decir, es equivalente arev^1
).Si está en la sucursal
foo
y emite "git merge bar
",foo
será el primer padre.Es decir: el primer padre es la rama en la que estaba cuando se fusionó, y el segundo es el compromiso en la rama en la que se fusionó.
fuente
git rev-list --children
seguro se parece a lo que quiero, pero no DWIM. Parece enumerar a todos los padres y sus hijos. Supongo que puedo enumerarlos a todos y analizarlos ... bleh, pero es algo.git rev-list --children
no es solo para enumerar a los niños, sino para enumerar a los padres con sus hijos ... siempre debe analizar.$ git children0of 9dd5932
fatal: No annotated tags can describe '71d7b5dd89d241072a0a078ff2c7dfec05d52e1f'.
However, there were unannotated tags: try --tags.
¿Qué resultado obtienes?git-children-of
es que usa git describe que los intentos de formatear el SHA son legibles para los humanos, lo que puede fallar con el error de @ TomHale, y da resultados comov1.0.4-14-g2414721
si fueran confusos si esperaba un SHA. Reemplazarlo con un simple loecho
convierte en una herramienta excelente, ¡gracias!lo que encontré es
donde configuré
commit1
como el commit actual ycommit2
para el jefe actual. Esto me devuelve una lista de todos los commits que crean una ruta entrecommit1
ycommit2
.La última línea de la salida es el hijo de commit1 (en la ruta de acceso a commit2).
fuente
| tail -1
para obtener el niño.Yo sé lo que quieres decir. Es frustrante tener una sintaxis abundante para ir a confirmaciones anteriores, pero ninguna para pasar a las siguientes. En una historia compleja, el problema de "cuál es el próximo compromiso" se vuelve bastante difícil, pero luego, en la fusión compleja, surge la misma dureza con los compromisos 'anteriores' también. En el caso simple, dentro de una sola rama con un historial lineal (incluso solo localmente para un número limitado de confirmaciones) sería bueno y tendría sentido avanzar y retroceder.
Sin embargo, el verdadero problema con esto es que los commits de los niños no están referenciados, es solo una lista vinculada hacia atrás. Encontrar el child commit requiere una búsqueda, lo cual no es tan malo, pero probablemente no es algo que git quiera poner en la lógica de refspec.
En cualquier caso, me encontré con esta pregunta porque simplemente quiero avanzar en la historia, un compromiso a la vez, haciendo pruebas, y a veces hay que avanzar y no retroceder. Bueno, pensando un poco más, se me ocurrió esta solución:
Elige un compromiso antes de donde estás. Esto probablemente podría ser una cabeza de rama. Si está en la sucursal ~ 10, luego "git checkout branch ~ 9" luego "git checkout branch ~ 8" para obtener el siguiente después de eso, luego "git checkout branch ~ 7" y así sucesivamente.
Disminuir el número debería ser realmente fácil en un script si lo necesita. Mucho más fácil que analizar git rev-list.
fuente
BRANCH=master; git co $BRANCH~$[ $(git rev-list HEAD..$BRANCH | wc -l) - 1 ]
" Tienes que ir hacia una rama, no hay forma de evitar eso.Dos respuestas prácticas:
Un niño
Basado en la respuesta de @ Michael , pirateé el
child
alias en mi.gitconfig
.Funciona como se esperaba en el caso predeterminado, y también es versátil.
El valor predeterminado es dar al hijo de HEAD (a menos que se proporcione otro argumento commit-ish) siguiendo la ascendencia un paso hacia la punta de la rama actual (a menos que se proporcione otro commit-ish como segundo argumento).
Use en
%h
lugar de%H
si desea la forma hash corta.Niños múltiples
Con una CABEZA separada (no hay rama) o para obtener todos los niños independientemente de las ramas:
Cambie
$1
a$*
para imprimir todos los elementos secundarios.También puede cambiar
--all
a un commit-ish para mostrar solo los hijos que son ancestros de ese commit; en otras palabras, para mostrar solo los hijos "en la dirección de" el commit dado. Esto puede ayudarlo a reducir la producción de muchos hijos a uno solo.fuente
No hay un "próximo compromiso" único. Debido a que el historial en Git es un DAG, y no una línea, muchos commits pueden tener un padre común (ramas), y los commits pueden tener más de un padre (fusiones).
Si tiene en mente una rama en particular, puede mirar su registro y ver qué confirmación enumera la presente como su padre.
fuente
<rev>^
es "commit principal" ('primer padre' para los commits de fusión).He probado muchas soluciones diferentes y ninguna funcionó para mí. Tuve que inventar el mío.
encontrar el próximo compromiso
encontrar compromiso anterior
fuente
En el caso de que no tenga en mente una confirmación de "destino" particular, sino que desee ver las confirmaciones secundarias que podrían estar en cualquier rama, puede usar este comando:
Si desea ver a todos los hijos y nietos , debe usarlos de forma
rev-list --children
recursiva, así:(La versión que da solo nietos usaría una más compleja
sed
y / ocut
).Finalmente, puede introducir eso en un
log --graph
comando para ver la estructura de árbol, así:Nota : todos los comandos anteriores suponen que ha establecido la variable de shell
${COMMIT}
en alguna referencia (branch, tag, sha1) del commit cuyos hijos le interesan.fuente
${COMMIT}
no es, pero podría usar$(git rev-parse HEAD)
en su lugar${COMMIT}
.(Esto comenzó como una respuesta a una pregunta duplicada. He hecho un poco de edición ligera para limpiarlo).
Todas las flechas internas de Git son unidireccionales, apuntando hacia atrás. Por lo tanto, no hay una sintaxis corta y conveniente para avanzar: simplemente no es posible.
Que es posible "movimiento en contra de las flechas", pero la manera de hacerlo es sorprendente si no se ha visto antes, y luego obvia después. Digamos que tenemos:
Usando
middle~2
sigue las flechas dos veces deC
atrás aA
. Entonces, ¿cómo nos movemos deC
aD
? La respuesta es: comenzamos enE
, usando el nombrelast
, y trabajamos hacia atrás hasta llegarmiddle
, registrando los puntos que visitamos en el camino . Luego nos movemos tan lejos como queremos en la dirección delast
: mover un paso aD
, o dos aE
.Esto es particularmente importante cuando tenemos sucursales:
¿Qué commit es un paso después
C
? No hay una respuesta correcta hasta que agregue a la pregunta: en la dirección de la función___ (complete el espacio en blanco).Para enumerar las confirmaciones entre
C
(excluyendoC
) en sí y, por ejemplo,G
usamos:Esto
--topo-order
se asegura de que incluso en presencia de complejas ramificaciones y fusiones, los commits salgan en orden topológico. Esto solo es necesario si la cadena no es lineal. La--ancestry-path
restricción significa que cuando trabajamos desde atrásfeature2
, solo enumeramos los commits que tienen commitC
como uno de sus propios antepasados. Es decir, si el gráfico, o el fragmento relevante de todos modos, en realidad se ve así:una simple solicitud del formulario
feature2..master
enumera commitsJ
,G
yI
, yF
yH
en algún orden. Con--ancestry-path
noqueamosH
yI
: no son descendientes deC
, solo deA
. Con--topo-order
nos aseguramos de que el orden de enumeración real seaJ
, entoncesG
, entoncesF
.El
git rev-list
comando derrama estas identificaciones hash en su salida estándar, una por línea. Para avanzar un paso en la dirección defeature2
, entonces, solo queremos la última línea.Es posible (y tentador y puede ser útil) agregar
--reverse
para quegit rev-list
imprima las confirmaciones en orden inverso después de generarlas. Esto funciona, pero si lo usa en una tubería como esta:solo para obtener el "próximo commit en la dirección de id2", y hay una lista muy larga de commits, el
git rev-list
comando puede obtener una tubería rota cuando intenta escribir en elhead
que dejó de leer su entrada y salió. Dado que el shell normalmente ignora los errores de tubería rota, esto funciona principalmente. Solo asegúrate de que se ignoren en tu uso.También es tentador agregar
-n 1
algit rev-list
comando, junto con--reverse
. ¡No lo hagas! Eso hace quegit rev-list
pare después de caminar un paso atrás y luego revierta la lista de confirmaciones visitadas (una entrada). Entonces esto solo produce<id2>
cada vez.Nota al margen importante
Tenga en cuenta que con los fragmentos de gráfico "diamante" o "anillo de benceno":
moviendo una cometen "hacia adelante" de
H
hacialast
obtendrá ya seaI
oK
. No hay nada que pueda hacer al respecto: ¡ambas confirmaciones son un paso adelante! Si luego comienza desde la confirmación resultante y da otro paso, ahora está comprometido con cualquier ruta en la que comenzó.La cura para esto es evitar moverse un paso a la vez y quedar encerrado en cadenas dependientes de la ruta. En cambio, si planea visitar una cadena completa de ruta de ascendencia, antes de hacer cualquier otra cosa , haga una lista completa de todas las confirmaciones en la cadena:
Luego, visite cada confirmación en esta lista, una a la vez, y obtendrá toda la cadena. Se
--topo-order
asegurará de que golpeeI
-y-J
en ese orden, yK
-y-L
en ese orden (aunque no hay una manera fácil de predecir si hará el par IJ antes o después del par KL).fuente
Tengo este alias en
~/.gitconfig
fuente
f()
? Y debehead -1
ser el primer hijo, de lo contrario, esto simplemente informará a HEAD.f()
. Sí,head -1
es una suposición valiente.nextref = "!f() { git log --reverse --ancestry-path --pretty=%H $1..HEAD | head -${2:-1} | tail -1; }; f"
para que pueda elegir qué tan adelante, opcionalmenteLogré encontrar al próximo hijo de la siguiente manera:
fuente
Si los commits secundarios están todos en alguna rama, puede usar
gitk --all commit^..
, donde "commit" es algo que identifica el commit. Por ejemplo, si el SHA-1 abreviado de la confirmación es c6661c5, escribagitk --all c6661c5^..
Probablemente necesitará ingresar el SHA-1 completo en la celda "SHA1 ID:" de gitk. Necesitará el SHA-1 completo, que para este ejemplo se puede obtener a través de
git rev-parse c6661c5
Alternativamente,
git rev-list --all --children | grep '^c6661c5883bb53d400ce160a5897610ecedbdc9d'
producirá una línea que contiene todos los elementos secundarios de este commit, presumiblemente si hay una rama involucrada o no.fuente
Cada confirmación almacena un puntero a su padre (padres, en caso de confirmación de fusión (estándar)).
Por lo tanto, no hay forma de señalar un commit secundario (si hay uno) del padre.
fuente
Esta publicación ( http://www.jayway.com/2015/03/30/using-git-commits-to-drive-a-live-coding-session/#comment-282667 ) muestra una forma ordenada si lo hace si puede crear una etiqueta bien definida al final de su pila de confirmación. Esencialmente
git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`'
donde "demo-end" es la última etiqueta.fuente
Las respuestas existentes suponen que tiene una rama que contiene la confirmación que está buscando.
En mi caso, la confirmación que estaba buscando no estaba activada
git rev-list --all
ya que ninguna rama contenía eso.Terminé mirando
gitk --reflog
manualmente.Si no puede encontrar su confirmación incluso en el registro, intente:
git fsck --full
para enumerar confirmaciones colgantes (es decir, no en ninguna rama), ogit fsck --lost-found
hacer referencias apuntando a compromisos pendientes para aplicar técnicas en las otras respuestas.fuente