Cambia un HEAD remoto Git para apuntar a algo además del maestro


124

¿Cómo configuro la referencia HEAD de un control remoto Git para que apunte a algo además de "maestro"?

Mi proyecto tiene una política de no usar una rama "maestra" (todas las ramas deben tener nombres significativos). Además, el repositorio principal canónico solo es accesible a través de ssh: //, sin acceso a shell (como GitHub o Unfuddle).

Mi problema es que el repositorio remoto todavía tiene una referencia HEAD a refs / heads / master, pero necesito que apunte a una rama diferente. Esto está causando dos problemas:

  1. Al clonar el repositorio, ahí esto,

    advertencia: HEAD remoto se refiere a una referencia inexistente, incapaz de pagar.

    Eso es confuso e inconveniente.

  2. El navegador de código basado en la web depende de HEAD como base para explorar el árbol. Necesito HEAD para señalar una rama válida, entonces.


Acabo de agregar una posibilidad para el registro, pero no es adecuado para su caso.
VonC

Truco "no-ancestro común": interesante. Puede publicarlo como una respuesta detallada y seleccionarlo como oficial si lo encuentra funcionando.
VonC

12
FWIW, ya que mencionó GitHub en la pregunta: si desea cambiar la referencia HEAD en GitHub, simplemente vaya a la pantalla "Admin" del repositorio y cambie el menú desplegable "Rama predeterminada" a la rama a la que desee que apunte HEAD.
Joe


Respuestas:


63

Hubo casi la misma pregunta en GitHub hace un año.

La idea era cambiar el nombre de la rama maestra:

git branch -m master development
git branch -m published master
git push -f origin master 

Making Master tiene lo que quiere que la gente use y haga todo el trabajo en las ramas.

(un " git-symbolic-ref HEAD refs/head/published" no se propagaría al repositorio remoto)

Esto es similar a " Cómo elimino el origen / maestro en Git ".


Como se dijo en este hilo : (énfasis mío)

" git clone" crea una sola rama local.
Para hacer eso, observa el HEAD refrepositorio remoto y crea una rama local con el mismo nombre que la rama remota a la que hace referencia.

Entonces, para terminar, tienes el repositorio A y clónalo:

  • HEADreferencias refs/heads/mastery eso existe
    -> obtienes una rama local llamada master, comenzando desde el origen / master

  • HEAD referencias refs/heads/anotherBranchy eso existe
    -> obtienes una rama local llamada anotherBranch, comenzando desdeorigin/anotherBranch

  • HEAD referencias refs/heads/mastery eso no existe
    -> "git clone" se queja

No estoy seguro de si hay alguna forma de modificar directamente la HEADreferencia en un repositorio .

(que es el punto central de su pregunta, lo sé)


Quizás la única forma sería una "publicación para los pobres" , donde usted:

 $ git-symbolic-ref HEAD refs/head/published
 $ git-update-server-info
 $ rsync -az .git/* server:/local_path_to/git/myRepo.git/

Pero eso implicaría acceso de escritura al servidor, que no siempre es posible.


Como explico en " Git: ¿forma correcta de cambiar Active Branch en un repositorio simple? ", git remote set-headNo cambiaría nada en el repositorio remoto.

Solo cambiaría la rama de seguimiento remoto almacenada localmente en su repositorio local, en remotes/<name>/HEAD.


Gracias VonC. Lo leí antes de publicar aquí. Pero como puede ver, una rama llamada "maestro" no es bienvenida en este proyecto por razones técnicas y políticas.
JasonSmith

Luego, podría aplicar esa política al no permitir cualquier actualización en la rama maestra a través de un enlace previo a la confirmación.
VonC

Sí, si resulta que no hay forma de hacer lo que quiero, haré exactamente eso y aceptaré tu respuesta. ¡Gracias por seguir!
JasonSmith

Gracias por la actualización. Por el momento, utilicé el truco "no-ancestro común" para hacer una rama maestra con solo una confirmación. (Es decir: git branch -D master; echo ref: refs / heads / master> .git / HEAD; rm *). Luego toqué un archivo llamado GO_AWAY y el mensaje de confirmación explica la situación. Eso funcionará por ahora. Puedo verificar a través de la fuente y localizar dónde el lado receptor establece HEAD para una respuesta final.
JasonSmith

1
@ctn Eso es simplemente porque olvidé la opción -f( --force). He editado la respuesta en consecuencia. Luego, responda su referencia si usa esa misma opción.
VonC

42

Actualización: esto solo funciona para la copia local del repositorio (el "cliente"). Por favor, vea los comentarios de otros a continuación.

Con una versión reciente de git (febrero de 2014), el procedimiento correcto sería:

git remote set-head $REMOTE_NAME $BRANCH

Entonces, por ejemplo, cambiar la cabeza del control remoto origina la rama developsería:

git remote set-head origin develop


¿Esta característica necesita una versión reciente de git en el servidor o es suficiente si la máquina cliente tiene instalado git reciente?
Mikko Rantalainen

3
@Totor es conciso pero correcto; esta respuesta debería ser rechazada. Git tiene este concepto algo confuso de una "rama local predeterminada para el control remoto". Le permite escribir "origin" en lugar de "origin / defaultbranch" y es una cosa pura del lado del cliente . Larga historia en git-scm.com/docs/git-remote # set-head
MarcH

1
para confirmar de qué está hablando @MarchH: ejecutar git checkout -b default; git push origin HEAD; git remote set-head origin default. Luego, puede inspeccionar los cambios locales con cat .git/refs/remotes/origin/HEAD(debería ser ref: refs/remotes/origin/default) y la falta de cambios remotos con git remote show origin(seguirá siendo lo que sea antes de agregar la rama predeterminada).
De Novo

37

Ya que mencionas GitHub, para hacerlo en su sitio simplemente entra en tu proyecto, luego ...

admin > Default Branch > (choose something)

Hecho.


1
¡Excelente! Esa fue la última parte que faltaba.
berkus

Mi origen / HEAD ya apunta a una rama de características en lugar de master. Traté de cambiar la "rama principal" de un lado a otro, pero no afectó la CABEZA ... ¿Alguna sugerencia?
Daniil Shevelev

3
Configuración> Sucursales> Sucursal predeterminada
Chun Yang

12

Ver: http://www.kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html

Esto establece la rama predeterminada en el repositorio git. Puede ejecutar esto en repositorios desnudos o reflejados.

Uso:

$ git symbolic-ref HEAD refs/heads/<branch name>

66
$ git symbolic-ref HEAD refs / heads / name-of-branch
Lamy

Hice esto en mi repositorio remoto y solucionó mis problemas de clonación donde, por alguna razón, el encabezado era otro nombre de rama y, por lo tanto, intentar clonar el maestro daría lugar a un error al intentar cerrar el maestro en el compositor, esto podría ser muy específico para este escenario , pero otros podrían estar en esa posición y preguntándose qué hacer
Christopher Thomas

10

(Ya había básicamente la misma pregunta " crear una referencia simbólica git en el repositorio remoto ", que no recibió una respuesta universal).

Pero hay respuestas específicas para varias "granjas" de git (donde varios usuarios pueden administrar repositorios de git a través de una interfaz restringida: a través de http y ssh): http://Github.com , http://Gitorious.org , http: / /repo.or.cz , Girar ( http://git.altlinux.org ).

Estas respuestas específicas pueden ser útiles para quienes leen esta página y piensan en estos servicios específicos.


44
Ahora tienen un menú desplegable para seleccionar la rama HEAD en repo.or.cz (ejemplo: repo.or.cz/editproj.cgi?name=for-me-and-for-all_imz.git ) y gitorious.org , también. ¡Excelente!
imz - Ivan Zakharyaschev

7

Si tiene acceso al repositorio remoto desde un shell, simplemente vaya al .git (o al directorio principal si es un repositorio simple) y cambie el archivo HEAD para que apunte al encabezado correcto. Por ejemplo, por defecto siempre contiene 'refs: refs / heads / master', pero si necesita foo para ser el HEAD, simplemente edite el archivo HEAD y cambie el contenido a 'refs: refs / heads / foo'.


Tengo derechos de administrador en el servidor Git e hice exactamente lo mismo. Usamos Gitolite y fui al repositorio que creé. El nombre del directorio es myrepo.git. El contenido del archivo HEAD en el directorio dado se cambió de ref: refs/heads/mastera ref: refs/heads/mainline. Ahora, cuando trato de clonar el repositorio en mi cuadro local, todavía apunta a master. Ejecuté el git clone ssh://gitolite@git.server/myrepocomando. ¿Alguna idea para tal comportamiento?
Technext

Versión del servidor Git: git version 1.7.1& Versión del cliente Git:git version 1.9.4.msysgit.2
Technext

5

Puede crear una rama maestra separada utilizando solo comandos Git de porcelana:

git init
touch GO_AWAY
git add GO_AWAY
git commit -m "GO AWAY - this branch is detached from reality"

Eso nos da una rama maestra con un mensaje grosero (es posible que desee ser más educado). Ahora creamos nuestra rama "real" (llamémosla troncal en honor a SVN) y la divorciamos de master :

git checkout -b trunk
git rm GO_AWAY
git commit --amend --allow-empty -m "initial commit on detached trunk"

¡Listo! gitk --all mostrará master y trunk sin ningún enlace entre ellos.

La "magia" aquí es que --amend hace que git commit cree un nuevo commit con el mismo padre que el HEAD actual, luego haga que HEAD lo señale. Pero el HEAD actual no tiene un padre, ya que es la confirmación inicial en el repositorio, por lo que el nuevo HEAD tampoco tiene uno, lo que los separa uno del otro.

El antiguo comando HEAD no se elimina con git-gc porque todavía lo apunta refs / heads / master.

La bandera --allow-empty solo es necesaria porque estamos cometiendo un árbol vacío. Si hubiera algunos git add después de git rm, entonces no sería necesario.

En verdad, puede crear una rama separada en cualquier momento ramificando la confirmación inicial en el repositorio, eliminando su árbol, agregando su árbol separado, luego haciendo git commit --amend .

Sé que esto no responde a la pregunta de cómo modificar la rama predeterminada en el repositorio remoto, pero da una respuesta clara sobre cómo crear una rama separada.


1
Puede crear una rama separada más fácilmente recuperando una rama no relacionada de otro repositorio y dándole un nombre. Por ejemplo, git fetch git:user@example.com:foo remote-branch-name && git checkout -b detached-branch FETCH_HEADagregará una nueva rama detached-branchque coincida con la rama remote-branch-nameen remoto git:user@example.com:foo. Por supuesto, el "control remoto" puede ser un repositorio en el sistema de archivos local que haya preparado previamente.
Mikko Rantalainen

2

Primero, cree la nueva rama que desea establecer como predeterminada, por ejemplo:

$>git branch main

Luego, empuja esa rama al origen :

$>git push origin main

Ahora, cuando inicie sesión en su cuenta de GitHub, puede ir a su repositorio y elegir Configuración> Rama predeterminada y elegir " principal ".

Luego, si así lo elige, puede eliminar la rama maestra:

$>git push origin :master


El punto clave a entender es que si su proveedor de alojamiento (GitHub en este ejemplo) no proporciona un método para modificar la rama predeterminada, no tiene suerte. El protocolo Git no proporciona una función para modificar la rama predeterminada remota; necesitaría poder ejecutar git symbolic-refen el shell remoto o modificar el archivo de texto llamado HEADen el directorio raíz del repositorio remoto.
Mikko Rantalainen

2

Relacionado con la pregunta, terminé aquí cuando buscaba:

¿Cómo hago para que un repositorio local tenga conocimiento de una rama predeterminada modificada en GitHub?

Para completar, agregando la respuesta:

git remote set-head origin -a

0

Para las personas con gitolita, la gitolita admite un comando llamado "espera" symbolic-ref. Le permite ejecutar ese comando de forma remota si tiene permiso W (escritura) para el repositorio.


-1

Sencillo sólo tienes que entrar en su cuenta de GitHub y en el lado de la derecha en el menú de navegación elija Configuración , en la ficha Configuración elegir rama por defecto y volver volver a la página principal de su repositorio que hizo el truco para mí.


1
Si bien muestra la nueva rama como predeterminada en la interfaz de GitHub, al hacer un clon git [repo], no obtengo esa rama. es decir .git / HEAD contiene la referencia incorrecta.
Joseph Sheedy
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.