Sviluppo

Git essenziale: i comandi che usi davvero

Git non è GitHub. I comandi che usi davvero: clone, commit, branch, merge, pull e push. Più .gitignore, messaggi chiari e i file da non committare mai.

14 min di letturaBaseGuidaDi Riccardo Sciortino
Indice
  1. Introduzione
  2. Perché Git esiste
  3. Annullare
  4. Collaborare
  5. Capire chi ha cambiato cosa
  6. Git non è GitHub (né GitLab)
  7. Il ciclo di lavoro quotidiano
  8. clone
  9. status
  10. add
  11. commit
  12. log
  13. Branch, switch e merge
  14. branch
  15. switch
  16. merge
  17. Quando un ramo ha senso
  18. Quando è rumore
  19. pull e push
  20. pull
  21. push
  22. .gitignore
  23. Un buon messaggio di commit
  24. Cosa non committare mai
  25. Force push: il comando che fa danni
  26. Autenticazione verso il remote
  27. Problemi comuni
  28. "origin does not appear to be a git repository"
  29. "Your branch is behind"
  30. "Please tell me who you are"
  31. Ho committato sul ramo sbagliato
  32. Il merge è un disastro
  33. Conclusione

Introduzione

Git serve a tre cose: tornare indietro, lavorare in più persone, capire chi ha cambiato cosa. Il resto è rumore.

Non ti serve la storia di Linus Torvalds. Non ti serve memorizzare cinquanta comandi. Ti serve un ciclo di lavoro che non ti faccia perdere codice, e la disciplina di non pubblicare segreti.

In questa guida trovi solo quello che usi davvero:

  • perché Git esiste (annullare, collaborare, blame)
  • clone, status, add, commit, log
  • branch, switch, merge
  • pull e push
  • .gitignore
  • come si scrive un commit decente
  • cosa non finisce mai in un repository
  • perché push --force è un'arma, non una scorciatoia

Git è il programma sul tuo PC. GitHub e GitLab sono siti che ospitano una copia remota. Confonderli è il primo errore, e costa tempo.

Perché Git esiste

Senza versionamento, il lavoro vive in una cartella. Sovrascrivi un file. Il collega ha un'altra copia. Dopo due settimane nessuno sa quale sia quella giusta.

Git tiene la storia. Ogni commit è uno snapshot. Puoi confrontare, tornare indietro, isolare un esperimento su un ramo. Non è magia. È un diario del codice, con data e autore.

Annullare

Hai rotto qualcosa. Non è la fine. Se hai committato prima della modifica, puoi vedere il diff e ripristinare. Se non hai committato, status e restore ti dicono cosa è ancora recuperabile.

Senza commit, Git non ha memoria. Salvare il file non basta. Devi registrare lo stato.

Collaborare

Due persone sullo stesso progetto senza Git si passano zip e "versione_finale_2_davvero". Con Git ognuno lavora sul proprio clone. I rami tengono gli esperimenti separati. Il merge unisce. I conflitti si vedono, non si nascondono in una copia "quasi uguale".

Capire chi ha cambiato cosa

git blame (e la vista History su GitHub/GitLab) mostra chi ha toccato una riga e in quale commit. Non è un processo. È un modo per chiedere alla persona giusta, o per capire perché quella riga esiste.

Git non ti protegge se non committi. Il diario si scrive. Altrimenti resta una cartella come le altre.

Git non è GitHub (né GitLab)

Usi Git in locale anche senza account. init, add, commit, log funzionano su un disco, da soli.

GitHub, GitLab, Gitea, Bitbucket sono remote: un altro computer che tiene una copia del repository. Servono a condividere, fare backup fuori dal portatile, aprire merge request, gestire issue.

Il flusso è questo:

  1. lavori in locale
  2. committi in locale
  3. push verso il remote
  4. gli altri pull da quel remote

Se il remote sparisce e hai solo il laptop, hai ancora la storia. Se il laptop muore e non hai mai fatto push, la storia muore con lui.

CosaCos'èCosa non è
GitProgramma di versionamento, sul tuo PCUn sito, un account, un'azienda
Repository (repo)Cartella con la storia (directory .git)"Il progetto su GitHub" in sé
RemoteCopia su un altro host (origin)Git
GitHub / GitLabHosting + interfaccia + permessiIl versionamento
CommitSnapshot registrato, con messaggioSalvare il file
BranchLinea di storia parallelaUna cartella duplicata a mano

"L'ho caricato su GitHub" non è un backup se il repo è solo lì e nessuno ha un clone aggiornato. E "l'ho committato" non significa che sia sul remote: serve push.

Il ciclo di lavoro quotidiano

Apri il terminale nella cartella del progetto. Quasi tutto passa da cinque comandi.

clone

Prendi una copia completa del repository, storia inclusa.

git clone [email protected]:esempio/progetto.git
cd progetto

L'URL SSH (git@…) è quello che userai se hai chiavi SSH. L'URL HTTPS chiede token o password. Per il lavoro di tutti i giorni, SSH è meno fastidioso.

clone crea la cartella, scarica i commit, imposta origin come remote. Non cloni ogni mattina. Cloni una volta. Poi pull.

Se il progetto è già sul disco e ha la cartella .git, sei già dentro un repo. Non cloni di nuovo sopra. Entri e lavori.

status

È il comando che usi di più. Mostra tre cose: file modificati, file in staging, file non tracciati.

git status

Prima di add e commit, lanci status. Dopo un merge, lanci status. Se qualcosa "non torna", lanci status. Costa un secondo. Evita commit accidentalmente vuoti o pieni di file sbagliati.

add

Sposti le modifiche nell'area di staging: quello che entrerà nel prossimo commit.

git add file.txt
git add src/
git add -p

add su un singolo file è preciso. add src/ è comodo se quella cartella è il pezzo che stai chiudendo. add -p (patch) ti fa scegliere i pezzi: utile quando hai mescolato due lavori nello stesso file.

# Evitalo come abitudine
git add .

git add . prende tutto quello che è in cartella, tranne ciò che è in .gitignore. Se il ignore è fatto male, ci finiscono dump, build, .env. Su un repo piccolo e pulito può bastare. Su un repo vero, è pigro.

Staging esiste per un motivo: un commit deve contenere una cosa sola. Non "tutto quello che era sporco sul disco".

commit

Registra lo snapshot. Messaggio obbligatorio. Senza messaggio Git si rifiuta, o apre l'editor.

git commit -m "Fix timeout sul login se il provider OIDC non risponde"

-m va bene per una riga. Se ti serve il corpo (perché, come testare, cosa non hai toccato), usa git commit senza -m e scrivi nell'editor.

git commit -am "…" fa add+commit solo sui file già tracciati. I file nuovi restano fuori. Non è un sostituto di status.

log

Leggi la storia.

git log --oneline -20
git log --oneline --graph --decorate -20

--oneline è quello che serve al 90%. Hash corto, titolo del commit. Se il titolo è "fix" o "update", il log è inutile. Torneremo sui messaggi.

Per un file:

git log --oneline -- percorso/del/file

Branch, switch e merge

Il ramo main (a volte master) è la linea che consideri stabile. I rami di lavoro servono a non mischiare un esperimento con il codice che già gira.

branch

git branch
git branch feature/export-csv

Senza argomenti, elenca. Con un nome, crea. Creare non ti sposta: resti dove eri.

Un nome di ramo deve dire cosa stai facendo. feature/export-csv si capisce. pippo e nuovo no. Tra sei mesi il ramo è ancora lì, e nessuno sa se si può cancellare.

switch

git switch feature/export-csv
git switch -c feature/export-csv

switch ti sposta. -c crea e sposta in un colpo. checkout fa le stesse cose, ma fa anche altro: è più facile sbagliarlo. Per cambiare ramo, usa switch.

Git ti blocca lo switch se hai modifiche che andrebbero in conflitto sul ramo di destinazione. Non forzare. Committa, oppure stash se sai cos'è. Se non lo sai, committa su un ramo temporaneo.

merge

Riporti un ramo dentro un altro. Di solito: sei su main, unisci il ramo di lavoro.

git switch main
git pull
git merge feature/export-csv

Se Git può unire da solo, lo fa (fast-forward o merge commit). Se due commit hanno toccato le stesse righe in modo diverso, hai un conflitto. I file segnati vanno aperti, puliti, poi:

git add file-risolto.ts
git status
git commit

Il commit di merge chiude l'unione. Non lasciare marker di conflitto nel codice. status deve tornare pulito.

Quando un ramo ha senso

  • Una feature che non è pronta
  • Un fix isolato da non mischiare
  • Un esperimento che potresti buttare

Quando è rumore

  • Un commit sul main di un repo solo tuo
  • Dieci rami aperti e nessuno sa quali sono vivi
  • Merge a catena senza pull prima

pull e push

Qui entra il remote. Di solito si chiama origin.

pull

Scarichi i commit che gli altri (o tu, da un altro PC) hanno già mandato sul remote, e li integri nel ramo corrente.

git pull

pull è fetch + merge (o rebase, se l'hai configurato così). Prima di iniziare a lavorare, pull. Prima di un merge su main, pull. Prima di un push, se lavori in due sullo stesso ramo, pull.

Se pull fallisce per conflitti, è lo stesso lavoro del merge: apri i file, sistema, add, commit.

push

Mandi i tuoi commit sul remote.

git push
git push -u origin feature/export-csv

-u (upstream) la usi la prima volta su un ramo nuovo. Dopo, git push basta.

Push non è "salva su internet". Push pubblica la storia che hai committato. Se nel commit c'è un .env, sul remote c'è un .env. Toglierlo dal commit successivo non lo toglie dalla storia.

Locale e remote divergono. status dopo pull e push ti dice se sei avanti, indietro, o in conflitto. Non indovinare.

.gitignore

File di testo nella radice del repo. Ogni riga è un pattern da non tracciare.

node_modules/
.env
.env.*
!.env.example
dist/
*.log
.DS_Store

.env.example (chiavi vuote o fittizie) può stare nel repo. Il .env vero no.

gitignore non toglie un file già committato. Se node_modules è nella storia, aggiungerlo al ignore ferma solo i commit nuovi. Per toglierlo dalla storia serve un lavoro a parte, e se il repo è già condiviso è doloroso. Meglio non committarlo la prima volta.

git status --ignored

Ti mostra cosa Git sta ignorando. Utile quando "manca un file" e in realtà è nel ignore.

Cosa finisce quasi sempre in .gitignore

  • Dipendenze installate (node_modules, vendor)

  • Build e cache (dist, .next, pycache)

  • Segreti e ambiente (.env, chiavi, certificati)

  • Log, dump, backup locali
  • File del sistema (.DS_Store, Thumbs.db)

Un buon messaggio di commit

Il log è documentazione. Se i titoli sono "fix", "wip", "aaaa", tra un mese non sai cosa è successo. blame diventa un elenco di rumore.

Una riga, all'imperativo, che dice cosa cambia e perché conta:

Limita a 3 i tentativi di login prima del lockout

Il form ritentava in loop sul 401 e bloccava l'account IdP.

La prima riga sta sotto i 72 caratteri. Il corpo (se serve) spiega il motivo, non ripete il diff. Il diff si vede già con git show.

DeboleMeglio
fixCorregge il timeout del webhook Stripe
updateAggiorna Next a 16.2 per il fix del middleware
variodue commit, uno per tema
modifiche varie e file envnon committare l'env; spezza il resto

Non serve Conventional Commits se siete in due e vi capite. Serve se il team è più grande o se i changelog li genera una macchina. In ogni caso: un commit, un argomento.

"WIP" sul tuo ramo, prima di pranzo, succede. Prima di un merge su main, riscrivi o fai squash. Il main si legge.

Cosa non committare mai

.env, file .pem, token, dump del database, backup, chiavi SSH private. Se un file permette di entrare da qualche parte, non sta nel repo.

# Controlla cosa stai per committare
git status
git diff --cached

--cached è il diff dello staging. Leggilo. Se vedi AWS_SECRET o DATABASE_URL=postgres://…, togli il file, aggiungilo al .gitignore, ricomincia il commit.

Un segreto committato e pushato è un segreto bruciato. Toglierlo dal commit successivo non basta: resta nella storia. Ruota la chiave, il token, la password. Poi, se serve, pulisci la storia. In quest'ordine.

Lo stesso vale per dati personali (export clienti, fogli paga, dump). Un repo privato su GitHub non è un caveau. Ha permessi, ha collaboratori, ha fork, ha CI che a volte stampa i log.

Force push: il comando che fa danni

git push --force
git push --force-with-lease

Riscrive la storia sul remote. I commit che c'erano possono sparire dalla punta del ramo. Chi aveva già fatto pull si trova un albero che non coincide più.

Lo usi solo sul tuo ramo, se sei solo, e sai perché (rebase, correzione di un commit appena fatto, non ancora usato da altri). Non lo usi su main. Non lo usi "perché pull dà conflitto". Il conflitto si risolve. Non si cancella.

--force-with-lease è meno cieco: rifiuta se sul remote c'è un commit che non hai. È il minimo, se proprio devi.

push --force su un ramo condiviso è il modo più veloce per far sparire il lavoro di qualcun altro. Se non sai spiegare perché ti serve, non lo lanciare.

Autenticazione verso il remote

HTTPS con password dell'account, su GitHub, non funziona più da anni. Serve un personal access token, oppure SSH.

SSH è il percorso pulito: una chiave sul PC, la pubblica sull'account, [email protected]:… come URL. Come si genera e si carica è in chiavi SSH.

# Verifica che Git veda il remote
git remote -v

Se origin è HTTPS e ogni push chiede credenziali, cambia URL:

git remote set-url origin [email protected]:esempio/progetto.git

Poi un git fetch di prova. Se chiede la passphrase della chiave, è il comportamento atteso. Se chiede la password di GitHub, l'URL o la chiave non sono a posto.

Problemi comuni

"origin does not appear to be a git repository"

Non c'è un remote, o l'URL è sbagliato. git remote -v. Se è vuoto, aggiungi origin. Se l'URL è copiato male (https su SSH, typo nell'org), correggilo con set-url.

"Your branch is behind"

Qualcun altro ha fatto push. git pull. Poi lavori. Poi push. Non force.

"Please tell me who you are"

Git non ha nome e email su quella macchina. Servono per il commit, restano nella storia.

git config --global user.name "Nome Cognome"
git config --global user.email "[email protected]"

Usa l'email che vuoi vedere nei commit. Su GitHub, quella associata all'account (o la noreply che ti dà il sito).

Ho committato sul ramo sbagliato

Se il commit è solo locale e l'ultimo:

git switch ramo-giusto
git cherry-pick HASH
git switch ramo-sbagliato
git reset --hard HEAD~1

reset --hard butta le modifiche non committate su quel ramo. Usalo solo se status è pulito e l'hash è quello giusto. Se il commit è già sul remote, non resettare: è un altro discorso, e spesso serve una mano.

Il merge è un disastro

git merge --abort

Torni allo stato prima del merge. Poi decidi: unisci di nuovo con calma, oppure chiedi a chi ha scritto l'altro ramo.

Quasi tutti i "Git è rotto" sono: ramo sbagliato, pull mancante, o file committati per sbaglio. Controlla status, log e remote. In quest'ordine.

Conclusione

Git è piccolo, se lo usi per quello che è. Cloni una volta. Guardi status. Aggiungi quello che deve stare nel commit. Scrivi un messaggio che tra un mese ha senso. Unisci i rami con merge. Aggiorni con pull, pubblichi con push. Ignori build e segreti. Non fai force push sul ramo degli altri.

GitHub e GitLab restano il posto dove sta origin. Non sono Git. Se l'autenticazione è una lotta, sistema le chiavi SSH e torna a lavorare. Come usiamo Git nei progetti è in tecnologie / Git; se serve un repository e un flusso di rilascio sul software aziendale, si parte da sviluppo software.


Risorse utili (autorevoli):

Parliamone

Questo articolo riguarda la tua azienda?

Se uno dei problemi descritti riguarda anche i tuoi sistemi, possiamo valutare insieme la situazione. Il primo confronto è gratuito.