Qual è la differenza tra un Git SHA-1 e un commit?
Jon Seymour ha dato la maggior parte della risposta che avrei dato io. Ho solo alcune cose da aggiungere.
Jon parla di SHA-1 come un "nome" per un oggetto. Io preferisco considerarlo per denotare "l'identità" dell'oggetto.
La ragione per cui questa piccola distinzione è importante, è che permette di identificare in modo univoco uno specifico commit (o albero, blob, o tag(), non importa quali cambiamenti possono essere fatti al repo. I tag potrebbero essere spostati (sostituiti), i rami aggiunti, il rebasing potrebbe sostituire un commit con un commit completamente diverso, che qualcuno potrebbe poi forzare nel repo, rimescolando le cose per tutti - e quello SHA-1 si riferirebbe ancora a quello stesso commit.
Un commit è in realtà un oggetto molto semplice. Puoi anche costruirlo manualmente. Ha le informazioni su committer e autore e le date. Ha il messaggio di commit. Ha l'SHA-1 di uno o più genitori. E ha lo SHA-1 dell'albero.
Anche un albero è un oggetto semplice, fondamentalmente costituito da una lista di blob (file o link) per nome, o sottoalberi (directory). E un hack speciale per i sottomoduli.
Se cambi una qualsiasi di queste informazioni, lo SHA-1 cambia - diventa un nuovo oggetto.
Se cambi il contenuto dell'albero - qualsiasi file (blob), qualsiasi directory (anche un albero), lo SHA-1 dell'albero cambierà.
Se cambi uno di questi per qualsiasi commit genitore, lo SHA-1 cambia. Che poi cambia questo commit. All'infinito.
Quindi non solo l'SHA-1 di un commit denota un particolare contenuto dell'albero - denota un'intera storia di come l'albero è arrivato lì.
Conoscere l'SHA-1 di un commit ti permette di recuperare da ogni tipo di casino. Ho usato le informazioni per recuperare dopo cattivi force-push, e per riparare repository corrotti (da accidentali cancellazioni parziali), ricostruendoli con commit e altri oggetti da altri repository.
Ma conoscere lo SHA-1 di un commit ti dice anche che l'albero e l'intera storia non sono stati manomessi. Potrei darvi l'SHA-1 di un commit, spingere il mio repo da qualche parte senza fiducia, lasciare che facciano tutte le modifiche che vogliono, e voi sapreste comunque che il commit che vi ho dato non è cambiato.
Possono *danneggiarlo*, rimuovendo oggetti, ma non possono cambiarlo.
Questa è una forte garanzia di sicurezza!
Non importa quanti attori non fidati siano coinvolti in un progetto, quando qualcuno vi dà una richiesta di pull, potete essere certi che il suo commit non è costruito su qualche storia alternativa. A meno che, naturalmente, non lo sia, cosa che sarà presto ovvia, perché il merging fallirà.
Quindi questo è il motivo per cui lo vedo più di un semplice nome per un commit, ma più fortemente legato all'identità stessa di un commit.
Nota: Ho sorvolato qui, la possibilità molto molto remota di una collisione di hash con SHA-1. SHA-1 non è sicuro come i più moderni SHA-256 o SHA-512, ma è ancora dell'ordine di 1/2^69 per un malintenzionato che usa le debolezze di SHA-1, o 1/2^80 senza, assumendo una distribuzione uguale. È difficile immaginare quanto sia grande 2^69.
Se costruissimo una catena di carbonio molto lunga, tra qui e alfa centauri, e usassimo SHA-1 per selezionare un atomo di carbonio in questo cambiamento, allora 2^69 secchi sarebbero distanti meno di 0,1 mm, ma gli interi 2^80 diversi hash SHA-1 sarebbero distanti circa 275 atomi.
Per tutti gli scopi pratici, possiamo ignorare la possibilità che due oggetti diversi abbiano lo stesso SHA-1.