git: cambiar de manera confiable a HEAD separado y luego restaurar HEAD más tarde, todo desde un script

Así que aquí está el escenario. Tengo un script que ejecuta algunas testings. Necesito hacer otro script que acepte como parámetro un nombre de cometer git y luego haga lo siguiente:

  1. Guarda el estado de confirmación actual: nombre de la sucursal o confirmación sin nombre.
  2. Cambia a un HEAD separado en el compromiso especificado
  3. Ejecuta el script de testing contra ese commit
  4. Cambia de nuevo para que HEAD sea el mismo que antes de este negocio

Necesito asegurarme de que este script sea robusto para que nunca sea destructivo sin importar el estado del repository. Debería funcionar cuando se ejecuta desde un HEAD desconectado o desde una bifurcación regular, y preferiblemente debería funcionar incluso cuando haya cambios no confirmados o no realizados.

Siento que esta debería ser una pregunta fácil de responder, ya que ejecutar una secuencia de commands de testing contra una confirmación anterior parece una tarea realmente común que quiero automatizar. Pero parece que no puedo encontrar ninguna serie simple de commands para hacerlo.

(Similar a lo que hace pushd / cd / popd para el directory de trabajo actual).

Si está en una secuencia de commands, solo para este caso de uso, no es necesario que haga nada superdeportivo, simplemente almacene donde HEAD estaba antes, y revíselo después de lo siguiente:

# If HEAD is a sym-ref, the first assignment will work # otherwise, it's detached, so get the SHA1 with rev-parse if ! head=$(git symbolic-ref HEAD 2>&1); then head=$(git rev-parse HEAD) fi # trim a refs/heads/ prefix; no-op otherwise head=${head#refs/heads/} # now go on and do your stuff, test, whatever you like # then return to where you were # This will ERASE ANY LOCAL CHANGES. git checkout -f $head 

Esto tiene la ventaja de funcionar sin importar lo que hagas en el medio – en particular, podrías hacer muchas operaciones de git allí – quizás una fusión de testing, o seleccionar una confirmación para la testing (tal vez probar esa confirmación, tal vez contenga alguna crear configuraciones de configuration puramente para testings). Como esas operaciones crean commits, harían que el enfoque HEAD@{1} fallara (en su lugar, querría HEAD@{2} ). Aún mejor, si las testings realmente implican crear twigs temporales, esto seguirá funcionando, mientras que el enfoque @{-1} no funcionaría.

(Además, por lo que puedo decir, HEAD@{1} siempre verifica el compromiso referido por HEAD en ese punto, no la twig que estaba apuntando a ese commit. Eso tiene sentido, ya que la twig podría " es concebible que haya cambiado desde entonces.)

testing (no probado)

 git checkout HEAD@{1} 

a "vuelve a cambiar tan HEAD " como lo estaba antes de su checkout xxx .

Ver también " HEAD y ORIG_HEAD en Git "


Todas las demás especificaciones de revisión están aquí: rev_parse, sección "ESPECIFICACIÓN DE REVISIONES" .
Por ejemplo, para volver a la twig anterior, puede intentar @{-1} .

Acabo de probarlo (la opción " HEAD anterior"):

Repo simple de git con 3 files agregados en tres confirmaciones ( a , luego b , luego c ):

 C:\git\tests\p3>git log --oneline 6e5b961 c 66c68e3 b 77e9a40 a 

Pago la primera comisión ( DETACHED HEAD )

 C:\git\tests\p3>git checkout 77e9a40 Note: moving to '77e9a40' which isn't a local branch If you want to create a new branch from this checkout, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new_branch_name> HEAD is now at 77e9a40... a C:git\tests\p3>dir 08/12/2010 12:27 PM 4 a.txt 

Intento volver a la HEAD anterior antes de hacer la DETACHED HEAD :

 C:\git\tests\p3>git checkout HEAD@{1} Previous HEAD position was 77e9a40... a HEAD is now at 6e5b961... c 

¡Funciona!

Obtienes la confirmación correcta, pero no la correcta (es decir, todavía estás en modo separado)

 C:\git\tests\p3>git branch * (no branch) master 

En esta configuration, tratar de volver a la twig anterior no funcionaría

 C:\git\tests\p3>git checkout HEAD@{-1} error: pathspec 'HEAD@{-1}' did not match any file(s) known to git. 

Así que la única solución real para volver al HEAD (no a un commit en un modo separado) es memorizarlo primero

 git symbolic-ref HEA 

Ver la respuesta de Jefromi .