Cambia una HEAD remota di Git per puntare a qualcosa oltre a master


124

Come imposto il riferimento HEAD di un telecomando Git in modo che punti a qualcosa oltre a "master"?

Il mio progetto prevede una politica di non utilizzare un ramo "master" (tutti i rami devono avere nomi significativi). Inoltre, il repository principale canonico è accessibile solo tramite ssh: //, senza accesso alla shell (come GitHub o Unfuddle).

Il mio problema è che il repository remoto ha ancora un riferimento HEAD a refs / heads / master, ma ho bisogno che punti a un ramo diverso. Ciò sta causando due problemi:

  1. Quando si clona il repository, ecco questo,

    avvertenza: HEAD remoto si riferisce a ref inesistente, impossibile effettuare il checkout.

    Questo è confuso e scomodo.

  2. Il browser del codice basato sul web dipende da HEAD come base per la navigazione nell'albero. Allora ho bisogno che HEAD indichi un ramo valido.


È stata aggiunta solo una possibilità per la registrazione, ma non adatta al tuo caso.
VonC

trucco "nessun antenato comune": interessante. Puoi pubblicarlo come risposta dettagliata e selezionarlo come ufficiale se trovi che funziona.
VonC,

12
FWIW, dal momento che hai menzionato GitHub nella domanda, se vuoi cambiare il riferimento HEAD su GitHub, vai alla schermata "Admin" del repository e cambia il menu a discesa "Default Branch" in qualsiasi ramo a cui desideri che HEAD punti.
Joe


Risposte:


63

C'era quasi la stessa domanda su GitHub un anno fa.

L'idea era di rinominare il ramo principale:

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

Fare in modo che il maestro abbia quello che vuoi che le persone usino e fai tutto il resto del lavoro nei rami.

(un "git-symbolic-ref HEAD refs/head/published " non verrebbe propagato al repository remoto)

Questo è simile a " Come faccio a eliminare origin / master in Git ".


Come detto in questo thread : (enfasi mia)

" git clone" crea solo un singolo ramo locale.
Per farlo, guarda il fileHEAD ref repository remoto e crea un ramo locale con lo stesso nome del ramo remoto a cui fa riferimento.

Quindi, per concludere, hai repo A e clonalo:

  • HEADriferimenti refs/heads/mastere che esiste
    -> ottieni un ramo locale chiamato master, a partire da origin / master

  • Riferimenti a HEAD refs/heads/anotherBranche che esistono
    -> ottieni un ramo locale chiamato anotherBranch, a partire daorigin/anotherBranch

  • Riferimenti a HEAD refs/heads/mastere che non esistono
    -> "git clone" si lamenta

Non sono sicuro che ci sia un modo per modificare direttamente il HEADref in un repo .

(che è il punto centrale della tua domanda, lo so;))


Forse l'unico modo sarebbe una "pubblicazione per i poveri" , dove tu:

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

Ma ciò comporterebbe l'accesso in scrittura al server, che non è sempre possibile.


Come spiego in " Git: modo corretto di modificare Active Branch in un semplice repository? ",git remote set-head Non cambierebbe nulla sul repository remoto.

Cambierà solo il ramo di monitoraggio remoto memorizzato localmente nel tuo repository locale, in remotes/<name>/HEAD.


Grazie, VonC. L'ho letto prima di postare qui. Ma come puoi vedere, un ramo chiamato "master" non è il benvenuto in questo progetto per ragioni tecniche e politiche.
JasonSmith,

È quindi possibile applicare tale politica disabilitando qualsiasi aggiornamento sul ramo principale tramite un hook pre-commit.
VonC

Sì, se si scopre che non c'è modo di fare quello che voglio, lo farò esattamente e accetterò la tua risposta. Grazie per il seguito!
JasonSmith,

Grazie per l'aggiornamento. Per il momento, ho usato il trucco "no-common-ancestor" per creare un ramo master con un solo commit. (Ad esempio: git branch -D master; echo ref: refs / heads / master> .git / HEAD; rm *). Quindi ho appena toccato un file chiamato GO_AWAY e il messaggio di commit spiega la situazione. Per ora funzionerà. Posso controllare la fonte e rintracciare dove il lato ricevente imposta HEAD per una risposta finale.
JasonSmith,

1
@ctn Questo è semplicemente perché ho dimenticato l' opzione -f( --force). Ho modificato la risposta di conseguenza. Quindi la risposta a cui fai riferimento utilizza la stessa opzione.
VonC

42

Aggiornamento: funziona solo per la copia locale del repository (il "client"). Si prega di vedere i commenti degli altri di seguito.

Con una versione recente di git (febbraio 2014), la procedura corretta sarebbe:

git remote set-head $REMOTE_NAME $BRANCH

Quindi, ad esempio, passare la testina da remoto origina ramo developsarebbe:

git remote set-head origin develop


Questa funzione richiede una versione recente di git sul server o è sufficiente se sulla macchina client è installato git recente?
Mikko Rantalainen

3
@Totor è conciso ma corretto; questa risposta dovrebbe essere sottovalutata. Git ha questo concetto un po 'confuso di un "ramo predefinito locale per il remoto". Ti permette di digitare "origin" invece di "origin / defaultbranch" ed è una pura cosa lato client . Lunga storia su git-scm.com/docs/git-remote # set-head
MarcH

1
per confermare di cosa sta parlando @MarchH: run git checkout -b default; git push origin HEAD; git remote set-head origin default. È quindi possibile ispezionare le modifiche locali con cat .git/refs/remotes/origin/HEAD(dovrebbe essere ref: refs/remotes/origin/default) e la mancanza di modifiche remote con git remote show origin(sarà ancora qualunque cosa fosse prima di aggiungere il ramo predefinito).
De Novo

37

Dato che hai menzionato GitHub, per farlo sul loro sito vai semplicemente nel tuo progetto, quindi ...

admin > Default Branch > (choose something)

Fatto.


1
Eccellente! Quello era l'ultimo pezzo mancante.
berkus

La mia origine / HEAD punta già a un ramo di funzionalità anziché a master. Ho provato a cambiare "ramo principale" avanti e indietro, ma non ha influenzato la TESTA ... Qualche suggerimento?
Daniil Shevelev

3
Impostazioni> Filiali> Ramo predefinito
Chun Yang

12

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

Questo imposta il ramo predefinito nel repository git. Puoi eseguirlo in repository nudi o con mirroring.

Uso:

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

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

L'ho fatto nel mio repository remoto e ha risolto i miei problemi di clonazione dove per qualche motivo la testa era un altro nome di ramo e quindi provare a clonare master avrebbe comportato un errore durante il tentativo di chiudere il master in composer, questo potrebbe essere molto specifico per questo scenario , ma altri potrebbero essere in quella posizione e chiedersi cosa fare
Christopher Thomas

10

(C'era già fondamentalmente la stessa domanda " crea un ref simbolico git nel repository remoto ", che non ha ricevuto risposta universale.)

Ma ci sono risposte specifiche per varie "fattorie" git (dove più utenti possono gestire i repository git attraverso un'interfaccia limitata: tramite http e ssh): http://Github.com , http://Gitorious.org , http: / /repo.or.cz , Girar ( http://git.altlinux.org ).

Queste risposte specifiche potrebbero essere utili per chi legge questa pagina e pensa a questi servizi specifici.


4
Ora hanno un menu a discesa per selezionare il ramo HEAD su repo.or.cz (esempio: repo.or.cz/editproj.cgi?name=for-me-and-for-all_imz.git ) e gitorious.org , pure. Grande!
imz - Ivan Zakharyaschev

7

Se hai accesso al repository remoto da una shell, vai nel .git (o nella directory principale se è un repository semplice) e modifica il file HEAD in modo che punti all'header corretto. Ad esempio, per impostazione predefinita contiene sempre "refs: refs / heads / master", ma se invece è necessario che foo sia HEAD, è sufficiente modificare il file HEAD e cambiare il contenuto in "refs: refs / heads / foo".


Ho i diritti di amministratore sul server Git e ho fatto esattamente lo stesso. Usiamo Gitolite e sono andato al repository che ho creato. Il nome della directory è myrepo.git. Il contenuto del file HEAD nella directory specificata è stato modificato da ref: refs/heads/mastera ref: refs/heads/mainline. Ora, quando provo a clonare il repository sulla mia casella locale, punta ancora a master. Ho eseguito il git clone ssh://gitolite@git.server/myrepocomando. Qualche idea per un simile comportamento?
Technext

Versione server Git: git version 1.7.1& Versione client Git:git version 1.9.4.msysgit.2
Technext

5

Puoi creare un ramo principale distaccato usando solo comandi Git in porcellana:

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

Questo ci dà un ramo principale con un messaggio scortese (potresti voler essere più educato). Ora creiamo il nostro ramo "reale" (chiamiamolo tronco in onore di SVN) e lo separiamo dal master :

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

Ehi, presto! gitk --all mostrerà master e trunk senza alcun collegamento tra di loro.

La "magia" qui è che --amend fa sì che git commit crei un nuovo commit con lo stesso genitore dell'attuale HEAD, quindi fa in modo che HEAD punti ad esso. Ma l'attuale HEAD non ha un genitore poiché è il commit iniziale nel repository, quindi nemmeno il nuovo HEAD ne ottiene uno, rendendoli separati l'uno dall'altro.

Il vecchio commit HEAD non viene eliminato da git-gc perché refs / heads / master punta ancora ad esso.

Il flag --allow-empty è necessario solo perché stiamo eseguendo il commit di un albero vuoto. Se ci fossero alcuni add di git dopo git rm non sarebbe necessario.

In verità, puoi creare un ramo scollegato in qualsiasi momento ramificando il commit iniziale nel repository, eliminando il suo albero, aggiungendo il tuo albero scollegato, quindi eseguendo git commit --amend .

So che questo non risponde alla domanda su come modificare il ramo predefinito sul repository remoto, ma fornisce una risposta chiara su come creare un ramo distaccato.


1
È possibile creare un ramo distaccato più facilmente recuperando un ramo non correlato da un altro repository e assegnandogli un nome. Ad esempio, git fetch git:user@example.com:foo remote-branch-name && git checkout -b detached-branch FETCH_HEADaggiungerà un nuovo ramo detached-branchche corrisponde al ramo remote-branch-namein remoto git:user@example.com:foo. Naturalmente, il "remoto" può essere un repository nel file system locale che hai precedentemente preparato.
Mikko Rantalainen

2

Innanzitutto, crea il nuovo ramo che desideri impostare come predefinito, ad esempio:

$>git branch main

Quindi, sposta quel ramo all'origine :

$>git push origin main

Ora, quando accedi al tuo account GitHub, puoi andare al tuo repository e scegliere Impostazioni> Ramo predefinito e scegliere " principale ".

Quindi, se lo desideri, puoi eliminare il ramo principale:

$>git push origin :master


Il punto chiave da capire è che se il tuo provider di hosting (GitHub in questo esempio) non fornisce un metodo per modificare il ramo predefinito, sei sfortunato. Il protocollo Git non fornisce una funzionalità per modificare il ramo predefinito remoto; dovresti essere in grado di eseguire git symbolic-refsulla shell remota o altrimenti in grado di modificare il file di testo chiamato HEADnella directory principale del repository remoto.
Mikko Rantalainen

2

In relazione alla domanda, sono finito qui durante la ricerca di:

Come faccio a rendere un repository locale consapevole di un ramo predefinito modificato su GitHub

Per completezza, aggiungendo la risposta:

git remote set-head origin -a

0

Per le persone gitolite, gitolite supporta un comando chiamato - aspetta - symbolic-ref. Ti consente di eseguire quel comando in remoto se disponi dell'autorizzazione W (scrittura) per il repository.


-1

Semplicemente accedi al tuo account GitHub e sull'estrema destra nel menu di navigazione scegli Impostazioni , nella scheda Impostazioni scegli Ramo predefinito e torna alla pagina principale del tuo repository che ha fatto il trucco per me.


1
Sebbene mostri il nuovo ramo come predefinito nell'interfaccia GitHub, quando eseguo un git clone [repo], non ottengo quel ramo. cioè .git / HEAD contiene il riferimento sbagliato.
Joseph Sheedy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.