Tôi đã làm một thí nghiệm để tìm hiểu chính xác Git sẽ hành xử như thế nào trong trường hợp này. Đây là phiên bản 2.7.9 ~ rc0 + next.20151210 (phiên bản Debian). Về cơ bản, tôi chỉ giảm kích thước băm từ 160 bit xuống 4 bit bằng cách áp dụng git diff và xây dựng lại sau:
--- 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);
}
Sau đó, tôi đã làm một vài cam kết và nhận thấy những điều sau đây.
- Nếu một blob đã tồn tại với cùng một hàm băm, bạn sẽ không nhận được bất kỳ cảnh báo nào cả. Mọi thứ dường như đều ổn, nhưng khi bạn đẩy, ai đó nhân bản hoặc bạn hoàn nguyên, bạn sẽ mất phiên bản mới nhất (phù hợp với những gì được giải thích ở trên).
- Nếu một đối tượng cây đã tồn tại và bạn tạo một đốm màu với cùng hàm băm: Mọi thứ sẽ có vẻ bình thường, cho đến khi bạn cố gắng đẩy hoặc ai đó nhân bản kho lưu trữ của bạn. Sau đó, bạn sẽ thấy rằng repo bị hỏng.
- Nếu một đối tượng cam kết đã tồn tại và bạn tạo một blob có cùng hàm băm: giống như # 2 - bị hỏng
- Nếu một blob đã tồn tại và bạn tạo một đối tượng cam kết có cùng hàm băm, nó sẽ thất bại khi cập nhật "ref".
- Nếu một blob đã tồn tại và bạn tạo một đối tượng cây có cùng hàm băm. Nó sẽ thất bại khi tạo cam kết.
- Nếu một đối tượng cây đã tồn tại và bạn tạo một đối tượng cam kết có cùng hàm băm, nó sẽ thất bại khi cập nhật "ref".
- Nếu một đối tượng cây đã tồn tại và bạn tạo một đối tượng cây có cùng hàm băm, mọi thứ sẽ có vẻ ổn. Nhưng khi bạn cam kết, tất cả các kho lưu trữ sẽ tham chiếu cây sai.
- Nếu một đối tượng cam kết đã tồn tại và bạn tạo một đối tượng cam kết có cùng hàm băm, mọi thứ sẽ có vẻ ổn. Nhưng khi bạn cam kết, cam kết sẽ không bao giờ được tạo và con trỏ CHÍNH sẽ được chuyển sang một cam kết cũ.
- Nếu một đối tượng cam kết đã tồn tại và bạn tạo một đối tượng cây có cùng hàm băm, nó sẽ thất bại khi tạo cam kết.
Đối với # 2, thông thường bạn sẽ gặp lỗi như thế này khi chạy "git đẩy":
error: object 0400000000000000000000000000000000000000 is a tree, not a blob
fatal: bad blob object
error: failed to push some refs to origin
hoặc là:
error: unable to read sha1 file of file.txt (0400000000000000000000000000000000000000)
nếu bạn xóa tệp và sau đó chạy "git checkout file.txt".
Đối với # 4 và # 6, thông thường bạn sẽ gặp một lỗi như thế này:
error: Trying to write non-commit object
f000000000000000000000000000000000000000 to branch refs/heads/master
fatal: cannot update HEAD ref
khi chạy "git commit". Trong trường hợp này, bạn thường có thể chỉ cần gõ lại "git commit" vì điều này sẽ tạo ra một hàm băm mới (vì dấu thời gian đã thay đổi)
Đối với # 5 và # 9, thông thường bạn sẽ gặp một lỗi như thế này:
fatal: 1000000000000000000000000000000000000000 is not a valid 'tree' object
khi chạy "git commit"
Nếu ai đó cố gắng sao chép kho lưu trữ bị hỏng của bạn, họ thường sẽ thấy một cái gì đó như:
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'
Điều "lo lắng" với tôi là trong hai trường hợp (2,3) kho lưu trữ bị hỏng mà không có bất kỳ cảnh báo nào và trong 3 trường hợp (1,7,8), mọi thứ có vẻ ổn, nhưng nội dung kho lưu trữ khác với những gì bạn mong đợi được. Mọi người nhân bản hoặc kéo sẽ có một nội dung khác với những gì bạn có. Các trường hợp 4,5,6 và 9 đều ổn, vì nó sẽ dừng với một lỗi. Tôi cho rằng sẽ tốt hơn nếu nó thất bại với một lỗi ít nhất là trong mọi trường hợp.