Perché git usa gli hash invece dei numeri di revisione?


80

Mi sono sempre chiesto perché Git preferisca gli hash rispetto ai numeri di revisione. I numeri di revisione sono molto più chiari e più facili da consultare (secondo me): c'è una differenza tra dire a qualcuno di dare un'occhiata alla revisione 1200 o commettere 92ba93e! (Solo per fare un esempio).

Quindi, c'è qualche motivo per questo design?


3
È possibile contrassegnare un commit con "v1.0" e quindi fare riferimento al commit da quel tag. Vedi git-scm.com/book/en/v2/Git-Basics-Tagging
Michael Durrant

Risposte:


114

Un singolo numero di revisione monotonicamente crescente ha davvero senso solo per un sistema di controllo versione centralizzato, in cui tutte le revisioni scorrono in un unico posto in grado di tracciare e assegnare numeri. Una volta che entri nel mondo DVCS, dove esistono numerose copie del repository e le modifiche vengono estratte e inviate ad esse in flussi di lavoro arbitrari, il concetto non si applica. (Ad esempio, non esiste un posto dove assegnare i numeri di revisione: se forzo il repository e decidi un anno dopo di eseguire le modifiche, come potrebbe un sistema garantire che i nostri numeri di revisione non siano in conflitto?)


11
Potresti voler guardare al modo di Bazaar - un DVCS che mantiene ancora i numeri di revisione. L'unica garanzia è che i numeri di revisione sono univoci all'interno di un ramo.
krlmlr

3
@krlmlr Person 1: "Hey, <P2>, what was revision 12345 for?" P2: "Revision 12345 was commited by <P3>." P3: "I don't have a revision 12345..."- Se ricordo bene, Mercurial ha un problema simile. D'altra parte, se usassero git, avrebbero tutti riferimenti identici per ogni commit.
Izkata,

1
@Izkata: P1: "Do you have revision with the GUID gdlmsnblngoijlafd-35345-fg?"... Bazaar ha ancora GUID ...
krlmlr

5
@Izkata Mercurial non ha un problema simile. Usano gli hash, proprio come git. Forniscono inoltre un numero di giri solo locale per facilitare la digitazione.
Hank Gay,

1
con git, i primi 5 caratteri dell'hash sono spesso abbastanza unici da usare una scorciatoia per l'ID di revisione completo.
mendota,

40

Hai bisogno di hash in un sistema distribuito. Supponiamo che tu e un collega stiate entrambi lavorando sullo stesso repository ed entrambi commettiate una modifica a livello locale e quindi inviate. Chi può essere il numero di revisione 1200 e chi è il numero di revisione 1201 dato che nessuna delle parti ha alcuna conoscenza reciproca? L'unica soluzione tecnica realistica è quella di creare un hash delle modifiche utilizzando un metodo noto e collegare le cose in base a quello.

È interessante notare che HG supporta i numeri di versione, ma sono esplicitamente una funzione solo locale: il repository ha un set, il repository del tuo collaboratore avrà un set diverso a seconda di come hanno spinto e tirato. Rende però l'utilizzo della riga di comando un po 'più amichevole di Git.


34

Integrità dei dati.

Non sono rispettosamente d'accordo con le risposte attuali. Gli hash non sono necessari per un DVCS, vedi la via del Bazar . Puoi fare altrettanto con qualsiasi altro tipo di identificatore univoco globale. Gli hash sono una misura per garantire l'integrità dei dati: rappresentano un digest delle informazioni contenute nell'oggetto (commit, alberi, ...) a cui fa riferimento l'hash. Modificare i contenuti senza alterare l'hash (ovvero un attacco preimage o un attacco di collisione ) è ritenuto difficile, sebbene non impossibile. (Se ti piace davvero, dai un'occhiata al documento del 2011 di Marc Stevens ).

Quindi, fare riferimento agli oggetti con il loro hash SHA consente di verificare se il contenuto è stato manomesso. E, dato che sono (quasi) garantiti per essere univoci, possono anche essere usati come identificatori di revisione - convenientemente.

Vedi il capitolo 9 del libro Git per maggiori dettagli.


8
Non è una misura di sicurezza, poiché l'hash può essere facilmente ricalcolato per un commit modificato. Viene utilizzato solo per integrità, per verificare i contenuti rispetto all'hash calcolato - vedere questo commento di Linus Torvalds sull'uso di SHA-1 in Git.
Lee,

@Lee: se il repository di Chuck è diverso da quello che Alice e Bob hanno in termini di hash di revisione, è garantito che anche Chuck abbia contenuti diversi. D'altra parte, è molto difficile per Chuck fabbricare un repository con contenuti diversi che sembrano identici nei loro hash di revisione.
krlmlr

@Lee: perso il tuo link. Chiamiamolo "integrità dei dati" quindi ...
krlmlr

dovrebbe essere la risposta corretta
SuperUberDuper,

8

Nelle parole di laici:

  • Gli hash sono destinati a essere quasi universalmente unici. NON è garantito ma è estremamente improbabile che vengano generati gli stessi SHA per contenuti diversi. In termini pratici per un determinato progetto puoi trattarlo come unico.
  • Con i numeri di revisione dovresti usare uno spazio dei nomi per fare riferimento in modo specifico alla revisione 1200.
  • Git può funzionare sia distribuito che / o centralizzato. Quindi, come si ottengono i numeri di revisione corretti e unici?
  • Anche l'uso dei numeri di revisione creerebbe la falsa osservazione che le revisioni più recenti dovrebbero avere numeri più alti e ciò non sarebbe vero a causa di diramazioni, fusioni, ribassature, ecc.
  • Hai sempre la possibilità di mettere tag per i commit.

32
Non è garantito per essere unico, ma è incredibilmente probabile che sia unico. :)
dsw88,

@ mustang2009cobra È vero.
Tulains Córdova,

1
È possibile che il mio cambiamento non sia accettato perché l'hash è invariato. È molto più probabile che due meteore colpiscano il mio computer e il computer con il repository nello stesso secondo, distruggendo i computer e uccidendo tutti i soggetti coinvolti.
gnasher729,


1

Hash non è la soluzione unica per VCS distribuito. Ma quando si tratta di un sistema distribuito, è possibile registrare solo l'ordinamento parziale degli eventi. (Per VCS, l'evento può essere un commit.) Ecco perché è impossibile mantenere un numero di revisione monotonicamente crescente. Di solito adottiamo qualcosa come l' orologio vettoriale (o il timestamp vettoriale) per registrare tale relazione ordinata parzialmente. Questa è la soluzione utilizzata in Bazaar .

Ma perché Git non usa l'orologio vettoriale ma l'hash? Penso che la causa principale sia la scelta della ciliegia . Quando eseguiamo cherry-pick su un repository, l'ordinamento parziale dei commit sta cambiando. Alcuni orologi vettoriali di commit devono essere riassegnati per rappresentare il nuovo ordinamento parziale. Tuttavia, tale riassegnazione nel sistema distribuito indurrebbe orologi vettoriali incoerenti. Questo è il vero problema che gli hash affrontano.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.