Bao nhiêu git sha là * nói chung * được coi là cần thiết để xác định duy nhất một thay đổi trong một cơ sở mã nhất định?


211

Nếu bạn định xây dựng, giả sử, một cấu trúc thư mục trong đó một thư mục được đặt tên cho một cam kết trong kho Git và bạn muốn nó đủ ngắn để khiến mắt bạn không bị chảy máu, nhưng đủ lâu để cơ hội của nó va chạm sẽ không đáng kể, bao nhiêu chuỗi con SHA thường được yêu cầu?

Giả sử tôi muốn xác định duy nhất thay đổi này: https://github.com/wycats/handlebars.js/commit/e62999f9ece7d9218b9768a908f8df9c11d7e920

Tôi có thể sử dụng ít nhất là bốn ký tự đầu tiên: https://github.com/wycats/handlebars.js/commit/e629

Nhưng tôi cảm thấy như thế sẽ có rủi ro. Nhưng giả sử một cơ sở mã hóa, trong một vài năm, có thể đã nói rằng Thay đổi 30k, cơ hội va chạm nếu tôi sử dụng 8 ký tự là gì? 12? Có một số thường được coi là chấp nhận được cho loại điều này?


Câu trả lời:


230

Câu hỏi này thực sự được trả lời trong Chương 7 của cuốn sách Pro Git :

Nói chung, tám đến mười ký tự là quá đủ để là duy nhất trong một dự án. Một trong những dự án Git lớn nhất, nhân Linux, đang bắt đầu cần 12 ký tự trong số 40 ký tự có thể để duy nhất.

7 chữ số là mặc định Git cho một SHA ngắn, vì vậy điều đó tốt cho hầu hết các dự án. Nhóm Kernel đã tăng số lần của họ, như đã đề cập, bởi vì có hàng trăm nghìn cam kết. Vì vậy, đối với các cam kết ~ 30k của bạn, 8 hoặc 10 chữ số sẽ hoàn toàn ổn.


37
Cũng lưu ý rằng gitkhá thông minh khi nói đến điều này. Bạn có thể đặt chữ viết tắt ngắn, nói thành 4 và gitsẽ sử dụng 4 chữ số cho càng nhiều giá trị băm càng tốt, nhưng chuyển sang 5 hoặc nhiều hơn khi biết rằng chữ viết tắt không phải là duy nhất ...
twalberg

31
Tuy nhiên, cũng lưu ý rằng điều này tất nhiên chỉ áp dụng cho thời điểm Git in SHA. Nếu bạn "lưu" các SHA viết tắt (giả sử, trong nhật ký, email, IM, v.v.) và sử dụng chúng sau này để tham khảo các cam kết, chúng có thể không còn là duy nhất! Mặc dù chắc chắn không có độ dài bình thường như 7-12 ký tự, nhưng nếu bạn giảm xuống còn 4 hoặc 5 và bạn nhận được vài chục nghìn đối tượng mới (hoặc cam kết, tùy thuộc vào ngữ cảnh), điều này thực sự có thể quay lại cắn bạn.
Nevik Rehnel

140

Lưu ý: bạn có thể hỏi git rev-parse --short SHA1 ngắn nhất và duy nhất.
Xem " git get băm ngắn từ băm thông thường "

git rev-parse --short=4 921103db8259eb9de72f42db8b939895f5651489
92110

Như bạn có thể thấy trong ví dụ của tôi, SHA1 có chiều dài là 5 ngay cả khi tôi chỉ định độ dài là 4.


Đối với các repos lớn, 7 không đủ kể từ năm 2010 và cam kết dce9648 bởi chính Linus Torvalds (git 1.7.4.4, tháng 10 năm 2010):

Mặc định của 7 xuất phát từ khá sớm trong quá trình phát triển git, khi bảy chữ số hex là rất nhiều (nó bao gồm khoảng 250+ triệu giá trị băm).
Hồi đó tôi nghĩ rằng bản sửa đổi 65 nghìn là rất nhiều (đó là những gì chúng tôi sắp đạt được ở BK), và mỗi bản sửa đổi có xu hướng khoảng 5-10 đối tượng mới hoặc hơn, vì vậy một triệu đối tượng là một con số lớn.

(BK = Máy quét bitcoin)

Những ngày này, các hạt nhân không phải là ngay cả những dự án lớn nhất git, và ngay cả những hạt nhân có khoảng 220k sửa đổi ( nhiều lớn hơn cây BK từng là) và chúng tôi đang tiếp cận hai triệu đối tượng.
Vào thời điểm đó, bảy chữ số hex vẫn là duy nhất cho rất nhiều trong số chúng, nhưng khi chúng ta nói về chỉ hai mức chênh lệch cường độ giữa số lượng đối tượng và kích thước băm, sẽ có xung đột trong các giá trị băm bị cắt bớt.
Nó thậm chí không còn gần với phi thực tế - nó xảy ra mọi lúc.

Cả hai chúng ta nên tăng chữ viết tắt mặc định nhỏ một cách phi thực tế thêm một cách để mọi người đặt dự án mặc định của riêng họ trong tệp cấu hình git .

core.abbrev

Đặt tên đối tượng chiều dài được viết tắt.
Nếu không được chỉ định, nhiều lệnh viết tắt thành 7 hexdigits, có thể không đủ để tên đối tượng viết tắt duy trì trong thời gian đủ dài.

environment.c:

int minimum_abbrev = 4, default_abbrev = 7;

Lưu ý: Như đã nhận xét bên dưới bởi marco.m , core.abbrevLengthđã được đổi tên trong core.abbrevcùng Git 1.7.4.4 trong cam kết a71f09f

Đổi tên core.abbrevlengththànhcore.abbrev

Nó tương ứng với --abbrev=$ntùy chọn dòng lệnh sau khi tất cả.


Gần đây, Linus đã thêm vào cam kết e6c587c (cho Git 2.11, Q4 2016):
(như đã đề cập trong câu trả lời của Matthieu Moy )

Trong những ngày đầu tiên, bằng cách nào đó chúng tôi đã quyết định viết tắt tên đối tượng xuống còn 7 chữ số, nhưng khi các dự án phát triển, ngày càng có nhiều khả năng thấy một tên đối tượng ngắn như vậy được tạo ra trong những ngày trước đó và được ghi lại trong các thông điệp tường trình không còn độc đáo.

Hiện tại, dự án nhân Linux cần 11 đến 12 hexdigits, trong khi bản thân Git cần 10 hexdigit để xác định duy nhất các đối tượng họ có, trong khi nhiều dự án nhỏ hơn vẫn có thể ổn với mặc định 7 hexdigit ban đầu. Một kích thước không phù hợp với tất cả các dự án.

Giới thiệu một cơ chế, trong đó chúng tôi ước tính số lượng đối tượng trong kho lưu trữ theo yêu cầu đầu tiên viết tắt tên đối tượng với cài đặt mặc định và đưa ra mặc định lành mạnh cho kho lưu trữ. Dựa trên kỳ vọng rằng chúng ta sẽ thấy xung đột trong kho lưu trữ với 2^(2N)các đối tượng khi sử dụng tên đối tượng được rút ngắn thành N bit đầu tiên, sử dụng đủ số lượng hexdigits để bao phủ số lượng đối tượng trong kho lưu trữ.
Mỗi hexdigit (4 bit) mà chúng ta thêm vào tên rút gọn cho phép chúng ta có bốn lần (2 bit) như nhiều đối tượng trong kho lưu trữ.

Xem cam kết e6c587c (01 tháng 10 năm 2016) bởi Linus Torvalds ( torvalds) .
Xem cam kết 7b5b772 , cam kết 65acfea (01 tháng 10 năm 2016) của Junio ​​C Hamano ( gitster) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết bb188d0 , ngày 03 tháng 10 năm 2016)

Thuộc tính mới đó (đoán mặc định hợp lý cho giá trị viết tắt SHA1) có ảnh hưởng trực tiếp đến cách Git tính toán số phiên bản của chính nó để phát hành .


3
Câu trả lời này cung cấp một cách để kiểm tra xem hàm băm "rút ngắn" dài nhất trong một kho lưu trữ là gì: stackoverflow.com/a/32406103/1858225
Kyle Strand

1
Lưu ý rằng core.abbrevLengthđã được đổi tên thành core.abbrev.
marco.m

@ marco.m Cảm ơn bạn. Tôi đã sửa đổi câu trả lời cho phù hợp. Và tôi đã liên kết với cam kết Git ghi lại tên mới đó core.abbrev.
VonC

Tôi sẽ chỉ thêm vào điều này để bạn có thể chạy git rev-parse --short=10 --verify HEADđể tạo 10 ký tự. Chúng tôi đã sử dụng git log -1 --format=%h, nhưng điều đó chỉ tạo ra 7 ký tự và chúng tôi đã va chạm.
Grayaii

Cảm ơn lời giải thích, các tài liệu ( git-scm.com/docs/git-rev-parse ) đã cũ.
André Werlang

36

Điều này được gọi là vấn đề sinh nhật.

Đối với xác suất nhỏ hơn 1/2 xác suất va chạm có thể xấp xỉ bằng

p ~ = (n 2 ) / (2m)

Trong đó n là số lượng vật phẩm và m là số khả năng cho mỗi vật phẩm.

Số khả năng cho một chuỗi hex là 16 c trong đó c là số lượng ký tự.

Vì vậy, cho 8 ký tự và 30K cam kết

30K ~ = 2 15

p ~ = (n 2 ) / (2m) ~ = ((2 15 ) 2 ) / (2 * 16 8 ) = 2 30 /2 33 = ⅛

Tăng nó lên 12 ký tự

p ~ = (n 2 ) / (2m) ~ = ((2 15 ) 2 ) / (2 * 16 12 ) = 2 30 /2 49 = 2 -19


Chính xác câu hỏi tôi đang cố gắng giải quyết, cảm ơn bạn! Bảng xác suất được liên kết trong câu trả lời của @ Messa cũng hữu ích.
Kyle Chadha

tuyệt vời, chúng ta không cần gì khác ngoài việc này, giải thích nó không chỉ là gì mà còn là nó đến như thế nào ...
workplaylifecycle 20/07/19

13

Câu hỏi này đã được trả lời, nhưng đối với bất kỳ ai đang tìm kiếm toán học phía sau - đó gọi là vấn đề sinh nhật ( Wikipedia ).

Đó là về khả năng có 2 (hoặc nhiều hơn) những người thuộc nhóm N người có sinh nhật vào cùng một ngày trong năm. Tương tự như xác suất của 2 (hoặc nhiều hơn) git cam kết từ kho lưu trữ có N cam kết trong tổng số có cùng tiền tố băm có độ dài X.

Nhìn vào bảng Xác suất . Ví dụ: đối với chuỗi hex băm có độ dài 8, xác suất xảy ra va chạm đạt 1% khi kho lưu trữ chỉ có khoảng 9300 mục (cam kết git). Đối với 110 000 cam kết xác suất là 75%. Nhưng nếu bạn có chuỗi hex băm có độ dài 12 thì xác suất va chạm trong 100 000 lần xác nhận là dưới 0,1%.


2

Phiên bản Git 2.11 (hoặc có lẽ là 2.12?) Sẽ chứa một tính năng điều chỉnh số lượng ký tự được sử dụng trong các định danh ngắn (ví dụ git log --oneline) theo kích thước của dự án. Khi bạn sử dụng phiên bản Git như vậy, câu trả lời cho câu hỏi của bạn có thể là "chọn bất kỳ độ dài nào mà Git mang lại cho bạngit log --oneline , nó đủ an toàn".

Để biết thêm chi tiết, hãy xem Thay đổi mặc định cho lõi core.abenamv? thảo luận trong Git Rev News phiên bản 20 và cam kết bb188d00f7 .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.