traductores - Hacer referencia al niño de un compromiso en Git
que es traducir (10)
Si desea mover la HEAD
al padre de la HEAD
actual, es fácil:
git reset --hard HEAD^
Pero, ¿hay alguna manera simple de hacer exactamente lo contrario de esta operación, es decir, establecer la cabeza en la primera confirmación del primer hijo del jefe actual?
En este momento, uso gitk como solución alternativa (alt-tab, up-arrow, alt-tab, middle-click), pero me gustaría una solución más elegante, que también se pueda usar cuando gitk no esté disponible.
Basado parcialmente en la respuesta de Paul Wagland y en parte en su fuente , estoy usando lo siguiente:
git log --ancestry-path --format=%H ${commit}..master | tail -1
Descubrí que la respuesta de Paul me daba el resultado incorrecto para las confirmaciones más antiguas (¿posiblemente debido a la fusión?), Donde la diferencia principal es el --ancestry-path
.
De acuerdo con la respuesta dada en ¿Cómo encuentro el siguiente compromiso en git? , Tengo otra solución que funciona para mí.
Suponiendo que desea encontrar la siguiente revisión en la rama "principal", puede hacer lo siguiente:
git log --reverse ${commit}..master | sed ''s/commit //; q''
Esto también supone que hay una próxima revisión, pero de todos modos la pregunta lo asume de alguna manera.
Depende de lo que estés preguntando. Puede haber un número infinito de hijos del jefe actual en un número infinito de ramas, algunas locales, otras remotas y muchas que se han redistribuido y están en su repositorio, pero no forman parte de un historial que usted pretende publicar.
Para un caso simple, si acaba de hacer un reinicio en HEAD^
, puede recuperar al niño que acaba de tirar como HEAD@{1}
.
El método anterior que utiliza git rev-list --all
considera todas las confirmaciones disponibles, que pueden ser muchas y, a menudo, innecesarias. Si los commits de child interesantes son alcanzables desde alguna rama, se puede reducir el número de commits que un script interesado en child commits necesita procesar:
branches=$(git branch --contains $commit)
determinará el conjunto de ramas que $ commit es un antecesor de.
Usando este conjunto, git rev-list --parents ^$commit $branches
debería producir exactamente el conjunto de todas las relaciones padre-hijo entre $ commit y todas las cabezas de ramas de las que es antecesor.
Es estrictamente imposible dar una buena respuesta: dado que se distribuye git, la mayoría de los niños de la comisión sobre los que preguntas pueden estar en repositorios que no tienes en tu máquina local. Por supuesto, es una respuesta tonta, pero algo en lo que pensar. Git rara vez implementa operaciones que no puede implementar correctamente.
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.
Muy probablemente no sea la solución más rápida posible, pero hace lo que necesito:
#!/bin/bash REV=$1 if [ x$REV == x ]; then echo "Usage: git-get-child []" exit fi HASH=$(git-rev-parse $REV) NUM=$2 if [ x$NUM == x ]; then NUM=1 fi git rev-list --all --parents | grep " $HASH" | sed -n "${NUM}s//([^ ]*/) .*$///1/p"
El git rev-list --all --parents
hace exactamente lo que necesito: itera sobre todos los commit alcanzables, e imprime la siguiente línea para cada uno:
SHA1_commit SHA1_parent1 SHA1_parent2
etc.
El espacio en la expresión grep asegura que solo esas líneas se encuentran donde el SHA1 en cuestión es un padre. Luego obtenemos la enésima línea para el enésimo hijo y obtenemos el SHA1 del niño.
Para mover HEAD (como se le pidió, esto no actualiza el índice o el árbol de trabajo), use:
git reset --soft $(git child)
Tendrá que usar la configuración que se detalla a continuación.
Explicación
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.
Con una cabeza separada, no hay rama, pero obtener el primer hijo todavía se puede lograr con este alias:
# 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
Puedes usar gitk
... ya que puede haber más de un niño, probablemente no haya una manera fácil como HEAD^
.
Si desea deshacer toda su operación, también puede usar el reflog. Use git reflog
para encontrar el puntero de su commit, que puede usar para el comando de reset
. Mira here .
Puedes usar la esencia del creador de Hudson (ahora Jenkins) Kohsuke Kawaguchi (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
Coloque esa secuencia de comandos en una carpeta a la que hace referencia $PATH
, y simplemente escriba:
git children-of <a-commit>