¿Qué sucede con los git commits creados en un estado HEAD separado?

137

Esto es lo que pasó:

Tengo una rama A. En la rama AI cometí un montón de cambios. No estaba contento con el código, así que revisé el commit anterior en la rama A. Luego realicé muchos cambios más y los confirmé en la rama A. Ahora no puedo encontrar este commit en ningún lado. ¿Perdí este código?

Mausimo
fuente
Cuando dice "Revisé la confirmación anterior en la rama A", ¿quiere decir "Restablezco la rama A a la confirmación anterior"? es decir, ¿realmente en git resetlugar de git checkout?
CB Bailey
No, solía pagar. reflog trabajado.
Mausimo
Si utilizó el proceso de pago, habrá estado en una ubicación separada HEADy la rama A se habría quedado en la confirmación anterior. ¿Qué comandos ejecutaste exactamente?
CB Bailey
1
Estaba usando la GUI de SourceTree GIT en OSX Lion. Estaba en la rama A y ejecuté un pago de la confirmación anterior en la Rama A. Luego hice un montón de cambios de código y me comprometí (Rama A). Creo que tenía una CABEZA separada.
Mausimo
OK, creo que estaba confundido cuando usted dijo que usted cometió un montón más cambios en la rama A .
CB Bailey

Respuestas:

186

El viejo commit todavía está en el registro de nuevo.

git reflog

Esto mostrará una lista de confirmaciones, y la confirmación "perdida" debería estar allí. Puedes convertirlo en una nueva sucursal. Por ejemplo, si el SHA-1 es ba5a739, entonces puede hacer una nueva rama llamada "nueva rama" en la confirmación anterior con:

git branch new-branch ba5a739

Tenga en cuenta que las confirmaciones "perdidas" se eliminarán cuando se elimine la base de datos.

Dietrich Epp
fuente
3
Hice lo mismo y tuve un ataque al corazón pensando que estaba perdido. Gracias por la info!
Chase
15
Úselo git cherry-pick [SHA]para mover el commit a una rama existente en caso de que accidentalmente cometió mientras estaba en estado de cabeza separada
Jan Aagaard Meier
3
Alternativamente, puede cambiar a una rama existente y hacer "git merge HEAD @ {n}" n correspondiente a la confirmación "perdida" que figura en el registro.
eaykin
¿Sabe si pruneeliminaría las confirmaciones también separadas que se mencionan en los mensajes de confirmación? ¿O eso los hace accesibles ?
Kamafeather
@ Kamafeather: No creo que eso los haga alcanzables.
Dietrich Epp
64

Sus confirmaciones aún están disponibles en el registro de registro, como ya se señaló. Además de las otras respuestas, aquí hay una manera de hacerse cargo de los compromisos HEAD separados directamente en su rama actual , sin crear y fusionar una nueva rama:

  1. Busque los hash SHA-1 de las confirmaciones que realizó en estado HEAD separado con

    git reflog
    
  2. Luego ejecute, con todos los hashes de confirmación ordenados de más antiguo a más reciente:

    git cherry-pick <hash1> <hash2> <hash3> ...
    

    Por ejemplo, si tuviera solo uno, dado en el formato de hash corto "primeros 7 caracteres":

    git cherry-pick a21d053
    

Esto creará nuevos commits para su rama actual, un commit por hash de HEAD-commit separado que usted menciona en el comando. También se hace cargo de los mensajes de confirmación originales.

Tanius
fuente
11

Puede encontrar confirmaciones perdidas (colgantes) con el siguiente comando:

git fsck --lost-found

Tenga en cuenta que si su cabeza actual está colgando commit, no aparece como perdido.

Puede encontrar más información en la página del manual de git-fsck (1)

Luego puede crear una rama en ese commit perdido:

git branch new-branch ba5a739
sergtk
fuente
Primero usé el comando "git reflog" y luego "git branch new-branch ba5a739" para un submódulo, funcionó.
ondermerol
7

El lenguaje Git para el estado de su directorio de trabajo es un " HEAD separado ". Aquí hay otro lugar que git refloghace la salvación.

$ git reflog
0b40dd6 HEAD@{0}: commit: my commit on detached HEAD
...

Si trato de pagar una rama diferente, git-1.7.5.1 da una sugerencia útil.

$ git checkout master
Advertencia: estás dejando 1 commit atrás, no conectado a
cualquiera de tus sucursales:

  0b40dd6 mi commit en HEAD separado

Si desea conservarlos creando una nueva sucursal, este puede ser un buen momento
para hacerlo con:

 git branch new_branch_name 0b40dd65c06bb215327863c2ca10fdb4f904215b

Cambió a la rama 'maestro'
Greg Bacon
fuente
Gracias por la información y el enlace. El enlace me ayudó a entender lo que estaba sucediendo.
Mausimo
6

No lo perdió, Git aún conserva una copia (pero actualmente no es accesible para ningún jefe de sucursal). Puedes encontrar tu commit faltante usando el git reflogcomando. El registro de registro realiza un seguimiento de las posiciones históricas de una cabeza de rama, y ​​puede usarlo para encontrar cosas a las que la cabeza de la rama apuntaba anteriormente.

Greg Hewgill
fuente
4

Siga estos pasos para vincular su cabeza separada con git repo

  1. git checkout "your branch with path but without remote name"

por ejemplo, si el nombre remoto es el origen y el nombre de la sucursal, bugfix/somebranchentonces usegit checkout bugfix/somebranch

  1. git reflog obtenga los SHA de confirmación que figuran en su lista de confirmación de rama separada.

  2. git cherry-pick "commit hash1" "commit hash2" "commit hash3"

  3. git push

¡¡TODO LISTO!!

usuario1520615
fuente
2

En Sourcetree, descubrí que git reflog no funcionaba, así que descubrí cómo hacerlo usando la GUI.

Primero, intente encontrar la confirmación "perdida" buscando un mensaje en el Historial de comandos (ver: Mostrar salida de comando). Esperemos que esté en el comando "Switching Branch" después de la confirmación que perdió y verá el comentario de confirmación con una ID de confirmación 1234567.

Lleve esa ID de confirmación al siguiente paso.

Pulse el botón "Rama" en la barra de herramientas superior y debería obtener un cuadro de diálogo "Nueva rama" donde puede especificar una determinada confirmación. ¡Ingrese esa ID de confirmación allí, especifique un nuevo nombre de rama, presione Crear rama y debería obtener una nueva rama con su confirmación perdida!

¡Esto me trajo algo de trabajo perdido!

blalond
fuente