Vedi la documentazione di Git che dice cose del genere
Il ramo deve essere completamente unito in HEAD.
Ma cos'è HEAD
esattamente Git ?
Vedi la documentazione di Git che dice cose del genere
Il ramo deve essere completamente unito in HEAD.
Ma cos'è HEAD
esattamente Git ?
Risposte:
Puoi pensare a HEAD come al "ramo attuale". Quando si cambia ramo con git checkout
, la revisione HEAD cambia per puntare alla punta del nuovo ramo.
Puoi vedere a cosa punta HEAD facendo:
cat .git/HEAD
Nel mio caso, l'output è:
$ cat .git/HEAD
ref: refs/heads/master
È possibile che HEAD faccia riferimento a una revisione specifica che non è associata al nome di un ramo. Questa situazione si chiama HEAD distaccato .
Per citare altre persone :
Una testa è semplicemente un riferimento a un oggetto commit. Ogni testa ha un nome (nome del ramo o nome del tag, ecc.). Per impostazione predefinita, in ogni repository è presente un head chiamato master. Un repository può contenere qualsiasi numero di teste. In qualsiasi momento, una testa viene selezionata come "testa corrente". Questa testa è alata con HEAD, sempre in maiuscolo ".
Nota questa differenza: una "testa" (minuscola) si riferisce a una delle teste nominate nel repository; "HEAD" (maiuscolo) si riferisce esclusivamente alla testa attualmente attiva. Questa distinzione viene usata frequentemente nella documentazione di Git.
Un'altra buona fonte che copre rapidamente il funzionamento interno di git (e quindi una migliore comprensione delle teste / HEAD) può essere trovata qui . I riferimenti (ref :) o head o branch possono essere considerati come post-it bloccati su commit nella cronologia dei commit. Di solito indicano la punta di una serie di commit, ma possono essere spostati con git checkout
o git reset
ecc.
git checkout HEAD~2
), che non è l'id di commit di un capo noto. Vedi l'articolo su eagain.net/articles/git-for-computer-scientists per una spiegazione più approfondita.
git revert
non è un buon esempio di spostamento di un ramo per non essere in punta, perché git revert
crea solo alcuni nuovi commit e lascia comunque il ramo corrente in corrispondenza del (nuovo) suggerimento.
commit
s, reset
s, ecc.
Consiglio questa definizione dallo sviluppatore di github Scott Chacon [ riferimento video ]:
Head è il tuo ramo attuale. È un riferimento simbolico. È un riferimento a un ramo. Hai sempre HEAD, ma HEAD indicherà uno di questi altri puntatori, uno dei rami su cui ti trovi. È il genitore del tuo prossimo commit. È quello che dovrebbe essere quello che è stato estratto per ultimo nella directory di lavoro ... Questo è l'ultimo stato noto di quale fosse la directory di lavoro.
L'intero video fornirà una buona introduzione all'intero sistema git, quindi ti consiglio anche di guardarlo tutto se ne hai il tempo.
HEAD è solo un puntatore speciale che punta al ramo locale in cui ti trovi attualmente.
Dal libro Pro Git , capitolo 3.1 Git Branching - Branches in a Nutshell , nella sezione Creazione di un nuovo ramo :
Cosa succede se si crea una nuova filiale? Bene, così facendo si crea un nuovo puntatore per muoversi. Supponiamo che tu crei un nuovo ramo chiamato testing. Puoi farlo con il comando git branch:
$ git branch testing
Questo crea un nuovo puntatore allo stesso commit in cui ti trovi attualmente
Come fa Git a sapere su quale ramo sei attualmente? Mantiene un puntatore speciale chiamato HEAD. Nota che questo è molto diverso dal concetto di HEAD in altri VCS a cui potresti essere abituato, come Subversion o CVS. In Git, questo è un puntatore al ramo locale in cui ti trovi attualmente. In questo caso, sei ancora padrone. Il comando git branch ha creato solo un nuovo ramo - non è passato a quel ramo.
34ac2
nell'esempio sopra, ora HEAD punta a quel commit e si chiama HEAD distaccato. In questo stato, è possibile apportare modifiche, sperimentare e anche eseguire il commit delle modifiche, ma una volta verificato un ramo diverso, si perderanno tutte le modifiche, a meno che ovviamente non si crei un nuovo ramo.
git log
e ottenuto qualcosa del genere commit ad0265... HEAD -> foo ...
significherebbe che il foo
ramo è un riferimento a commit id ad0265
. Fare un checkout del riferimento testuale foo
non è una testa staccata. Fare un checkout dell'ID commit ad0265
si tradurrebbe in una testa staccata. Forse mi sto perdendo un po 'di delicatezza di ciò che stai comunicando. Spero che questo muro di testo aiuti a scoprire dove mi sono perso.
Supponendo che non si tratti di un caso speciale chiamato "TESTA staccata", quindi, come indicato nel libro di O'Reilly Git, 2a edizione, p.69, HEAD
significa:
HEAD
fa sempre riferimento al commit più recente sul ramo corrente. Quando si modificano i rami,HEAD
viene aggiornato per fare riferimento all'ultimo commit del nuovo ramo.
così
HEAD
è la "punta" del ramo corrente .
Si noti che possiamo utilizzare HEAD
per fare riferimento al commit più recente e utilizzare HEAD~
come commit prima del suggerimento e HEAD~~
o HEAD~2
come commit anche prima e così via.
C'è un malinteso, forse sottile, ma importante in un numero di queste risposte. Ho pensato di aggiungere la mia risposta per chiarirla.
Che cosa è
HEAD
?
HEAD
è un riferimento simbolico che punta a dove ti trovi nella cronologia dei commit. Ti segue ovunque tu vada, qualunque cosa tu faccia, come un'ombra. Se effettui un commit, HEAD
si sposterà. Se fai il checkout, HEAD
si sposterà. Qualunque cosa tu faccia, se ti sei trasferito in un posto nuovo nella tua cronologia di commit, si HEAD
è spostato insieme a te. Per affrontare un malinteso comune: non puoi staccartiHEAD
. Non è questo lo stato HEAD distaccato. Se mai ti ritrovi a pensare: "oh no, sono nello stato HEAD distaccato! Ho perso la HEAD!" Ricorda, è la tua TESTA. HEAD sei tu. Non ti sei staccato dalla TESTA, tu e la tua TESTA avete staccato da qualcos'altro.
HEAD
può indicare un commit, sì, ma in genere non lo fa. Lasciami dire di nuovo. In genere HEAD
non punta a un commit. Punta a un riferimento di ramo. È attaccato a quel ramo e quando fai certe cose (es. commit
O reset
), il ramo attaccato si sposterà insieme HEAD
. Puoi vedere a cosa sta puntando guardando sotto il cofano.
cat .git/HEAD
Normalmente otterrai qualcosa del genere:
ref: refs/heads/master
A volte otterrai qualcosa del genere:
a3c485d9688e3c6bc14b06ca1529f0e78edd3f86
Questo è ciò che accade quando HEAD
punta direttamente a un commit. Questo è chiamato HEAD distaccato, perché HEAD
punta a qualcosa di diverso da un riferimento di ramo. Se effettui un commit in questo stato, master
non essendoti più associato HEAD
, non si muoverà più con te. Non importa dove si trovi quel commit. Potresti essere sullo stesso commit del tuo ramo master, ma se HEAD
punta al commit anziché al ramo, viene rimosso e un nuovo commit non verrà associato a un riferimento di ramo.
Puoi osservarlo graficamente se provi il seguente esercizio. Da un repository git, esegui questo. Otterrai qualcosa di leggermente diverso, ma i loro bit chiave saranno lì. Quando è il momento di verificare direttamente il commit, usa qualsiasi hash abbreviato che ottieni dal primo output (eccolo a3c485d
).
git checkout master
git log --pretty=format:"%h: %d" -1
# a3c485d: (HEAD -> master)
git checkout a3c485d -q # (-q is for dramatic effect)
git log --pretty=format:"%h: %d" -1
# a3c485d: (HEAD, master)
OK, quindi c'è una piccola differenza nell'output qui. Il controllo diretto del commit (invece del ramo) ci dà una virgola anziché una freccia. Cosa ne pensi, siamo in uno stato HEAD distaccato? HEAD fa ancora riferimento a una revisione specifica associata al nome di un ramo. Siamo ancora nel ramo principale, vero?
Ora prova:
git status
# HEAD detached at a3c485d
No. Siamo nello stato "HEAD distaccato".
Puoi vedere la stessa rappresentazione di (HEAD -> branch)
vs. (HEAD, branch)
con git log -1
.
HEAD
sei tu. Indica qualsiasi cosa tu abbia verificato, ovunque tu sia. In genere questo non è un commit, è un ramo. Se HEAD
indica un commit (o tag), anche se è lo stesso commit (o tag) a cui punta anche un ramo, tu (e HEAD
) sei stato staccato da quel ramo. Dal momento che non hai un ramo attaccato a te, il ramo non ti seguirà mentre fai nuovi commit. HEAD
, tuttavia, lo farà.
.git/HEAD
è ciò che il software considera HEAD.
HEAD
si riferisce al commit corrente a cui punta la tua copia di lavoro, ovvero il commit che hai attualmente estratto. Dalla documentazione ufficiale del kernel Linux su come specificare le revisioni di Git :
HEAD
nomina il commit su cui hai basato le modifiche nell'albero di lavoro.
Si noti, tuttavia, che nella prossima versione 1.8.4 di Git, @
può anche essere usato come scorciatoia per HEAD
, come notato dal collaboratore di Git Junio C Hamano nel suo blog Git Blame :
Invece di digitare "HEAD", puoi invece pronunciare "@", ad esempio "git log @".
L'utente di Stack Overflow VonC ha anche trovato alcune informazioni interessanti sul perché è @
stato scelto come scorciatoia nella sua risposta a un'altra domanda .
Inoltre, in alcuni ambienti non è necessario capitalizzare HEAD
, in particolare nei sistemi operativi che utilizzano file system senza distinzione tra maiuscole e minuscole, in particolare Windows e OS X.
Dai un'occhiata a Creare e giocare con i rami
HEAD è in realtà un file il cui contenuto determina dove si riferisce la variabile HEAD:
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
35ede5c916f88d8ba5a9dd6afd69fcaf773f70ed
In questo repository, il contenuto del file HEAD si riferisce a un secondo file chiamato refs / heads / master . Il file refs / heads / master contiene l'hash del commit più recente sul ramo master.
Il risultato sono i punti HEAD sul commit della diramazione principale dal file .git / refs / heads / master .
Vorrei solo dettagliare alcune cose nella risposta accettata da Greg Hewgil. Secondo la Guida tascabile Git
Ramo:
il ramo stesso è definito come tutti i punti raggiungibili nel grafico di commit dal commit denominato (il "suggerimento" del ramo).
TESTA: un tipo speciale di rif
Lo speciale riferimento HEAD determina su quale ramo ti trovi ...
refs
Git definisce due tipi di riferimenti, o puntatori denominati, che chiama "refs":
- Un semplice riferimento, che punta direttamente a un ID oggetto (di solito un commit o tag)
- Un riferimento simbolico (o symref), che indica un altro riferimento (semplice o simbolico)
Come ha detto Greg, HEAD può essere in uno "stato distaccato". Quindi HEAD può essere sia un semplice ref (per una HEAD distaccata) che un symref.
se HEAD è un riferimento simbolico per un ramo esistente, allora sei su quel ramo. Se, d'altra parte, HEAD è un semplice ref che nomina direttamente un commit dal suo ID SHA-1, allora non sei "su" alcun ramo, ma piuttosto in modalità "staccata HEAD", che si verifica quando dai un'occhiata ad alcuni precedenti impegnarsi a esaminare.
Penso che "HEAD" sia il commit del check out corrente. In altre parole, "HEAD" indica il commit attualmente verificato.
Se hai appena clonato e non verificato, non so a cosa faccia riferimento, probabilmente una posizione non valida.
HEAD
è qualsiasi commit attualmente sottoposto a check-out. Consultare il manuale per i dettagli (il paragrafo pertinente segue immediatamente la Fig 3.4).
master
ramo - quindi HEAD punterà a master.
master
, ma non è sempre. Vediremote set-head
remote set-head
, che influisce solo sul ramo predefinito locale e non modificherà il valore predefinito sul server.
Testa punta sulla punta del ramo attualmente estratto.
Nel tuo repository, c'è una cartella .git. Apri il file in questa posizione: .git \ refs \ heads. Il codice (sha-1 hash) in quel file (master nella maggior parte dei casi) sarà il commit più recente, cioè quello visto nell'output del comando git log
. Maggiori informazioni sulla cartella .git: http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html
git reset HEAD^
, quindi il commit più recente (il precedente suggerimento) non è più indicato dalla punta del ramo.
Dopo aver letto tutte le risposte precedenti, volevo ancora più chiarezza. Questo blog sul sito Web ufficiale di git http://git-scm.com/blog mi ha dato quello che stavo cercando:
HEAD in Git è il puntatore al riferimento di ramo corrente, che a sua volta è un puntatore all'ultimo commit che hai fatto o all'ultimo commit che è stato estratto nella tua directory di lavoro. Ciò significa anche che sarà il genitore del prossimo commit che fai. In genere è più semplice pensarci perché HEAD è l'istantanea del tuo ultimo commit.
HEAD
non è un commit; si punta a uno.
checkout HEAD^
, ora HEAD non punta nemmeno all'ultima istantanea di commit su nessun ramo.
commit
, merge
, rebase
, log
, ecc, ma concettualmente forse "(puntatore) la posizione attuale" è la sintesi buona.
Sembra che HEAD
sia solo un tag per l'ultimo commit che hai verificato.
Questa può essere la punta di un ramo specifico (come "master") o un commit intermedio di un ramo ("testa staccata")
Oltre a tutte le definizioni, la cosa che mi è rimasta impressa nella mente è stata, quando si effettua un commit, GIT crea un oggetto commit all'interno del repository. Gli oggetti commit devono avere un genitore (o più genitori se si tratta di un commit di unione). Ora, come fa Git a conoscere il genitore dell'attuale commit? Quindi HEAD è un puntatore al (riferimento dell'ultimo) commit che diventerà il genitore del commit corrente.
Questi due potrebbero confonderti:
testa
Puntando a riferimenti nominati un ramo ha inviato di recente. A meno che non si utilizzi il riferimento al pacchetto, head viene in genere archiviato in $ GIT_DIR / refs / heads /.
TESTA
Ramo corrente, o il tuo albero di lavoro è generalmente generato dall'albero a cui punta HEAD. HEAD deve puntare a una testa, tranne per il fatto che stai usando una HEAD staccata.
Dai un'occhiata a http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is
Figura 3-5 File HEAD che punta al ramo in cui ti trovi.
HEAD
riferisce dipende dal fatto che tu stia parlando di un repository bare vs un non-bare. Nel contesto di un repository non nudo, si riferisce effettivamente al commit attualmente estratto, che non richiede che vi sia un ramo ad esso collegato (ovvero quando si trova in HEAD
stato distaccato ).
Un ramo è in realtà un puntatore che contiene un ID commit come 17a5 . HEAD è un puntatore a un ramo su cui l'utente sta attualmente lavorando.
HEAD ha un file di riferimento che assomiglia a questo:
ref:
È possibile controllare questi file accedendo .git/HEAD
.git/refs
al repository in cui si sta lavorando.
Git
si tratta di impegni.
E Head
indica il commit che hai attualmente verificato.
$ git cat-file -t HEAD
commit
Ogni volta che esegui il checkout di un ramo, HEAD punta all'ultimo commit su quel ramo. I contenuti di HEAD possono essere controllati come di seguito (per il ramo master):
$ cat .git/refs/heads/master
b089141cc8a7d89d606b2f7c15bfdc48640a8e25
Come concetto, la testa è l'ultima revisione in un ramo. Se hai più di una testa per ramo nominato, probabilmente lo hai creato quando esegui commit locali senza unire, creando effettivamente un ramo senza nome.
Per avere un repository "pulito", dovresti avere una testa per ramo nominato e unirti sempre a un ramo nominato dopo aver lavorato localmente.
Questo vale anche per Mercurial .