Pregunta ¿Cómo puedo reconciliar el HEAD separado con el maestro / origen?


Soy nuevo en las complejas complejidades de Git. Siempre trabajo en una sola rama y confirmo los cambios y luego periódicamente presiono mi origen remoto.

En algún lugar recientemente, hice un reinicio de algunos archivos para sacarlos de la puesta en escena de compromiso, y luego hice un rebase -i para deshacerse de un par de compromisos locales recientes. Ahora estoy en un estado que no entiendo del todo.

En mi área de trabajo, git log muestra exactamente lo que esperaba: estoy en el tren correcto con los compromisos que no quería que se fueran, y nuevos, etc.

Pero simplemente llegué al repositorio remoto, y lo que hay allí es diferente: un par de las confirmaciones que había matado en la rebase se presionaron, y las nuevas confirmadas localmente no están allí.

Creo que "maestro / origen" está separado de HEAD, pero no estoy 100% claro sobre lo que eso significa, cómo visualizarlo con las herramientas de línea de comando y cómo solucionarlo.


1274
2018-04-24 17:51


origen


Respuestas:


Primero, aclaremos qué es HEAD y lo que significa cuando está separado.

HEAD es el nombre simbólico de la confirmación actualmente desprotegida. Cuando HEAD no está separado (lo "normal"1 situación: tiene una rama desprotegida), HEAD realmente apunta a la "ref" de una rama y la ramificación apunta a la confirmación. HEAD está así "unido" a una rama. Cuando realiza una nueva confirmación, la rama a la que HEAD apunta se actualiza para apuntar a la nueva confirmación. HEAD sigue automáticamente ya que solo apunta a la rama.

  • git symbolic-ref HEAD rendimientos refs/heads/master
    La rama llamada "master" está desprotegida.
  • git rev-parse refs/heads/master rendimiento 17a02998078923f2d62811326d130de991d1a95a
    Esa confirmación es la sugerencia actual o "cabeza" de la rama principal.
  • git rev-parse HEAD también rinde 17a02998078923f2d62811326d130de991d1a95a
    Esto es lo que significa ser una "referencia simbólica". Apunta a un objeto a través de otra referencia.
    (Las réplicas simbólicas se implementaron originalmente como enlaces simbólicos, pero luego se cambiaron a archivos sin formato con una interpretación adicional para que pudieran usarse en plataformas que no tienen enlaces simbólicos).

Tenemos HEAD → refs/heads/master → 17a02998078923f2d62811326d130de991d1a95a

Cuando HEAD está separado, apunta directamente a un compromiso, en lugar de señalar indirectamente a uno a través de una rama. Puedes pensar en un HEAD separado como en una sucursal sin nombre.

  • git symbolic-ref HEAD falla con fatal: ref HEAD is not a symbolic ref
  • git rev-parse HEAD rendimientos 17a02998078923f2d62811326d130de991d1a95a
    Como no es una referencia simbólica, debe apuntar directamente al compromiso en sí.

Tenemos HEAD → 17a02998078923f2d62811326d130de991d1a95a

Lo importante para recordar con un HEAD separado es que si el commit apunta a que no tiene referencias (ningún otro ref puede alcanzarlo), entonces se pondrá "colgando" cuando pagues algún otro commit. Eventualmente, dichos commits pendientes serán eliminados a través del proceso de recolección de basura (de manera predeterminada, se guardan durante al menos 2 semanas y pueden mantenerse más tiempo al ser referenciados por el reflog de HEAD).

1 Está perfectamente bien hacer un trabajo "normal" con un HEAD separado, solo tienes que hacer un seguimiento de lo que estás haciendo para evitar tener que pescar el historial eliminado del reflog.


Los pasos intermedios de una rebase interactiva se realizan con un HEAD separado (parcialmente para evitar contaminar el reflog de la rama activa). Si finaliza la operación de rebase completa, actualizará su rama original con el resultado acumulado de la operación de rebase y volverá a conectar HEAD a la rama original. Supongo que nunca completaste completamente el proceso de rebase; esto te dejará con un HEAD separado que apunta a la confirmación que fue procesada más recientemente por la operación de rebase.

Para recuperarse de su situación, debe crear una rama que señale la confirmación actualmente señalada por su HEAD separado:

git branch temp
git checkout temp

(estos dos comandos se pueden abreviar como git checkout -b temp)

Esto volverá a conectar su HEAD al nuevo temp rama.

A continuación, debe comparar la confirmación actual (y su historial) con la rama normal en la que esperaba trabajar:

git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp
git diff master temp
git diff origin/master temp

(Probablemente quiera experimentar con las opciones de registro: agregar -p, dejar fuera --pretty=… para ver el mensaje de registro completo, etc.)

Si tu nuevo temp la rama se ve bien, es posible que desee actualizar (por ejemplo) master para señalarlo:

git branch -f master temp
git checkout master

(estos dos comandos se pueden abreviar como git checkout -B master temp)

Luego puede eliminar la rama temporal:

git branch -d temp

Finalmente, es probable que desee impulsar la historia restablecida:

git push origin master

Es posible que deba agregar --force al final de este comando para presionar si la bifurcación remota no se puede "reenviar rápidamente" a la nueva confirmación (es decir, se descartó o reescribió alguna confirmación existente, o se reescribió un poco el historial).

Si estaba en medio de una operación de rebase, probablemente debería limpiarlo. Puede verificar si una rebase estaba en proceso buscando el directorio .git/rebase-merge/. Puede limpiar manualmente la rebase en progreso simplemente borrando ese directorio (por ejemplo, si ya no recuerda el propósito y el contexto de la operación de rebase activa). Usualmente usarías git rebase --abort, pero eso hace un reajuste adicional que probablemente desee evitar (mueve HEAD a la rama original y lo restablece a la confirmación original, lo que deshace parte del trabajo que hicimos anteriormente).


2160
2018-04-24 19:56



Solo haz esto:

git checkout master

O bien, si tiene cambios que desea conservar, haga esto:

git checkout -b temp
git checkout -B master temp

512
2017-09-18 07:23



Me encontré con este problema y cuando leí en la respuesta más votado:

HEAD es el nombre simbólico de la confirmación actualmente desprotegida.

Pensé: ¡Ah, ja! Si HEAD es el nombre simbólico de la confirmación de compra actual, puedo reconciliarlo contra master refinándolo contra master:

git rebase HEAD master

Este comando:

  1. echa un vistazo master
  2. identifica los compromisos principales de HEAD volver al punto HEAD divergido de master
  3. juega esos compromisos en la parte superior de master

El resultado final es que todos los commits que estaban en HEAD pero no master están entonces también en master. master sigue siendo revisado.


En cuanto al control remoto:

un par de los commits que había matado en la rebase fueron empujados, y los nuevos cometidos localmente no están allí.

El historial remoto ya no se puede reenviar rápidamente usando su historial local. Tendrás que forzar-empujar (git push -f) para sobrescribir el historial remoto. Si tiene colaboradores, generalmente tiene sentido coordinar esto con ellos para que todos estén en sintonía.

Después de empujar master a distancia origin, su sucursal de seguimiento remoto origin/master se actualizará para apuntar a la misma confirmación como master.


97
2017-08-02 03:10



Busque aquí una explicación básica de la cabeza desprendida:

http://git-scm.com/docs/git-checkout

Línea de comando para visualizarlo:

git branch

o

git branch -a

obtendrás resultados como a continuación:

* (no branch)
master
branch1

los * (no branch) muestra que estás en la cabeza separada.

Podrías haber llegado a este estado haciendo un git checkout somecommit etc. y te habría advertido con lo siguiente:

Estás en el estado 'HEAD separado'. Tú   puede mirar a su alrededor, hacer experimentos   cambia y los compromete, y usted puede   descarta cualquier compromiso que hagas en este   estado sin impactar ninguna rama   realizando otra salida.

Si quieres crear una nueva rama para   retener los commits que crees, puedes hacer   entonces (ahora o más tarde) usando -b con el   comando de pago de nuevo. Ejemplo:

git checkout -b new_branch_name

Ahora, para obtenerlos en master:

Haz un git reflog o incluso solo git log y tenga en cuenta sus compromisos. Ahora git checkout master y git merge los compromisos.

git merge HEAD@{1}

Editar:

Para agregar, use git rebase -i no solo para borrar / eliminar confirmaciones que no necesita, sino también para editarlas. Simplemente mencione "editar" en la lista de compromisos y podrá modificar su compromiso y luego emitir un git rebase --continue ir hacia adelante. Esto habría asegurado que nunca entraras a un HEAD separado.


78
2018-04-24 18:41



Obtenga su compromiso separado en su propia rama

Simplemente ejecuta git checkout -b mynewbranch.

Entonces corre git log, y verá que el compromiso es ahora HEAD en esta nueva rama.


29
2018-05-20 02:44



si solo tienes la rama principal y quieres volver a "desarrollar" o una función simplemente haz esto:

git checkout origin/develop

Nota: echando un vistazo origen / desarrollo.

Estás dentro CABEZA separada estado. Puedes mirar alrededor, hacer experimentos cambia y los compromete, y puede descartar cualquier compromiso que realice en este estado sin impactar ninguna rama realizando otro pago y envío ...

entonces

git checkout -b develop

Funciona :)


18
2017-11-08 13:24



Si desea empujar su HEAD desconectado actual (verifique git log antes), intente:

git push origin HEAD:master

para enviar su HEAD separado a la rama principal en el origen. Si tu push es rechazado, prueba git pull origin master primero para obtener los cambios de origen. Si no te importan los cambios de origen y se rechaza, porque hiciste una rebase intencional y quieres reemplazar el origen / maestro con tu rama actualmente separada, entonces puedes forzarla (-f) En caso de que haya perdido algo de acceso a las confirmaciones anteriores, siempre puede ejecutar git reflog para ver la historia de todas las ramas.


Para volver a una rama principal, mientras mantiene los cambios, intente con los siguientes comandos:

git rebase HEAD master
git checkout master

Ver: Git: "Actualmente no en ninguna rama". ¿Hay una forma fácil de volver a una sucursal, mientras se mantienen los cambios?


16
2017-09-17 20:35



Si está completamente seguro de que HEAD es el buen estado:

git branch -f master HEAD
git checkout master

Probablemente no puedas empujar hacia el origen, ya que tu maestro ha divergido del origen. Si está seguro de que nadie más está utilizando el repositorio, puede presionar forzosamente:

git push -f

Más útil si estás en una rama de función que nadie más está usando.


7
2018-03-01 09:31