Hacer reference al niño de un compromiso en Git

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.

Muy probablemente no sea la solución más rápida posible, pero hace lo que necesito:

 #! / bin / bash

 REV = $ 1

 si [x $ REV == x];  entonces
     echo "Uso: git-get-child []"
     salida
 fi

 HASH = $ (git-rev-parse $ REV)

 NUM = $ 2

 si [x $ NUM == x];  entonces
     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.

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 twig, se puede networkingucir el número de commits que un script interesado en child commits necesita procesar:

 branches=$(git branch --contains $commit) 

determinará el set de twigs que $ commit es un antecesor de.

Usando este set, git rev-list --parents ^$commit $branches debería producir exactamente el set de todas las relaciones padre-hijo entre $ commit y todas las cabezas de twigs de las que es antecesor.

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 dio el resultado incorrecto para las confirmaciones más antiguas (¿posiblemente debido a la fusión?), Donde la diferencia principal es la bandera --ancestry-path .

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 command de reset . Mira aquí .

Para mover HEAD (como se le pidió, esto no actualiza el índice o el tree de trabajo), use:

git reset --soft $(git child)

Tendrá que usar la configuration 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 pnetworkingeterminado, 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 less que se proporcione otro argumento de commit-ish) siguiendo el ancestro un paso hacia la punta de la twig actual (a less 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 twig, pero get 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

Depende de lo que estés preguntando. Puede haber un número infinito de hijos del jefe actual en un número infinito de twigs, algunas locales, otras remotas y muchas que se han networkingistribuido y están en su repository, 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 [email protected]{1} .

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 twig "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.

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 "[email protected]"; 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 commands en una carpeta a la que hace reference $PATH , y simplemente escriba:

 git children-of <a-commit> 

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 repositorys 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 label bien definida al final de su stack 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 label.