Berapa banyak dari git sha * umumnya * dianggap perlu untuk secara unik mengidentifikasi perubahan dalam basis kode yang diberikan?

212

Jika Anda akan membangun, katakanlah, struktur direktori tempat direktori diberi nama untuk komit di repositori Git, dan Anda ingin itu cukup pendek untuk membuat mata Anda tidak berdarah, tetapi cukup lama sehingga kemungkinan bertabrakan. akan diabaikan, berapa banyak substring SHA umumnya diperlukan?

Katakanlah saya ingin secara unik mengidentifikasi perubahan ini: https://github.com/wycats/handlebars.js/commit/e62999f9ece7d9218b9768a908f8df9c11d7e920

Saya dapat menggunakan sesedikit empat karakter pertama: https://github.com/wycats/handlebars.js/commit/e629

Tapi saya merasa itu akan berisiko. Tetapi dengan menggunakan basis kode yang, selama beberapa tahun, mungkin memiliki — katakanlah — 30 ribu perubahan, apa peluang tabrakan jika saya menggunakan 8 karakter? 12? Apakah ada nomor yang secara umum dianggap dapat diterima untuk hal semacam ini?

Jun-Dai Bates-Kobashigawa
sumber

Jawaban:

230

Pertanyaan ini sebenarnya dijawab dalam Bab 7 buku Pro Git :

Secara umum, delapan hingga sepuluh karakter lebih dari cukup untuk menjadi unik dalam suatu proyek. Salah satu proyek Git terbesar, kernel Linux, mulai membutuhkan 12 karakter dari 40 yang mungkin untuk tetap unik.

7 digit adalah standar Git untuk SHA pendek, jadi itu bagus untuk sebagian besar proyek. Tim Kernel telah meningkat beberapa kali, seperti yang disebutkan, karena mereka memiliki beberapa ratus ribu komitmen. Jadi untuk komit ~ 30k Anda, 8 atau 10 digit harus baik-baik saja.

Nevik Rehnel
sumber
38
Perhatikan juga bahwa gitini cukup pintar dalam hal ini. Anda dapat mengatur singkatan, katakan menjadi 4, dan gitakan menggunakan 4 digit untuk hash sebanyak mungkin, tetapi beralih ke 5 atau lebih ketika tahu bahwa singkatan itu tidak unik ...
twalberg
31
Perhatikan juga, bahwa ini tentu saja hanya berlaku untuk saat Git mencetak SHA. Jika Anda "menyimpan" SHA yang disingkat (katakanlah, dalam log, email, IM, dll.) Dan gunakan nanti untuk merujuk pada commit, mereka mungkin tidak lagi unik! Meskipun tentu tidak mungkin untuk panjang normal seperti 7-12 karakter, jika Anda turun ke 4 atau 5, dan Anda mendapatkan beberapa ribu objek baru (atau melakukan, tergantung pada konteks), ini mungkin memang kembali menggigit Anda.
Nevik Rehnel
140

Catatan: Anda dapat meminta git rev-parse --shortSHA1 yang terpendek namun unik.
Lihat " git dapatkan hash pendek dari hash biasa "

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

Seperti yang Anda lihat dalam contoh saya SHA1 memiliki panjang 5 bahkan jika saya menentukan panjang 4.


Untuk repo besar, 7 tidak cukup sejak 2010, dan melakukan dce9648 oleh Linus Torvalds sendiri (git 1.7.4.4, Okt 2010):

Default 7 berasal dari cukup awal dalam pengembangan git, ketika tujuh digit hex banyak (mencakup sekitar 250+ juta nilai hash).
Saat itu saya berpikir bahwa revisi 65 ribu adalah banyak (itu yang akan kita bahas di BK), dan setiap revisi cenderung sekitar 5-10 objek baru, jadi sejuta objek adalah jumlah yang besar.

(BK = BitKeeper)

Hari-hari ini, kernel bahkan bukan proyek git terbesar, dan bahkan kernel memiliki sekitar 220 ribu revisi ( jauh lebih besar dari pohon BK sebelumnya) dan kami mendekati dua juta objek.
Pada titik itu, tujuh digit hex masih unik untuk banyak dari mereka, tetapi ketika kita berbicara tentang hanya dua urutan perbedaan besarnya antara jumlah objek dan ukuran hash, akan ada tabrakan dalam nilai hash terpotong.
Itu bahkan tidak lagi mendekati tidak realistis - itu terjadi setiap saat.

Kita berdua harus meningkatkan singkatan default yang tidak realistis kecil, dan menambahkan cara bagi orang untuk menetapkan standar per proyek mereka sendiri dalam file konfigurasi git .

core.abbrev

Atur panjang nama objek yang disingkat.
Jika tidak ditentukan, banyak perintah disingkat menjadi 7 hexdigits, yang mungkin tidak cukup untuk nama objek yang disingkat agar tetap unik untuk waktu yang cukup lama.

environment.c:

int minimum_abbrev = 4, default_abbrev = 7;

Catatan: Seperti yang dikomentari di bawah ini oleh marco.m , core.abbrevLengthdiganti namanya di core.abbrevGit 1.7.4.4 yang sama di commit a71f09f

Ganti nama core.abbrevlengthkembali menjadicore.abbrev

Itu sesuai dengan --abbrev=$nopsi baris perintah setelah semua.


Baru-baru ini, Linus ditambahkan dalam melakukan e6c587c (untuk Git 2.11, Q4 2016):
(seperti yang disebutkan di Matthieu Moy 's jawaban )

Pada hari-hari yang cukup awal, kami entah bagaimana memutuskan untuk menyingkat nama objek menjadi 7-hexdigits, tetapi seiring bertambahnya proyek, semakin besar kemungkinan nama objek pendek dibuat pada hari-hari sebelumnya dan dicatat dalam pesan log tidak lagi unik.

Saat ini proyek kernel Linux membutuhkan 11 hingga 12 hexdigits, sementara Git sendiri membutuhkan 10 hexdigits untuk secara unik mengidentifikasi objek yang mereka miliki, sementara banyak proyek yang lebih kecil mungkin masih baik-baik saja dengan default 7-hexdigit asli. Satu ukuran tidak cocok untuk semua proyek.

Memperkenalkan suatu mekanisme, di mana kami memperkirakan jumlah objek dalam repositori atas permintaan pertama untuk menyingkat nama objek dengan pengaturan default dan muncul dengan standar waras untuk repositori. Berdasarkan harapan bahwa kita akan melihat tabrakan dalam repositori dengan 2^(2N)objek ketika menggunakan nama objek yang disingkat menjadi N bit pertama, gunakan jumlah hexdigit yang cukup untuk menutupi jumlah objek dalam repositori.
Setiap hexdigit (4-bit) yang kita tambahkan ke nama yang disingkat memungkinkan kita untuk memiliki empat kali (2-bit) karena banyak objek dalam repositori.

Lihat komit e6c587c (01 Okt 2016) oleh Linus Torvalds ( torvalds) .
Lihat komit 7b5b772 , komit 65acfea (01 Okt 2016) oleh Junio ​​C Hamano ( gitster) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam komit bb188d0 , 03 Okt 2016)

Properti baru itu (menebak default yang masuk akal untuk nilai singkatan SHA1) memiliki efek langsung pada bagaimana Git menghitung nomor versinya sendiri untuk rilis .

VONC
sumber
3
Jawaban ini menyediakan cara untuk memeriksa apa hash "singkat" terpanjang dalam repositori tunggal adalah: stackoverflow.com/a/32406103/1858225
Kyle Strand
1
Catatan yang core.abbrevLengthtelah diubah namanya menjadi core.abbrev.
marco.m
@ marco.m Terima kasih. Saya telah mengubah jawaban sesuai dengan itu. Dan saya telah menautkan ke komit Git yang mencatat nama baru itu untuk core.abbrev.
VonC
Saya hanya akan menambahkan ini yang dapat Anda jalankan git rev-parse --short=10 --verify HEADuntuk menghasilkan 10 karakter. Kami menggunakan git log -1 --format=%h, tapi itu hanya menghasilkan 7 karakter dan kami mendapat tabrakan.
grayaii
Terima kasih atas penjelasannya, dokumen ( git-scm.com/docs/git-rev-parse ) sudah basi.
André Werlang
36

Ini dikenal sebagai masalah ulang tahun.

Untuk probabilitas kurang dari 1/2 probabilitas tabrakan dapat diperkirakan sebagai

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

Di mana n adalah jumlah item dan m adalah jumlah kemungkinan untuk setiap item.

Jumlah kemungkinan untuk string hex adalah 16 c mana c adalah jumlah karakter.

Jadi untuk 8 karakter dan 30K komit

30K ~ = 2 15

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

Menambahnya menjadi 12 karakter

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

plugwash
sumber
Persis pertanyaan yang saya coba pecahkan, terima kasih! Tabel probabilitas yang ditautkan dalam jawaban @ Messa juga membantu.
Kyle Chadha
luar biasa, kita tidak membutuhkan yang lain selain ini, jelaskan tidak hanya apa itu tetapi juga bagaimana itu datang ...
workplaylifecycle
13

Pertanyaan ini telah dijawab, tetapi bagi siapa pun yang mencari matematika di belakang - ini disebut masalah Ulang Tahun ( Wikipedia )

Ini adalah tentang kemungkinan memiliki 2 (atau lebih) orang dari kelompok N orang untuk berulang tahun pada hari yang sama dalam setahun. Yang analog dengan kemungkinan 2 (atau lebih) git dikomit dari repositori yang memiliki N komit secara total memiliki awalan hash yang sama dengan panjang X.

Lihatlah tabel Probabilitas . Sebagai contoh untuk hash hex string dengan panjang 8, probabilitas tabrakan mencapai 1% ketika repositori hanya memiliki sekitar 9300 item (git melakukan). Untuk 110.000 komit, probabilitasnya adalah 75%. Tetapi jika Anda memiliki hash hex string dengan panjang 12 probabilitas tabrakan dalam 100.000 komit di bawah 0,1%.

Messa
sumber
2

Git versi 2.11 (atau mungkin 2.12?) Akan berisi fitur yang menyesuaikan jumlah karakter yang digunakan dalam pengidentifikasi pendek (misalnya git log --oneline) dengan ukuran proyek. Setelah Anda menggunakan versi Git seperti itu, jawaban untuk pertanyaan Anda bisa "pilih berapa pun yang diberikan Git kepada Andagit log --oneline , cukup aman".

Untuk detail lebih lanjut, lihat Mengubah default untuk "core.abbrev"? diskusi di Git Rev News edisi 20 dan melakukan bb188d00f7 .

Matthieu Moy
sumber