Introduzione
Tutto ciò che Git sa su un repository vive in .git/. Sapere cosa è ogni entry rimuove il mistero dalle diagnostiche "cosa è appena successo?".
Layout di alto livello
.git/
HEAD # ref simbolico al branch corrente
config # configurazione locale del repository
description # usato da gitweb
index # la staging area
packed-refs # ref di branch e tag impacchettati (opzionale)
hooks/ # script di hook lato client
info/ # file di exclude e altre info locali al repo
logs/ # reflog
objects/ # tutti gli oggetti (loose + pack/)
refs/ # branch, tag, tracking remoto
worktrees/ # worktree linkati (se ci sono)
modules/ # directory .git dei submodule
HEAD e refs
cat .git/HEAD
ls .git/refs/heads
ls .git/refs/remotes/origin
ls .git/refs/tags
cat .git/packed-refs | head
objects/
Oggetti loose sotto objects/xx/, oggetti packed in objects/pack/. Non toccare a mano.
logs/
Il reflog. logs/HEAD registra ogni movimento di HEAD; logs/refs/heads/<branch> registra la storia di ogni branch.
cat .git/logs/HEAD | head
hooks/
Script di hook di esempio, tutti chiamati *.sample per default. Per abilitare, togli il suffisso e rendi eseguibile:
cd .git/hooks
cp pre-commit.sample pre-commit
chmod +x pre-commit
info/
info/exclude è un file di ignore per repo, per clone (non committato). info/refs è generato da git update-server-info per server HTTP dumb.
config
Configurazione locale in formato INI. Modifica via git config --local o git config -e:
cat .git/config
git config --local user.email "[email protected]"
worktrees/
Ogni worktree linkato ha una directory sotto .git/worktrees/<name>/ con il proprio HEAD, index e logs.
modules/
Per i repo con submodule, la directory .git di ogni submodule vive qui, e la working tree del submodule contiene un piccolo file .git che punta ad essa.
Repository bare
Un repo bare ha gli stessi contenuti ma al livello superiore (nessun wrapper .git/) e nessuna working tree. Convenzione: nominare la directory project.git.
git rev-parse per i path
Gli script che hanno bisogno di trovare path dentro .git/ non dovrebbero mai assumere che la directory sia letteralmente chiamata .git. I submodule usano un file .git che punta altrove; i worktree hanno gitdir linkati; i repo bare non hanno gitdir separato. Usa git rev-parse:
git rev-parse --git-dir # gitdir effettiva per il repo corrente
git rev-parse --git-common-dir # dir condivisa per i worktree
git rev-parse --show-toplevel # radice della working tree
git rev-parse --is-inside-git-dir
git rev-parse --is-inside-work-tree
Queste cinque domande coprono quasi ogni controllo "dove sono?" di cui uno script ha bisogno.
Errori comuni
Modificare i file dentro .git/ direttamente. Quasi tutto ha un comando Git che lo fa correttamente, atomicamente e con gli hook. Fare backup solo della working tree e dimenticare che .git/ contiene l'intera storia; fai il backup di tutta la directory. Condividere .git/hooks/ assumendo che si propaghi; gli hook non sono versionati. Usa core.hooksPath o uno strumento come pre-commit per condividerli. Infine, cancellare .git/index d'impulso; ricostruisci con git read-tree HEAD, ma solo dopo aver fatto un backup.