Introduzione
L'index è un file binario in .git/index che rispecchia un oggetto tree: una lista ordinata di path con mode, hash e info di stat. È la staging area per il prossimo commit e una cache che permette a Git di saltare il re-hashing di file invariati.
Ispezionarlo
git ls-files --stage
# 100644 a1b2c3... 0 README.md
# 100644 e4f5g6... 0 src/main.c
Stage 0 significa "nessun conflitto". Durante un merge, i path in conflitto ottengono gli stage 1 (base), 2 (ours), 3 (theirs).
Cosa ti dà il caching di stat
L'index memorizza anche ctime, mtime, dimensione e inode per ogni path. git status li confronta con la working tree prima dell'hashing; se corrispondono, il file è assunto invariato. Per questo git status è veloce su tree enormi.
git update-index --refresh
git update-index --really-refresh
Modificare l'index
git add file.txt # stage dalla working tree
git rm --cached file.txt # rimuovi dall'index, mantieni su disco
git restore --staged file.txt # togli dallo stage
git update-index --chmod=+x bin/run # cambia bit eseguibile
Assume unchanged e skip-worktree
Due flag dicono a Git di ignorare certi path:
git update-index --assume-unchanged config.local
git update-index --skip-worktree config.local
assume-unchanged: un suggerimento di performance; Git può comunque notare modifiche.skip-worktree: più forte; pensato per file che l'utente mantiene modificati localmente.
Nessuno dei due sostituisce .gitignore; entrambi sono hack locali allo workspace, non condivisibili.
Leggere e scrivere tree
git write-tree # snapshot dell'index come oggetto tree
git read-tree HEAD # resetta l'index a un tree
git read-tree --reset -u HEAD # aggiorna anche la working tree
Questi comandi plumbing sono alla base di commit, checkout e merge.
Conflitti nell'index
Durante un merge, l'index diventa la fonte di verità per ciò che non è risolto:
git ls-files -u
# 100644 a1... 1 src/main.c
# 100644 b2... 2 src/main.c
# 100644 c3... 3 src/main.c
Risolvere un conflitto significa scrivere il contenuto finale e fare git add, riducendo a una singola entry stage-0.
Sparse checkout e sparse index
Lo sparse checkout popola la working tree con solo un sottoinsieme del tree del repository, utile nei monorepo. Con la modalità cone più lo sparse index, l'index stesso si restringe al cono attivo, rendendo le operazioni veloci su repo enormi:
git sparse-checkout init --cone
git sparse-checkout set src/myteam docs
git sparse-checkout list
git sparse-checkout disable
Lo sparse index marca le entry omesse con un bit speciale così Git può espanderle pigramente solo quando i comandi ne hanno bisogno. Questa funzionalità richiede Git 2.32 o più recente per piena funzionalità.
Errori comuni
Credere che l'index sia solo "ciò che è in stage". È anche una cache e un tracker di conflitti. Cancellare .git/index quando si è bloccati; ricostruisci con git read-tree HEAD, ma perdi qualsiasi staging non committato. Usare --assume-unchanged come sostituto di .gitignore; il prossimo clone non lo onorerà. Infine, aspettarsi che l'index tracci directory vuote; non può. Usa un file segnaposto (.gitkeep) se devi committare una cartella vuota.