2012-01-12 10 views
98

Tengo una rama configurada para rastrear una referencia en origen. git checkout <branchname> conmuta a la misma rama, y ​​una git status me va a mostrar hasta qué punto por delante o por detrás de mi rama es de origen, pero me sorprende que todavía origin/HEAD puntos en los origin/master, y no origin/<branchname>¿Cómo se establece origen/HEAD?

Así que mi pregunta es, en qué circunstancias ¿se mueve el origen/HEAD?

EDIT:

aprecio las respuestas acerca de cómo para mover origen/HEAD, pero estoy interesado en lo "orgánico" se mueve, fuera de mí diciendo explícitamente que lo haga.

Por ejemplo, cuando cambio de ramas, git hace que HEAD apunte a la rama que estoy revisando, así que me sorprende que el origen/HEAD no se mueva de la misma manera.

+0

Tenga en cuenta que esta pregunta es sobre referencias simbólicas locales en controles remotos, como 'refs/origin/HEAD'. No se trata de cómo se establece la referencia simbólica propia del repositorio 'HEAD'. – clacke

Respuesta

127

Tenga en cuenta primero que su pregunta muestra un poco de malentendido.origen/HEAD representa la rama predeterminada en el control remoto, es decir, la CABEZA que está en ese repositorio remoto al que está llamando origen. Cuando cambias ramas en tu repositorio, no estás afectando eso. Lo mismo es cierto para sucursales remotas; Es posible que tenga master y origin/master en su repositorio, donde origin/master representa una copia local de la rama master en el repositorio remoto. CABEZA

de origen sólo cambiará si usted o alguien más en realidad cambia en el repositorio remoto, que básicamente no debería ocurrir nunca - desea que la rama por defecto un acuerdo de recompra pública de permanecer constante, en la rama estable (probablemente dominar) . origen/HEAD es una referencia local que representa una copia local de HEAD en el repositorio remoto. (Su nombre completo es refs/remotes/origin/HEAD.)

Creo que lo anterior responde a lo que realmente quería saber, pero para continuar y responder a la pregunta que hizo explícitamente, se establece origen/HEAD automáticamente cuando clonas un repositorio, y eso es todo. Curiosamente, es no establecido por comandos como git remote update - Creo que la única forma en que cambiará es si lo cambia manualmente. (Por cambio me refiero a punto a una rama diferente; obviamente, el cometer apunta a cambios si es que los cambios de la rama, lo que podría suceder en FETCH/tire/actualización remota.)


Editar: El problema discuten a continuación fue corregido en Git 1.8.4.3; ver this update.


Hay una pequeña advertencia, sin embargo. HEAD es una referencia simbólica, que apunta a una rama en lugar de directamente a una confirmación, pero los protocolos de transferencia remota de git solo informan confirmaciones para las referencias. Entonces, Git conoce el SHA1 de la confirmación señalada por HEAD y todos los demás refs; luego debe deducir el valor de HEAD al encontrar una rama que apunte al mismo compromiso. Esto significa que si dos ramas apuntan allí, es ambiguo. (Creo que recoge maestro, si es posible, entonces cae de nuevo a la primera orden alfabético.) Verá este informa en la salida del git remote show origin:

$ git remote show origin 
* remote origin 
    Fetch URL: ... 
    Push URL: ... 
    HEAD branch (remote HEAD is ambiguous, may be one of the following): 
    foo 
    master 

Curiosamente, aunque la idea de la cabeza de impresión de este modo va a cambiar si las cosas cambio en el control remoto (por ejemplo, si se elimina foo), en realidad no actualiza refs/remotes/origin/HEAD. Esto puede conducir a situaciones realmente extrañas. Digamos que en el ejemplo anterior, el origen/HEAD apuntaba a foo y luego se eliminaba la rama foo del origen. Entonces podemos hacer esto:

$ git remote show origin 
... 
HEAD branch: master 
$ git symbolic-ref refs/remotes/origin/HEAD 
refs/remotes/origin/foo 
$ git remote update --prune origin 
Fetching origin 
x [deleted]   (none)  -> origin/foo 
    (refs/remotes/origin/HEAD has become dangling) 

Así que aunque el show remoto sabe que HEAD es maestro, no actualiza nada. La rama foo obsoleta se poda correctamente, y la CABEZA queda colgando (apuntando a una rama inexistente), y todavía no la actualiza para apuntar a la maestra. Si quiere arreglar esto, use git remote set-head origin -a, que automáticamente determina el HEAD del origen como arriba, y luego realmente establece el origen/HEAD para apuntar a la rama remota apropiada.

+0

@jefromi Awesome answer! Solo una observación: escribe que * HEAD es una referencia simbólica, apuntando a una rama en lugar de directamente a una confirmación [...] *, pero podría valer la pena mencionar el "estado HEAD separado", para completar. – Jubobs

+0

Consulte mi actualización: http://stackoverflow.com/a/25430727/2541573 – Jubobs

+2

@Jubobs ¡Gracias! Si mi respuesta necesita actualización, siéntase libre de simplemente editarla; sin duda, le ahorrará tiempo a la gente leer un breve resumen de cómo funcionan las cosas en realidad, en lugar de tener que examinar lo que era verdad hace dos años y lo que es verdad ahora. . – Cascabel

38

Es su configuración como el propietario de su repositorio local. Cambiará como sigue:

git remote set-head origin some_branch 

y origen/HEAD apuntará a su sucursal en lugar de maestro. Esto se aplicaría solo a su repositorio y no a los demás. Por defecto, apuntará a maestro, a menos que se haya configurado algo más en el repositorio remoto.

Manual entry for remote set-head proporciona buena información al respecto.

Editar: para enfatizar: sin que usted lo diga, la única forma en que se "movería" sería un caso como renaming the master branch, que no creo que se considere "orgánico". Entonces, yo diría orgánicamente que no se mueve.

+1

El énfasis de edición no es completamente correcto aquí. También puede cambiar si clona desde una copia local que no está en la rama maestra. – mphair

+0

No considero un clon "en movimiento", pero creo que podemos estar en desacuerdo con eso :) – eis

7

Recuerde que hay dos git repos independientes estamos hablando. Su repositorio local con su código y el control remoto ejecutándose en otro lugar.

Tiene razón, cuando cambia una rama, HEAD apunta a su rama actual. Todo esto está sucediendo en su repo de git local. No es el repositorio remoto, que podría ser propiedad de otro desarrollador, ni el servidor de su oficina, ni github, ni otro directorio en el sistema de archivos, o ...

Su computadora (repositorio local) no tiene ningún negocio cambiando el puntero HEAD en el repositorio remoto de git. Podría ser propiedad de un desarrollador diferente, por ejemplo.

Una cosa más, lo que su computadora llama origen/XXX es la comprensión de su computadora del estado del control remoto en el momento de la última recuperación.

Entonces, ¿qué actualizaría "orgánicamente" origen/HEAD? Sería actividad en el repositorio remoto de git. No es su repositorio local.

personas han mencionado

git simbólico-árbitro general árbitros/cabeza/my_other_branch

Normalmente, que se utiliza cuando hay un repositorio git central compartido en el servidor para su uso por el desarrollo equipo. Sería un comando ejecutado en la computadora remota. Vería esto como actividad en el repositorio remoto de git.

+0

Lo siento, si soy un poco repetitivo. Solo quiero señalar el hecho de que git es un sistema de control de versiones distribuidas, y como tal, los dos repos son independientes. –

7

Descargo de responsabilidad: esta es una actualización de Jefromi's answer, que estoy escribiendo para ahorrar algo de tiempo.

Intenté en vano replicar (en Git 2.0.1) el mensaje remote HEAD is ambiguous que Jefromi menciona en su respuesta; así que hice un poco de excavación (clonando https://github.com/git/git y buscando en el registro).Solía ​​ser que

Determining HEAD is ambiguous since it is done by comparing SHA1s. 

In the case of multiple matches we return refs/heads/master if it 
matches, else we return the first match we encounter. builtin-remote 
needs all matches returned to it, so add a flag for it to request such. 

(Commit 4229f1fa325870d6b24fe2a4c7d2ed5f14c6f771, de fecha 27 de Feb, 2009 encontrado con git log --reverse --grep="HEAD is ambiguous")

Sin embargo, la ambigüedad en cuestión desde entonces ha sido levantado:

One long-standing flaw in the pack transfer protocol used by "git 
clone" was that there was no way to tell the other end which branch 
"HEAD" points at, and the receiving end needed to guess. A new 
capability has been defined in the pack protocol to convey this 
information so that cloning from a repository with more than one 
branches pointing at the same commit where the HEAD is at now 
reliably sets the initial branch in the resulting repository. 

(Commit 9196a2f8bd46d36a285bdfa03b4540ed3f01f671, de fecha 8 de Nov, 2013, encontrado con git log --grep="ambiguous" --grep="HEAD" --all-match)

Editar (gracias a torek):

$ git name-rev --name-only 9196a2f8bd46d36a285bdfa03b4540ed3f01f671 
tags/v1.8.4.3~3 

Esto significa que, si estás usando Git v1.8.4. 3 o posterior, no debería encontrarse con ningún problema ambiguo de HEAD remoto.

+1

Según las etiquetas en la fuente de git, esta corrección se aplica a la versión de Git 1.8.4.3 y posterior. – torek

+0

Necesito 1.8.4.3 o posterior en ambos lados, ¿verdad? –

+0

@RobertSiemer No estoy seguro, pero creo que sí, sí. – Jubobs

13

¿Qué mueve el origen/HEAD "orgánicamente"?

  • git clone conjuntos una vez al lugar donde la cabeza está en el origen
    • que sirve como la rama por defecto a la comprobación después de la clonación con git clone

Lo que hace de HEAD en ¿origen representa?

  • en repositorios desnudos (a menudo repositorios “en los servidores”) que sirve como un marcador para la rama predeterminada, porque git clone lo utiliza de tal manera
  • en repositorios no desnudos (local o remoto), refleja el pago actual del repositorio

¿Qué establece origen/HEAD?

  • git clone recuperaciones y establece que
  • que tendría sentido si git fetch lo actualiza como cualquier otra referencia, pero no
  • git remote set-head origin -a recuperaciones y lo establece
    • útil para actualizar la conocimiento local de qué remoto considera la "rama predeterminada"

Trivia

  • origin/HEAD también se puede ajustar a cualquier otro valor sin contactar el control remoto: git remote set-head origin <branch>
    • no veo caso de uso de este, excepto para las pruebas
  • desafortunadamente, nada es capaz de establecer HEAD en el control remoto
  • versiones anteriores de git d no sé a qué rama apunta HEAD en el control remoto, solo que hash commit finalmente tiene: así que con suerte eligió un nombre de rama que apunta al mismo hash
+0

Había perdido la referencia a 'origin/HEAD' y su solución ayudó. ¡Gracias! –

Cuestiones relacionadas