Belirli bir kod tabanındaki bir değişikliği benzersiz bir şekilde tanımlamak için * genellikle * ne kadar bir git sha gerekir?


212

Diyelim ki, Git deposunda bir taahhüt için bir dizinin adlandırıldığı bir dizin yapısı inşa edecekseniz ve gözlerinizin kanaması için yeterince kısa, ancak çarpışma şansı kadar uzun olmasını istiyorsanız genellikle ne kadar SHA alt dizesi gereklidir?

Bu değişikliği benzersiz bir şekilde tanımlamak istediğimi varsayalım: https://github.com/wycats/handlebars.js/commit/e62999f9ece7d9218b9768a908f8df9c11d7e920

İlk dört karakter kadar azını kullanabilirim: https://github.com/wycats/handlebars.js/commit/e629

Ama bunun riskli olacağını hissediyorum. Ancak, birkaç yıl içinde 30 bin değişiklik yapabilen bir kod temeli varsa, 8 karakter kullanırsam çarpışma şansı nedir? 12? Bu tür şeyler için genellikle kabul edilebilir bir sayı var mı?


Yanıtlar:


230

Bu soru aslında Pro Git kitabının 7. Bölümünde yanıtlanmaktadır :

Genellikle, bir projede benzersiz olmak için sekiz ila on karakter yeterlidir. En büyük Git projelerinden biri olan Linux çekirdeği, benzersiz kalabilmek için 40'tan 12 karaktere ihtiyaç duymaya başlıyor.

Kısa bir SHA için 7 basamak Git varsayılanıdır, bu nedenle çoğu proje için uygundur. Çekirdek ekibi, daha önce de belirtildiği gibi, birkaç kez arttı, çünkü birkaç yüz bin taahhüt var. Bu nedenle ~ 30 bin işleminiz için 8 veya 10 basamak mükemmel şekilde iyi olmalıdır.


38
Ayrıca git, bunun söz konusu olduğunda oldukça akıllı olduğunu unutmayın . Kısaltmayı kısa olarak 4'e ayarlayabilir ve gitolabildiğince çok karma için 4 hane kullanabilirsiniz, ancak kısaltmanın benzersiz olmadığını bildiğinde 5 veya daha fazla
seçeneğe geçin

31
Bununla birlikte, bunun elbette sadece Git'in SHA'yı yazdırdığı an için geçerli olduğunu da unutmayın. Kısaltılmış SHA'ları "kaydederseniz" (örneğin günlüklerde, e-postalarda, IM'lerde vb.) Ve bunları daha sonra taahhütlere atıfta bulunmak için kullanırsanız, artık benzersiz olmayabilirler! 7-12 karakter gibi normal uzunluklar için kesinlikle olası olmasa da, 4 veya 5'e inerseniz ve birkaç on bin yeni nesne alırsanız (veya bağlama göre değişir), bu gerçekten sizi ısırmaya geri dönebilir.
Nevik Rehnel

140

Not: git rev-parse --shortEn kısa ve benzersiz SHA1'i isteyebilirsiniz .
Bkz. " Git normal karmadan kısa karma "

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

Örneğimde de görebileceğiniz gibi, 4 uzunluğunu belirtmiş olsam bile SHA1'in uzunluğu 5'tir.


Büyük depolar için 7, 2010'dan beri yeterli değildir ve Linus Torvalds'ın kendisi tarafından dce9648 taahhüt edin (git 1.7.4.4, Eki 2010):

Yedi varsayılan rakam, yedi onaltılık basamak çok olduğunda (yaklaşık 250+ milyon hash değerini kapsar) git gelişiminde oldukça erken gelir.
O zamanlar 65k revizyonun çok olduğunu düşündüm (BK'da vurmak üzereydik) ve her revizyon yaklaşık 5-10 yeni nesne ya da bu yüzden bir milyon nesne büyük bir sayıydı.

(BK = BitKeeper)

Bu günlerde, çekirdek en büyük git projesi bile değil ve hatta çekirdek bile yaklaşık 220 bin revizyona sahip ( BK ağacından çok daha büyük) ve iki milyon nesneye yaklaşıyoruz.
Bu noktada, yedi onaltılık basamak hala birçoğu için benzersizdir, ancak nesne sayısı ve karma boyutu arasında sadece iki büyüklük farkı söz konusu olduğunda , kesilmiş karma değerlerinde çarpışmalar olacaktır .
Artık gerçekçi olmayanlara bile yakın değil - her zaman oluyor.

Biz de gerçekçi olamayacak kadar küçüktü varsayılan kısaltması artırmak gerektiğini ve insanların git config dosyasında başına proje kendi varsayılan ayarlamak için bir yol ekleyin .

core.abbrev

Uzunluk olarak adlandırılan nesne adlarını ayarlayın.
Belirtilmezse, birçok komut 7 onaltılık kısaltma ile kısaltılır; bu, kısaltılmış nesne adlarının yeterince uzun süre benzersiz kalması için yeterli olmayabilir.

environment.c:

int minimum_abbrev = 4, default_abbrev = 7;

Not: As aşağıda yorumladı tarafından marco.m , core.abbrevLengthiçinde değiştirildi core.abbreviçinde aynı Git 1.7.4.4 yılında a71f09f taahhüt

Yeniden adlandırma core.abbrevlengthgericore.abbrev

Sonuçta --abbrev=$nkomut satırı seçeneğine karşılık gelir .


Daha yakın zamanlarda, Linus ilave e6c587c taahhüt (Git 2.11 için, S4 2016):
(belirtildiği gibi Matthieu Moy 'ın cevabı )

Oldukça erken günlerde, bir şekilde 7-onaltılık sayılara kadar nesne adlarını kısaltmaya karar verdik, ancak projeler büyüdükçe, daha önceki günlerde yapılan ve günlük iletilerine kaydedilen bu kadar kısa bir nesne adlarının artık benzersiz olmadığı görülüyor.

Şu anda Linux çekirdeği projesi 11 ila 12 onaltılık düzeye ihtiyaç duyarken, Git'in sahip oldukları nesneleri benzersiz bir şekilde tanımlamak için 10 onaltılık düzeye ihtiyacı varken, birçok küçük proje orijinal 7-onaltılık varsayılanı ile hala iyi olabilir. Tek beden tüm projelere uymaz.

Bir nesne adını varsayılan ayarla kısaltmak ve depo için aklı başında bir varsayılan bulmak için ilk istek üzerine depodaki nesne sayısını tahmin ettiğimiz bir mekanizma tanıtın. 2^(2N)İlk N bitine kısaltılmış nesne adlarını kullanırken nesnelerle birlikte bir depoda çarpışma göreceğimiz beklentisine dayanarak, havuzdaki nesne sayısını karşılamak için yeterli sayıda onaltılık kullanın.
Kısaltılmış ada eklediğimiz her hexdigit (4 bit), depodaki nesnelerin dört katına (2 bit) sahip olmamızı sağlar.

Linus Torvalds ( ) tarafından taahhüt edilen e6c587c (01 Ekim 2016) bölümüne bakınız . Bkz 7b5b772 işlemek , 65acfea taahhüt tarafından (01 Eki 2016) Junio C Hamano ( ) . ( Junio ​​C Hamano tarafından birleştirildi - - içinde taahhüt bb188d0 , 03 Eki 2016)torvalds
gitster
gitster

Bu yeni özelliğin (SHA1 kısaltma değeri için makul bir varsayılan tahmin) Git'in sürüm için kendi sürüm numarasını nasıl hesapladığı üzerinde doğrudan bir etkisi vardır .


3
Bu yanıt, tek bir depodaki en uzun "kısaltılmış" karmanın ne olduğunu kontrol etmenin bir yolunu sunar: stackoverflow.com/a/32406103/1858225
Kyle Strand

1
Yeniden core.abbrevLengthadlandırıldığını unutmayın core.abbrev.
marco.m

@ marco.m Teşekkür ederim. Cevabı buna göre değiştirdim. Ve yeni adı kaydeden Git taahhüdüne bağlandım core.abbrev.
VonC

Ben sadece git rev-parse --short=10 --verify HEAD10 karakter oluşturmak için çalıştırabilirsiniz ekleyeceğiz . Kullanıyorduk git log -1 --format=%h, ama bu sadece 7 karakter üretti ve bir çarpışma yaşadık.
grayaii

Açıklama için teşekkürler, dokümanlar ( git-scm.com/docs/git-rev-parse ) bayat.
André Werlang

36

Bu doğum günü problemi olarak bilinir.

1/2'den düşük olasılıklar için, bir çarpışma olasılığı şu şekilde tahmin edilebilir:

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

Burada n, öğe sayısı ve m, her öğe için olasılık sayısıdır.

Onaltılık bir dize için olasılık sayısı 16 c'dir, burada c karakter sayısıdır.

Yani 8 karakter ve 30 bin taahhüt için

30K ~ = 2 15

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

12 karaktere yükseltmek

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


Tam olarak çözmeye çalıştığım soru, teşekkür ederim! @ Messa'nın cevabında yer alan olasılık tablosu da faydalıdır.
Kyle Chadha

mükemmel, daha başka bir şeye ihtiyacımız yok, sadece ne olduğunu değil, aynı zamanda nasıl geldiğini
açıklayın

13

Bu soru cevaplandı, ancak arkasında matematik arayan herkes için - buna Doğum Günü problemi ( Wikipedia ) deniyor .

N grubundan 2 (veya daha fazla) kişinin yılın aynı günü doğum günü geçirme olasılığıyla ilgilidir. Muhtemelen 2 (veya daha fazla) git'e benzeyen git, toplamda X uzunluğunun aynı karma önekine sahip N taahhütlerine sahip depodan taahhüt eder.

Bak Olasılık masaya . Örneğin, uzunluğu 8 olan karma onaltılık dize için, depoda yaklaşık 9300 öğe olduğunda (git komutu) çarpışma olasılığı% 1'e ulaşır. 110.000 taahhüt için olasılık% 75'tir. Ancak, 12 uzunluğunda karma altıgen dizeniz varsa 100.000 işlemede çarpışma olasılığı% 0.1'in altındadır.


2

Git sürüm 2.11 (veya belki 2.12?), Kısa tanımlayıcılarda (örneğin git log --oneline) kullanılan karakter sayısını projenin boyutuna uyarlayan bir özellik içerecektir . Git'in böyle bir sürümünü kullandıktan sonra, sorunuzun cevabı "Git'in size sağladığı uzunluğu seçin git log --oneline, yeterince güvenlidir" olabilir.

Daha fazla ayrıntı için bkz . “Core.abbrev” için varsayılanı değiştirme? Git Rev News edition 20'deki tartışma ve bb188d00f7'yi taahhüt edin .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.