Я провел эксперимент, чтобы выяснить, как именно Git будет вести себя в этом случае. Это с версией 2.7.9 ~ rc0 + next.20151210 (версия Debian). Я просто уменьшил размер хеша со 160-битного до 4-битного, применив следующий diff и перестроив 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);
}
Затем я сделал несколько коммитов и заметил следующее.
- Если BLOB-объект с таким же хешем уже существует, вы вообще не получите никаких предупреждений. Кажется, все в порядке, но когда вы нажимаете, кто-то клонирует, или вы возвращаетесь, вы потеряете последнюю версию (в соответствии с тем, что описано выше).
- Если объект дерева уже существует, и вы создаете BLOB-объект с таким же хешем: все будет казаться нормальным, пока вы не попробуете протолкнуть или кто-то клонирует ваш репозиторий. Тогда вы увидите, что репо повреждено.
- Если объект фиксации уже существует, и вы создаете BLOB-объект с таким же хешем: то же самое, что и # 2 - поврежден
- Если BLOB-объект уже существует, и вы создаете объект коммита с таким же хешем, он потерпит неудачу при обновлении «ref».
- Если BLOB-объект уже существует, и вы создаете объект дерева с таким же хешем. Это не удастся при создании коммита.
- Если объект дерева уже существует, и вы делаете объект фиксации с тем же хешем, то произойдет сбой при обновлении «ref».
- Если объект дерева уже существует и вы создаете объект дерева с таким же хешем, все будет хорошо. Но когда вы фиксируете, все хранилище будет ссылаться на неправильное дерево.
- Если объект фиксации уже существует, и вы делаете объект фиксации с тем же хешем, все будет хорошо. Но когда вы делаете коммит, коммит никогда не будет создан, а указатель HEAD будет перемещен в старый коммит.
- Если объект фиксации уже существует, и вы создаете объект дерева с таким же хешем, он завершится неудачно при создании фиксации.
Для # 2 вы, как правило, получаете ошибку, подобную этой, когда вы запускаете "git push":
error: object 0400000000000000000000000000000000000000 is a tree, not a blob
fatal: bad blob object
error: failed to push some refs to origin
или:
error: unable to read sha1 file of file.txt (0400000000000000000000000000000000000000)
если вы удалите файл, а затем запустите "git checkout file.txt".
Для № 4 и № 6 вы, как правило, получите ошибку, подобную этой:
error: Trying to write non-commit object
f000000000000000000000000000000000000000 to branch refs/heads/master
fatal: cannot update HEAD ref
при запуске "git commit". В этом случае вы можете просто снова набрать «git commit», так как это создаст новый хеш (из-за измененной метки времени)
Для № 5 и № 9 вы обычно получаете сообщение об ошибке, подобное этому:
fatal: 1000000000000000000000000000000000000000 is not a valid 'tree' object
при запуске "git commit"
Если кто-то попытается клонировать ваш поврежденный репозиторий, он обычно увидит что-то вроде:
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'
Меня «беспокоит» то, что в двух случаях (2,3) хранилище становится поврежденным без каких-либо предупреждений, а в 3 случаях (1,7,8) все выглядит нормально, но содержимое хранилища отличается от того, что вы ожидаете быть. У людей, клонирующих или тянущих, будет другое содержание, чем у вас. Случаи 4,5,6 и 9 в порядке, так как остановится с ошибкой. Я полагаю, было бы лучше, если бы это не удалось с ошибкой, по крайней мере, во всех случаях.