Git 04
🔀 Git & GitHub · Modulo 1 · Lezione 04
Il ciclo di lavoro 🔄
I tre stati di un file · Working directory · Staging area · Repository · git status in profondità
🧠 Nella Lezione 03 hai imparato i comandi. In questa lezione capisci il modello mentale. La differenza tra chi usa Git a memoria e chi lo capisce sta nella comprensione dei tre stati e delle tre aree. Quando sai leggere git status come un professionista, sai sempre dove sei e cosa fare — anche quando qualcosa va storto.
🎯 Obiettivi della lezione
- Comprendere in profondità le tre aree di Git: working directory, staging area, repository
- Conoscere tutti gli stati possibili di un file: untracked, tracked, modified, staged, committed
- Leggere e interpretare ogni riga dell’output di
git status - Capire cosa succede quando si modifica un file già in staging
- Usare
git add -pper aggiungere solo parti di un file - Togliere un file dalla staging area senza perdere le modifiche
📖 1. Teoria
1.1 — Le tre aree di Git: il modello completo
Nella Lezione 01 abbiamo introdotto le tre aree. Nella Lezione 03 le abbiamo usate in pratica. Ora le approfondiamo — perché capire perché esistono è la chiave per padroneggiare Git.
Git la osserva ma non salva automaticamente nulla. Le modifiche qui sono “provvisorie” finché non le promuovi con
git add.Analogia: il tavolo da lavoro. Puoi sparpagliare fogli, fare bozze, cancellare — niente è definitivo.
git add. Si chiama anche index.La staging area è una bozza del prossimo snapshot: puoi aggiungere, togliere, modificare la selezione finché non sei soddisfatto. Solo quando fai
git commit la bozza diventa definitiva.Analogia: la busta in cui raccogli i fogli da consegnare. Puoi aggiungere e togliere fogli prima di sigillarla.
.git. Ogni git commit aggiunge uno snapshot immutabile qui.Gli snapshot non si cancellano e non si modificano (a meno di operazioni avanzate come
rebase). La storia è permanente e sicura.Analogia: l’archivio. I fogli consegnati finiscono qui — datati, firmati, per sempre.
📌 Perché la staging area non è inutile: la domanda più frequente dei principianti è “perché non fare direttamente commit senza staging?”. La risposta è il controllo. Immagina di aver modificato 5 file: 3 per una nuova funzione e 2 per un bug fix. Con la staging area puoi fare due commit separati e puliti — prima i 3 file della funzione, poi i 2 del bug fix. Senza staging, dovresti committare tutto insieme in un unico commit caotico.
1.2 — I cinque stati di un file
Un file nel tuo repository può trovarsi in uno di cinque stati. Capire questi stati è capire Git.
| Stato | Significato | Dove si trova | Colore in git status |
|---|---|---|---|
| Untracked | File nuovo — Git non l’ha mai visto | Solo nella working directory | 🔴 Rosso |
| Modified | File tracciato, ma cambiato rispetto all’ultimo commit | Working directory (modifiche non in staging) | 🔴 Rosso |
| Staged | Modifiche selezionate per il prossimo commit | Staging area | 🟢 Verde |
| Committed | Salvato nel repository — identico all’ultimo commit | Repository | Non appare (è “pulito”) |
| Deleted | File tracciato che è stato cancellato | Working directory (assente) | 🔴 Rosso |
Git lo ignora
git add
il commit
git commit
pulito
modifica
non in staging
git add, poi a Committed con git commit. Il ciclo si ripete all’infinito.1.3 — Leggere git status come un professionista
L’output di git status è diviso in tre sezioni, ciascuna corrispondente a un’area. Impara a leggerle tutte e saprai sempre dove sei.
On branch main
Changes to be committed: ← SEZIONE 1: Staging area (verde)
(use “git restore –staged <file>…” to unstage)
modified: README.md
new file: index.html
Changes not staged for commit: ← SEZIONE 2: Working dir, tracciati (rosso)
(use “git add <file>…” to update what will be committed)
(use “git restore <file>…” to discard changes)
modified: style.css
Untracked files: ← SEZIONE 3: File nuovi, non tracciati (rosso)
(use “git add <file>…” to include in what will be committed)
notes.txt
| Sezione | Cosa significa | Azione |
|---|---|---|
| Changes to be committed | File nella staging area — andranno nel prossimo commit | git commit per salvarli, oppure git restore --staged per toglierli dalla staging |
| Changes not staged | File tracciati che sono stati modificati ma non aggiunti alla staging | git add per includerli, oppure git restore per scartare le modifiche |
| Untracked files | File nuovi che Git non ha mai visto | git add per iniziare a tracciarli, oppure ignorarli (li vedremo con .gitignore) |
📌 Trucco mnemonico: verde = va nel commit, rosso = non va nel commit (a meno che non fai git add). Se fai git commit adesso, solo i file verdi vengono salvati. I rossi restano dove sono.
1.4 — Il caso tricky: un file sia staged che modified
Questo è il punto che confonde tutti all’inizio. Un file può apparire contemporaneamente in verde (staged) e in rosso (modified). Come è possibile?
style.css — aggiungi una riga di codice CSS.git add style.css — Git fotografa lo stato attuale e lo mette in staging.style.css — aggiungi un’altra riga.git status mostra style.css sia in verde che in rosso. La versione in staging è quella del Passo 2. La versione nella working directory è quella del Passo 3. Se fai commit ora, salvi solo le modifiche del Passo 2.On branch main
Changes to be committed:
modified: style.css ← la versione del Passo 2
Changes not staged for commit:
modified: style.css ← le modifiche del Passo 3 (non ancora in staging)
git commit senza toccare nient’altro. Il commit salva la versione in staging (Passo 2). Le modifiche del Passo 3 restano nella working directory come “not staged”. Potrai aggiungerle al prossimo commit.
git add style.css — questo aggiorna la staging area con la versione più recente (Passo 3). Ora git status mostra il file solo in verde. Poi fai git commit per salvare tutto.
1.5 — Togliere un file dalla staging area
Hai fatto git add per errore? Nessun problema — puoi togliere un file dalla staging area senza perdere le modifiche. Il file torna semplicemente allo stato “modified” o “untracked”.
$ git add password.txt # oops!
$ git status
new file: password.txt ← in verde, pronto per il commit
# Togliamolo dalla staging (ma teniamo il file)
$ git restore –staged password.txt
$ git status
password.txt ← tornato in rosso (untracked), ma il file esiste ancora
| Comando | Effetto | Le modifiche si perdono? |
|---|---|---|
| git restore –staged file | Toglie il file dalla staging area | No — le modifiche restano nella working directory |
| git restore file | Scarta le modifiche nella working directory | Sì! — il file torna alla versione dell’ultimo commit |
⚠️ Attenzione alla differenza: git restore --staged file (con --staged) è sicuro — toglie dalla staging senza toccare il file. git restore file (senza --staged) è distruttivo — cancella le modifiche nella working directory e le sostituisce con la versione dell’ultimo commit. Non c’è undo. Approfondiremo nella Lezione 06.
1.6 — git add -p: staging chirurgica
Hai modificato un file in due punti — una modifica è per una funzione nuova, l’altra è un fix. Vuoi fare due commit separati, ma le modifiche sono nello stesso file. Come fare?
git add -p (dove -p sta per patch) ti mostra le modifiche pezzo per pezzo e ti chiede: “Vuoi aggiungere questo blocco alla staging area?”
diff –git a/style.css b/style.css
— a/style.css
+++ b/style.css
@@ -1,3 +1,5 @@
body {
+ background: #f0f0f0; ← modifica 1
font-family: Arial;
+ color: #333; ← modifica 2
}
Stage this hunk [y,n,q,a,d,s,e,?]? ← Git ti chiede cosa fare
| Tasto | Significato |
|---|---|
| y | Yes — aggiungi questo blocco alla staging area |
| n | No — salta questo blocco (non aggiungerlo) |
| s | Split — dividi il blocco in pezzi più piccoli (se possibile) |
| q | Quit — esci (quello che hai già scelto resta in staging) |
| ? | Help — mostra tutti i tasti disponibili |
git add -p ogni volta. Per ora basta sapere che esiste — lo userai quando avrai bisogno di commit chirurgici su file con modifiche miste.1.7 — git status -s: la versione compatta
Quando hai molti file, l’output standard di git status è verboso. La versione compatta mostra una riga per file con un codice a due lettere:
M README.md ← M in colonna 1 (staging) = modified e staged
A index.html ← A in colonna 1 = new file, staged
M style.css ← M in colonna 2 (working dir) = modified, non staged
?? notes.txt ← ?? = untracked
MM app.js ← M+M = staged E poi modificato di nuovo (caso tricky!)
| Colonna 1 | Colonna 2 | Significato |
|---|---|---|
| Staging area | Working dir | Colonna 1 = stato in staging. Colonna 2 = stato nella working directory. |
| M | · | Modified e staged — pronto per il commit |
| · | M | Modified ma non staged — serve git add |
| A | · | File nuovo aggiunto alla staging |
| ? | ? | Untracked — Git non lo conosce |
1.8 — Riepilogo visuale: cosa fa ogni comando
git restore file↑ ripristina dal commit
⚠️ distruttivo
git add file →sposta qui dalla working dir
git restore --staged file↑ rimuovi dalla staging
✅ sicuro
git commit -m "..." →salva lo snapshot dalla staging
git logmostra la storia dei commit
💻 2. Esempi guidati
Esempio A — Osservare tutti gli stati di un file
$ mkdir lab-stati && cd lab-stati && git init
# STATO: Untracked
$ echo “versione 1” > file.txt
$ git status -s
?? file.txt
# STATO: Staged (new file)
$ git add file.txt
$ git status -s
A file.txt
# STATO: Committed (clean)
$ git commit -m “Aggiunto file.txt v1”
$ git status -s
(nessun output = tutto pulito)
# STATO: Modified (not staged)
$ echo “versione 2” > file.txt
$ git status -s
M file.txt
# STATO: Staged (modified)
$ git add file.txt
$ git status -s
M file.txt
# STATO: Staged + Modified (il caso tricky)
$ echo “versione 3” >> file.txt # aggiunge una riga DOPO il git add
$ git status -s
MM file.txt ← prima colonna verde (staged v2), seconda rossa (v3 non staged)
Esempio B — Unstaging: togliere un file dalla staging area
# file.txt è in stato MM (staged + modified)
# Togliamo file.txt dalla staging (manteniamo le modifiche)
$ git restore –staged file.txt
$ git status -s
M file.txt ← tornato a “modified not staged” — le modifiche ci sono ancora
# Verifichiamo che il contenuto è intatto
$ cat file.txt
versione 2
versione 3 ← entrambe le modifiche sono ancora qui
# Ora ri-aggiungiamo tutto e committiamo
$ git add file.txt
$ git commit -m “Aggiornato file.txt a v2+v3”
Esempio C — Staging selettiva con più file
$ echo “header” > header.html
$ echo “footer” > footer.html
$ echo “TODO: comprare il latte” > todo.txt
$ echo “password123” > secret.txt
$ git status -s
?? footer.html
?? header.html
?? secret.txt
?? todo.txt
# Commit 1: solo i file HTML (correlati tra loro)
$ git add header.html footer.html
$ git commit -m “Aggiunti header e footer del sito”
# Commit 2: il file todo (personale, non correlato)
$ git add todo.txt
$ git commit -m “Aggiunta lista TODO personale”
# secret.txt NON lo aggiungiamo — non deve finire nel repository!
$ git status -s
?? secret.txt ← resta untracked, non verrà mai committato (per ora)
$ git log –oneline
b4c2e1f Aggiunta lista TODO personale
8a3d5c2 Aggiunti header e footer del sito
f7e1a9b Aggiornato file.txt a v2+v3
a3b8f2c Aggiunto file.txt v1
🏋️ 3. Esercizi
🟢 Esercizio 1 — Predici git status (Facile)
Per ciascuna sequenza di comandi, prevedi l’output di git status -s prima di eseguirlo. Poi verifica.
mkdir test1 && cd test1 && git init
echo “ciao” > a.txt
git status -s → previsione: ???
Sequenza B: (continua dalla A)
git add a.txt
git status -s → previsione: ???
Sequenza C: (continua dalla B)
git commit -m “primo”
git status -s → previsione: ???
Sequenza D: (continua dalla C)
echo “mondo” >> a.txt
echo “nuovo” > b.txt
git status -s → previsione: ???
Sequenza E: (continua dalla D)
git add a.txt
git status -s → previsione: ???
🔵 Esercizio 2 — Il caso tricky in pratica (Medio)
diario.txt contenente “Giorno 1”. Committa.b) Modifica
diario.txt: aggiungi “Giorno 2”. Fai git add diario.txt.c) Senza committare, modifica di nuovo
diario.txt: aggiungi “Giorno 3”.d) Esegui
git status e git status -s. Spiega cosa vedi.e) Fai
git commit -m "Aggiunto giorno 2". Poi git status -s. Il giorno 3 è nel commit?f) Aggiungi e committa il giorno 3 separatamente.
g) Verifica con
git log --oneline che ci siano 3 commit.
🟠 Esercizio 3 — Unstaging chirurgico (Medio)
buono.txt, cattivo.txt, segreto.txt.b) Aggiungi tutti e 3 con
git add . — oops, non volevi aggiungere segreto.txt!c) Togli solo
segreto.txt dalla staging area con git restore --staged segreto.txt.d) Verifica con
git status -s: buono.txt e cattivo.txt in verde, segreto.txt in rosso.e) Committa solo i due file buoni.
f) Verifica:
segreto.txt è ancora nella cartella? (Sì.) È nel commit? (No — verificalo con git show --stat HEAD.)
🟣 Esercizio 4 — Simulazione progetto reale (Difficile)
Simula un mini-progetto web con commit strutturati:
mini-sito.b) Commit 1: crea
README.md con il titolo del progetto e index.html con una struttura HTML base. Messaggio: “Inizializzato progetto con README e struttura HTML”.c) Commit 2: crea
style.css con stili per body e h1. Messaggio: “Aggiunto foglio di stile base”.d) Commit 3: modifica
index.html per collegare il CSS (<link>) e aggiungi un paragrafo. Messaggio: “Collegato CSS e aggiunto contenuto alla home”.e) Commit 4: modifica
style.css aggiungendo stili per i paragrafi E modifica README.md aggiungendo le istruzioni. Entrambe le modifiche in un unico commit. Messaggio: “Aggiunti stili paragrafo e istruzioni al README”.f) Verifica con
git log --oneline: 4 commit, messaggi chiari, storia leggibile.
❓ 4. Quiz di verifica
1. Un file appare in verde sotto “Changes to be committed”. Se fai git commit adesso, viene salvato?
Mostra risposta
Sì. I file in verde nella sezione “Changes to be committed” sono nella staging area e verranno inclusi nel prossimo commit. I file in rosso (nelle altre due sezioni) non verranno inclusi. Questo è il principio fondamentale: verde = nel commit, rosso = fuori dal commit.
2. Come è possibile che git status -s mostri MM per un file?
Mostra risposta
Succede quando il file è stato modificato, aggiunto alla staging area con git add, e poi modificato di nuovo senza rifarlo git add. La prima M (colonna sinistra, verde) indica che la versione in staging è diversa dall’ultimo commit. La seconda M (colonna destra, rossa) indica che la versione nella working directory è diversa da quella in staging. In pratica, ci sono tre versioni del file: quella dell’ultimo commit, quella in staging e quella nella working directory. Se fai commit adesso, salvi quella in staging — la terza modifica resta fuori.
3. Qual è la differenza tra git restore --staged file e git restore file?
Mostra risposta
git restore --staged file toglie il file dalla staging area e lo riporta allo stato “modified” o “untracked” nella working directory — non cancella nessuna modifica. È un’operazione sicura. git restore file (senza --staged) invece cancella le modifiche nella working directory, ripristinando il file alla versione dell’ultimo commit. È un’operazione distruttiva e irreversibile. La regola: con --staged togli dalla staging, senza --staged butti via le modifiche.
4. Perché esiste la staging area? Non sarebbe più semplice fare commit direttamente dalla working directory?
Mostra risposta
La staging area esiste per darti controllo granulare su cosa finisce in ogni commit. Senza staging, dovresti committare tutte le modifiche insieme — il che produce commit caotici che mescolano funzionalità diverse, fix di bug e esperimenti. Con la staging area puoi: (1) avere 10 file modificati e committarne solo 3, (2) fare commit separati per modifiche logicamente indipendenti, (3) con git add -p, committare anche solo parti di uno stesso file. Il risultato è una storia del progetto pulita, leggibile e utile — ogni commit descrive un’unica modifica logica.
5. Dopo git status -s vedi: M README.md (spazio-M). Cosa significa lo spazio nella prima colonna?
Mostra risposta
Lo spazio nella prima colonna (staging area) significa che non ci sono modifiche in staging per quel file. La M nella seconda colonna (working directory) significa che il file è stato modificato ma non è ancora stato aggiunto alla staging area con git add. Se facessi commit adesso, questo file non sarebbe incluso. Per includerlo, devi prima fare git add README.md — a quel punto il codice diventa M· (M in prima colonna, spazio in seconda).
6. Hai fatto git add . ma ti accorgi di aver incluso un file con password. Il commit non è ancora stato fatto. Come risolvi?
Mostra risposta
Dato che il commit non è stato fatto, il file è solo in staging — basta toglierlo con git restore --staged password.txt. Il file torna a “untracked” e non verrà incluso nel prossimo commit. Poi puoi fare git commit tranquillamente — il file con la password non sarà nel repository. Nella Lezione 15 imparerai a creare un .gitignore per evitare che file sensibili vengano aggiunti per errore anche con git add .. Se invece avessi già fatto il commit, la situazione sarebbe più complessa — la gestiremo nella Lezione 06.
📚 Riepilogo della lezione
- Le tre aree: Working Directory (tavolo da lavoro) → Staging Area (busta da consegnare) → Repository (archivio permanente)
- I 5 stati di un file: untracked · modified · staged · committed · deleted
git statusha 3 sezioni: verde (staging) · rosso tracciati (working) · rosso untracked (nuovi)- Un file può essere MM — staged E modified — se lo modifichi dopo il
git add git restore --staged file— toglie dalla staging senza perdere modifiche (sicuro)git restore file— scarta le modifiche nella working dir (distruttivo!)git add -p— staging chirurgica, blocco per bloccogit status -s— versione compatta: due colonne (staging | working dir)
Prossima lezione →
Lezione 05 — Leggere la storiagit log con tutti i suoi formati e filtri. git diff per confrontare versioni.git show per esplorare un singolo commit.
Corso Git & GitHub · Per studenti e insegnanti · Lezione 04 di 45