Qué hacer con el compromiso realizado en una cabeza separada

281

Usando git hice algo como esto

git clone
git checkout {a rev number tree rev before} (here I started to be in a detached head state)
//hacking
git commit
//hacking
git commit
(some commit where made on origin/master)
git pull (which does complete because there was some error due to the fact that I'm no more on master)

Debido a que me dijo que todavía puedo comprometerme cuando estoy en un estado de desapego, lo hice. Pero ahora quiero fusionar mi rama principal separada y mi rama maestra local, y luego empujar mi montón de cambios a origen / maestro.

Entonces mi pregunta es cómo podría fusionar la rama maestra con mi estado real (cabeza separada)

benzen
fuente
posible duplicado de Git: HEAD ha desaparecido, quiero fusionarlo en maestro
Karl Bielefeldt
Podría agregar una captura de pantalla de un árbol de confirmación en este estado (cómo se ve realmente una confirmación en una cabeza separada en gitk o SourceTree), eso mejoraría aún más esta pregunta.
florisla
Desafortunadamente en este momento no puedo, pero si puedes proporcionar, estaré feliz de verlo aquí. Incluso si es un empate, lo hará más claro
benzen

Respuestas:

478

Crea una rama donde estés, luego cambia a master y fusiona:

git branch my-temporary-work
git checkout master
git merge my-temporary-work
Ryan Stewart
fuente
12
¿Cómo se evita separar las cabezas en el futuro?
ycomp
Hice esto y me encontré por delante de origen por 5 commits. En ese caso, ¿solo haces git push origin?
Winnemucca
55
extraño, me sale "Ya actualizado". al fusionar mi trabajo temporal
Robert Sinclair
10
No olvides eliminar mi trabajo temporal con "git branch -d mi trabajo temporal"
Capitán Lepton
55
@ycomp "cabeza separada" ocurre cuando edita los archivos de una confirmación anterior y luego confirma los que no tienen una rama para hacer referencia a esta nueva confirmación más adelante. Para evitar la cabeza desprendida, no verifique los commits antiguos. Si aún desea todos los archivos desde allí, pero como una nueva confirmación, puede retirar el directorio de la confirmación, en lugar de la confirmación en sí. Ver esta respuesta
lucidbrot
96

Podrías hacer algo como esto.

# Create temporary branch for your detached head
git branch tmp

# Go to master
git checkout master

# Merge in commits from previously detached head
git merge tmp

# Delete temporary branch
git branch -d tmp

Aún más simple sería

git checkout master
git merge HEAD@{1}

pero esto tiene el pequeño peligro de que si comete un error puede ser un poco más difícil recuperar los compromisos cometidos en la cabeza desprendida.

CB Bailey
fuente
44
Sé que esto es años después, pero gracias por esta respuesta. No me consideré haciendo la búsqueda con la respuesta aceptada aquí porque no quería dejar una rama temporal y esta respuesta tiene el comando para eliminarla.
Jeremy Pridemore
8
Si decide utilizar el comando git merge HEAD@{1}es probable que debe asegurarse de que es el que desea utilizar mediante el usogit reflog
Michael Stramel
3
Ser capaz de fusionar HEAD @ {1} me salvó la vida ya que ya había retirado el master de forma preventiva.
juil
extraño, me sale "Ya actualizado". al fusionar tmp (pero los archivos son diferentes)
Robert Sinclair
19

Esto es lo que hice:

Básicamente, piense en el detached HEADcomo una nueva rama, sin nombre. Puede comprometerse en esta rama como cualquier otra rama. Una vez que haya terminado de comprometerse, desea llevarlo al control remoto.

Entonces, lo primero que debes hacer es darle detached HEADun nombre. Puedes hacerlo fácilmente, mientras estás en esto detached HEAD:

git checkout -b some-new-branch

Ahora puede empujarlo al control remoto como cualquier otra rama.

En mi caso, también quería adelantar esta rama para dominarla junto con los commits que hice en el detached HEAD(ahora some-new-branch). Todo lo que hice fue

git checkout master

git pull # To make sure my local copy of master is up to date

git checkout some-new-branch

git merge master // This added current state of master to my changes

Por supuesto, lo fusioné más tarde master.

Eso es todo.

Bhushan
fuente
1
Esta respuesta funcionó para mí donde los otros no. git checkout -b new-branchtrabajó para mi. Las otras sugerencias exigieron git branch new-branch, pero eso me dejó aún en la cabeza separada y la nueva rama no recogió mis cambios.
Jesse Patel
17

Solo puedes hacer git merge <commit-number>ogit cherry-pick <commit> <commit> ...

Según lo sugerido por Ryan Stewart, también puede crear una rama desde el HEAD actual:

git branch brand-name

O solo una etiqueta:

git tag tag-name
Arnaud Le Blanc
fuente
Puede encontrar su número de confirmación en la cabeza separada porgit rev-parse HEAD
KOGI
6

En el caso de HEAD separado, las confirmaciones funcionan de manera normal, excepto que no se actualiza ninguna rama con nombre. Para actualizar la rama maestra con sus cambios confirmados, realice una rama temporal donde se encuentre (de esta manera la rama temporal tendrá todos los cambios confirmados que ha realizado en el HEAD separado), luego cambie a la rama maestra y combine la rama temporal con el maestro.

git branch  temp
git checkout master
git merge temp
Razan Paul
fuente
3

Una solución fácil es que acaba de crear una nueva rama para que cometen y la salida a la misma: git checkout -b <branch-name> <commit-hash>.

De esta manera, todos los cambios que realizó se guardarán en esa rama. En caso de que necesite limpiar su rama maestra de las confirmaciones restantes, asegúrese de ejecutarla git reset --hard master.

Con esto, volverá a escribir sus ramas, así que asegúrese de no molestar a nadie con estos cambios. Asegúrese de leer este artículo para obtener una mejor ilustración del estado HEAD separado .

Nesha Zoric
fuente
1

Tal vez no sea la mejor solución (reescribirá el historial), pero también podría hacerlo git reset --hard <hash of detached head commit>.

novato
fuente