Búsqueda de sitios web

¿Cómo se arregla un HEAD separado en un repositorio de Git?


Uno de los mensajes de error habituales que probablemente encuentre con Git es la advertencia de que está en un estado de 'cabeza separada'. Es posible que haya tropezado con esto accidentalmente, pero no se preocupe: es un problema normal y puede solucionarse fácilmente una vez que comprenda lo que significa.

¿Qué es Git HEAD?

HEAD es simplemente un alias para su compromiso de trabajo actual, muy parecido a su directorio actual en una línea de comando. Independientemente del estado en el que se encuentre su repositorio de Git, HEAD siempre apunta a algo, y se agregarán nuevas confirmaciones delante de HEAD.

Por lo general, HEAD no hace referencia directa a una sola confirmación. En su lugar, apunta a una rama e indirectamente hace referencia a la última confirmación en esa rama. Cada vez que paga una nueva rama, Git cambia el HEAD a esa rama. Esto le permite realizar nuevas confirmaciones que se agregarán al final de esa rama.

Sin embargo, también puede consultar las confirmaciones individuales. ¿Qué sucede si desea examinar el repositorio en un momento específico? Esa es una de las principales ventajas de Git, pero presenta un pequeño problema con la forma en que Git estructura las cosas. Dado que las nuevas confirmaciones no actualizarán una rama, todas las confirmaciones que realice después de mover el HEAD se separarán de todas las referencias de la rama, por lo tanto, separarán el HEAD.

En realidad, esto puede ser bastante útil. Supongamos que movió HEAD hacia atrás algunas confirmaciones y luego realizó algunas actualizaciones experimentales. Básicamente, estás creando una nueva rama, que podría volver a fusionarse con master más adelante.

Tendrás que integrarlo oficialmente en el repositorio de Git si decides mantener los cambios, pero como una herramienta para hacer modificaciones en el pasado, tener un HEAD separado no es tan aterrador como parece.

Si llegaste aquí por accidente

Es muy fácil terminar aquí por accidente y confundirse con el mensaje de error del que se queja Git a pesar de no haber hecho nada malo. Afortunadamente, es increíblemente fácil de arreglar:

Si acabas de verificar una confirmación y no has tocado el repositorio de otra manera (no se realizaron nuevas confirmaciones), simplemente puedes mover el HEAD a donde pertenece con git checkout:

git checkout master

Esto es básicamente como ejecutar cd en Linux, excepto que Git aún asocia las confirmaciones y los cambios almacenados en caché con el antiguo HEAD, por lo que no desea verificar si tiene confirmaciones o cambios que quedarían colgados.

Si tuviste algunos cambios y simplemente deseas desecharlos, puedes restablecer por completo a master:

git reset --hard origin/master
git clean -d --force

Sin embargo, si desea guardar sus compromisos, deberá fusionarlos oficialmente nuevamente en la línea de tiempo de Git.

Si desea guardar sus cambios

Lo primero que querrá hacer si desea mantener los cambios que realizó mientras estaba en un estado HEAD desconectado es crear una nueva rama. Esto se debe a que el recolector de elementos no utilizados de Git limpiará automáticamente las confirmaciones separadas, por lo que nunca querrás perderles el rastro.

git branch detached-branch

Luego, puede verificar esta rama para mover la CABEZA para que ya no esté separada y, en su lugar, apunte a esta nueva rama oficial:

git checkout detached-branch

Una vez que se registran los cambios, tiene una de dos opciones. Esta nueva rama es básicamente una rama de características normal, por lo que puede git merge o git rebase.

La fusión es sencilla; pago maestro, y fusionar la rama separada:

git checkout master
git merge detached-branch

Esto funciona bien si se está integrando a una rama que necesita aprobación, como es el caso de las solicitudes de incorporación de cambios y las revisiones de código. Es posible que deba pasar por el proceso de aprobación de su equipo en lugar de ejecutar estos comandos usted mismo.

Si tiene acceso, como si se está fusionando de nuevo en una rama de función en la que está trabajando, un mejor método es seleccionar las confirmaciones separadas. Cherry picking básicamente copia una confirmación y la pega en otra rama. Por lo general, se usa para extraer confirmaciones específicas de una rama de características antes de que todo esté listo, pero en este caso, la selección selectiva puede conciliar la rama separada sin una fusión.

En este ejemplo, la confirmación anterior está separada. En lugar de fusionarlo, se selecciona y se traslada a la rama feature . Esto mueve HEAD y la rama de características para apuntar a la última confirmación sin fusión. Luego, la confirmación separada original se puede descartar.

Primero, deberá crear la rama separada y luego verificar la rama de características para mover la CABEZA allí:

git branch detached-branch
git checkout feature

Luego ejecute el registro de Git para obtener una lista de confirmaciones:

git log --pretty=format:"%h %s" --graph

Luego, puede seleccionar una confirmación por su ID:

git cherry-pick 1da76d3

Luego, una vez que haya confirmado que las confirmaciones seleccionadas se aplican correctamente, puede eliminar la rama separada, ya que las confirmaciones se copiaron y ya no se usan.

git branch -D detached-branch

Reorganizar en lugar de fusionar

También podrías hacer una reorganización. Los rebases son diferentes de las fusiones en que reescriben el historial de la rama, levantando las confirmaciones separadas y moviéndolas al frente de la rama.

Sin embargo, el problema con esto es que todavía te quedan dos ramas, y aún necesitarás fusionar feature y tached-branch juntos, dejándote con una fusión comprometerse de cualquier manera. Pero deja el repositorio con un historial de Git más lineal, lo que es preferible a ejecutar git merge si tiene la autoridad para hacerlo.

Artículos relacionados: