Ho fatto un esperimento per scoprire esattamente come si sarebbe comportato Git in questo caso. Questo è con la versione 2.7.9 ~ rc0 + next.20151210 (versione Debian). Fondamentalmente ho appena ridotto la dimensione dell'hash da 160-bit a 4-bit applicando il seguente diff e ricostruendo git:
--- git-2.7.0~rc0+next.20151210.orig/block-sha1/sha1.c
+++ git-2.7.0~rc0+next.20151210/block-sha1/sha1.c
@@ -246,6 +246,8 @@ void blk_SHA1_Final(unsigned char hashou
blk_SHA1_Update(ctx, padlen, 8);
/* Output hash */
- for (i = 0; i < 5; i++)
- put_be32(hashout + i * 4, ctx->H[i]);
+ for (i = 0; i < 1; i++)
+ put_be32(hashout + i * 4, (ctx->H[i] & 0xf000000));
+ for (i = 1; i < 5; i++)
+ put_be32(hashout + i * 4, 0);
}
Poi ho fatto alcuni commit e ho notato quanto segue.
- Se esiste già un BLOB con lo stesso hash, non riceverai alcun avviso. Tutto sembra andare bene, ma quando spingi, qualcuno clona o ritorni, perderai l'ultima versione (in linea con quanto spiegato sopra).
- Se esiste già un oggetto albero e si crea un BLOB con lo stesso hash: tutto sembrerà normale, finché non si tenta di spingere o qualcuno clona il proprio repository. Quindi vedrai che il repository è danneggiato.
- Se esiste già un oggetto commit e si crea un BLOB con lo stesso hash: uguale a # 2 - danneggiato
- Se esiste già un BLOB e si crea un oggetto commit con lo stesso hash, fallirà durante l'aggiornamento di "ref".
- Se esiste già un BLOB e si crea un oggetto albero con lo stesso hash. Non funzionerà durante la creazione del commit.
- Se esiste già un oggetto ad albero e si crea un oggetto commit con lo stesso hash, fallirà durante l'aggiornamento di "ref".
- Se esiste già un oggetto albero e si crea un oggetto albero con lo stesso hash, tutto sembrerà ok. Ma quando commetti, tutto il repository farà riferimento all'albero sbagliato.
- Se esiste già un oggetto commit e si crea un oggetto commit con lo stesso hash, tutto sembrerà ok. Ma quando esegui il commit, il commit non verrà mai creato e il puntatore HEAD verrà spostato su un vecchio commit.
- Se esiste già un oggetto commit e si crea un oggetto albero con lo stesso hash, fallirà durante la creazione del commit.
Per # 2 in genere si verifica un errore del genere quando si esegue "git push":
error: object 0400000000000000000000000000000000000000 is a tree, not a blob
fatal: bad blob object
error: failed to push some refs to origin
o:
error: unable to read sha1 file of file.txt (0400000000000000000000000000000000000000)
se si elimina il file e si esegue "git checkout file.txt".
Per # 4 e # 6, in genere si verifica un errore come questo:
error: Trying to write non-commit object
f000000000000000000000000000000000000000 to branch refs/heads/master
fatal: cannot update HEAD ref
quando si esegue "git commit". In questo caso, in genere puoi semplicemente digitare nuovamente "git commit" poiché ciò creerà un nuovo hash (a causa del timestamp modificato)
Per # 5 e # 9, in genere viene visualizzato un errore come questo:
fatal: 1000000000000000000000000000000000000000 is not a valid 'tree' object
quando si esegue "git commit"
Se qualcuno prova a clonare il tuo repository corrotto, in genere vedrà qualcosa del tipo:
git clone (one repo with collided blob,
d000000000000000000000000000000000000000 is commit,
f000000000000000000000000000000000000000 is tree)
Cloning into 'clonedversion'...
done.
error: unable to read sha1 file of s (d000000000000000000000000000000000000000)
error: unable to read sha1 file of tullebukk
(f000000000000000000000000000000000000000)
fatal: unable to checkout working tree
warning: Clone succeeded, but checkout failed.
You can inspect what was checked out with 'git status'
and retry the checkout with 'git checkout -f HEAD'
Ciò che "mi preoccupa" è che in due casi (2,3) il repository si corrompe senza alcun preavviso e in 3 casi (1,7,8), tutto sembra ok, ma il contenuto del repository è diverso da quello che ti aspetti essere. Le persone che clonano o tirano avranno un contenuto diverso da quello che hai. I casi 4,5,6 e 9 sono ok, poiché si fermerà con un errore. Suppongo che sarebbe meglio se fallisse con un errore almeno in tutti i casi.