tipos - git ver archivos modificados
¿Cómo encuentro el próximo commit en git? (14)
Dos respuestas prácticas:
Un niño
Basado en la respuesta de .gitconfig
alias child
en mi .gitconfig
.
Funciona como se esperaba en el caso predeterminado, y también es versátil.
# Get the child commit of the current commit.
# Use $1 instead of ''HEAD'' if given. Use $2 instead of curent branch if given.
child = "!bash -c ''git log --format=%H --reverse --ancestry-path ${1:-HEAD}..${2:/"$(git rev-parse --abbrev-ref HEAD)/"} | head -1'' -"
Por defecto, se le da al hijo de HEAD (a menos que se proporcione otro argumento de commit-ish) siguiendo el ancestro un paso hacia la punta de la rama actual (a menos que se proporcione otro commit-ish como segundo argumento).
Usa %h
vez de %H
si quieres la forma corta de hash.
Múltiples niños
Con una cabeza separada (no hay rama) o para obtener todos los niños, independientemente de las ramas:
# For the current (or specified) commit-ish, get the all children, print the first child
children = "!bash -c ''c=${1:-HEAD}; set -- $(git rev-list --all --not /"$c/"^@ --children | grep $(git rev-parse /"$c/") ); shift; echo $1'' -"
Cambie $1
a $*
para imprimir todos los niños
ref^
refiere a la confirmación antes de la ref
, ¿qué pasa con la confirmación después de ref
?
Por ejemplo, si selecciono git checkout 12345
¿cómo git checkout 12345
el siguiente compromiso?
Gracias.
PD Sí, git es un árbol de estructura de puntero de nodo DAG. ¿Cómo encuentro el compromiso después de este?
Cada confirmación almacena un puntero a su padre (padres, en el caso de una fusión (estándar)).
Por lo tanto, no hay forma de señalar a un compromiso hijo (si hay uno) del padre.
El creador de Hudson (ahora Jenkins) Kohsuke Kawaguchi acaba de publicar (noviembre de 2013):
kohsuke / git-children-of :
Dado un compromiso, encuentre hijos inmediatos de ese compromiso.
#!/bin/bash -e
# given a commit, find immediate children of that commit.
for arg in "$@"; do
for commit in $(git rev-parse $arg^0); do
for child in $(git log --format=''%H %P'' --all | grep -F " $commit" | cut -f1 -d'' ''); do
git describe $child
done
done
done
Como se ilustra en 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".
C1 -> C2 -> C3
/ /
A -> B E -> F
/ /
D1 -> D2 ----/
El orden de confirmaciones se realiza por "orden topográfica " o "orden de fecha" (ver el libro GitPro )
Pero desde Git1.6.0 , puede enumerar los hijos de una confirmación.
git rev-list --children
git log --children
Nota: para las confirmaciones de los padres , tiene el mismo problema, con el sufijo ^
para un parámetro de revisión que significa el primer padre de ese objeto de confirmación. ^<n>
significa que el <n>
padre (es decir, rev^
es equivalente a rev^1
).
Si está en la sucursal foo
y emite " git merge bar
", entonces foo
será el primer padre.
Es decir: el primer padre es la rama en la que estaba cuando se fusionó, y el segundo es la confirmación en la rama en la que se fusionó.
En el caso de que no tenga en mente un "destino" en particular, sino que desee ver confirmaciones hijo que podrían estar en cualquier rama, puede usar este comando:
git rev-list --children --all | grep ^${COMMIT}
Si desea ver a todos los niños y nietos , debe usar rev-list --children
recursively, de esta manera:
git rev-list --children --all | /
egrep ^/($(git rev-list --children --all | /
grep ^${COMMIT} | /
sed ''s/ /|/g'')/)
(La versión que solo da grand-children usaría un sed
y / o cut
más complejo).
Finalmente, puede alimentar eso en un comando log --graph
para ver la estructura del árbol, de esta manera:
git log --graph --oneline --decorate /
/^${COMMIT}^@ /
$(git rev-list --children --all | /
egrep ^/($(git rev-list --children --all | /
grep ^${COMMIT} | /
sed ''s/ /|/g'')/))
En mi caso, el compromiso que estaba buscando no estaba en git rev-list --all
, todos, ya que ninguna rama contenía eso. Terminé mirando a través de gitk --reflog
manualmente.
Esta publicación ( http://www.jayway.com/2015/03/30/using-git-commits-to-drive-a-live-coding-session/#comment-282667 ) muestra una forma clara de hacerlo si puede crear una etiqueta bien definida al final de su pila de compromisos. Esencialmente git config --global alias.next ''!git checkout `git rev-list HEAD..demo-end | tail -1`''
git config --global alias.next ''!git checkout `git rev-list HEAD..demo-end | tail -1`''
donde "demo-end" es la última etiqueta.
He intentado muchas soluciones diferentes y ninguna funcionó para mí. Tuve que inventar el mío.
encontrar el siguiente compromiso
function n() {
git log --reverse --pretty=%H master | grep -A 1 $(git rev-parse HEAD) | tail -n1 | xargs git checkout
}
encontrar compromiso previo
function p() {
git checkout HEAD^1
}
Logré encontrar al siguiente hijo de la siguiente manera:
git log --reverse --children -n1 HEAD (where ''n'' is the number of children to show)
No hay un único "próximo compromiso". Debido a que el historial en Git es un DAG, y no una línea, muchos commits pueden tener un elemento primario común (branches), y commits puede tener más de un padre (fusionarse).
Si tiene una rama en particular en mente, puede mirar su registro y ver qué commit enumera el presente como su padre.
Para enumerar todas las confirmaciones, empezando por la actual, y luego por su hijo, y así sucesivamente, básicamente el registro de git estándar, pero yendo para el otro lado en el tiempo, use algo como
git log --reverse --ancestry-path 894e8b4e93d8f3^..master
donde 894e8b4e93d8f3 es el primer compromiso que desea mostrar.
Si el niño se compromete en una sucursal, puede usar gitk --all commit^..
, donde "commit" es algo que identifica la confirmación. Por ejemplo, si la abreviatura SHA-1 del compromiso es c6661c5, escriba gitk --all c6661c5^..
Probablemente necesites 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''
git rev-list --all --children | grep ''^c6661c5883bb53d400ce160a5897610ecedbdc9d''
producirá una línea que contiene todos los elementos git rev-list --all --children | grep ''^c6661c5883bb53d400ce160a5897610ecedbdc9d''
de esta confirmación, presumiblemente si hay una rama involucrada o no.
Tengo este alias en ~/.gitconfig
first-child = "!f() { git log --reverse --ancestry-path --pretty=%H $1..${2:-HEAD} | head -1; }; f"
Yo sé lo que quieres decir. Es frustrante tener una sintaxis abundante para ir a compromisos previos, pero ninguno para ir a los siguientes. En una historia compleja, el problema de "lo que es el siguiente compromiso" se vuelve bastante difícil, pero luego, en la fusión compleja, también emerge la misma dureza con los compromisos "previos". En el caso simple, dentro de una sola rama con una historia lineal (incluso a nivel local para un número limitado de confirmaciones) sería bueno y tendría sentido avanzar y retroceder.
El verdadero problema con esto, sin embargo, es que los commits de los niños no están referenciados, es solo una lista de enlaces hacia atrás. Encontrar la confirmación del niño requiere una búsqueda, que no es tan mala, 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 dar un paso adelante en la historia que uno comete a la vez, haciendo pruebas, y algunas veces tiene que dar un paso adelante y no hacia atrás. Bueno, con un poco más de pensamiento, 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ás en la rama ~ 10, entonces "git checkout branch ~ 9" luego "git checkout branch ~ 8" para obtener la 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.
lo que encontré es
git rev-list --ancestry-path commit1..commit2
donde establezco commit1
como el commit actual y commit2
para el head actual. Esto me devuelve una lista de todas las confirmaciones que crean una ruta entre commit1
y commit2
.
La última línea del resultado es el elemento secundario de commit1 (en la ruta de commit2).