特定のコードベースの変更を一意に識別するために、どのくらいのgit shaが「一般に」必要と考えられていますか?


211

たとえば、Gitリポジトリでcommitのためにディレクトリに名前が付けられているディレクトリ構造を構築する場合、目を出血させないように短くするが、衝突する可能性があるほど長くする必要がある場合無視できますが、SHAサブストリングのどのくらいが一般的に必要ですか?

この変更を一意に識別したいとしましょう:https : //github.com/wycats/handlebars.js/commit/e62999f9ece7d9218b9768a908f8df9c11d7e920

最初の4文字まで使用できます:https : //github.com/wycats/handlebars.js/commit/e629

しかし、それは危険だと思います。しかし、2〜3年で、たとえば3万個の変更がある可能性があるコードベースを想定すると、8文字を使用した場合に衝突する可能性は何ですか?12?この種のものに一般的に受け入れられると考えられる数はありますか?


回答:


230

この質問は、実際にはPro Gitブックの第7章で回答されています。

通常、8〜10文字は、プロジェクト内で一意になるには十分です。最大のGitプロジェクトの1つであるLinuxカーネルは、固有の文字数を維持するために、40文字のうち12文字を必要とし始めています。

7桁は短いSHAのGitデフォルトなので、ほとんどのプロジェクトで問題ありません。カーネルチームは、数十万回のコミットがあるため、前述のように数回増加しています。したがって、約3万回のコミットでは、8桁または10桁で十分です。


37
また、これに関してgitはかなり賢いことに注意してください。省略形を短く、たとえば4に設定して、git
できるだけ

31
ただし、これはもちろん、GitがSHAを印刷するときにのみ適用されることにも注意してください。短縮されたSHA(たとえば、ログ、電子メール、IMなど)を "保存"し、後でコミットを参照するために使用すると、一意ではなくなる可能性があります。7〜12文字のような通常の長さの場合は確かにありそうもありませんが、4または5に減らして、数万の新しいオブジェクト(またはコンテキストによってはコミット)を取得した場合、これは実際に戻ってきます。
Nevik Rehnel 2013年

140

注:git rev-parse --short最短かつユニークなSHA1を要求できます。
「を参照してください。定期的なハッシュから短いハッシュを取得するGIT

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

私の例でわかるように、長さを4に指定しても、SHA1の長さは5です。


大きなリポジトリの場合、2010年以降7では不十分であり、Linus Torvalds自身がdce9648コミットします(git 1.7.4.4、2010年10月):

デフォルトの7は、Git開発のかなり早い段階であり、7桁の16進数が多かった(約2億5000万以上のハッシュ値に対応)。
当時、65,000のリビジョンはたくさんあり(BKでヒットしようとしていた)、各リビジョンは約5〜10の新しいオブジェクトになる傾向があるため、100万のオブジェクトが大きな数でした。

(BK = BitKeeper)

最近では、カーネルは最大のgitプロジェクトでもなく、カーネルにも約220kのリビジョン(BKツリーよりもはるかに大きい)があり、200万のオブジェクトに近づいています。
その時点で、7桁の16進数、まだそれらの多くのためにユニークですが、私たちは、オブジェクトの数とハッシュサイズとの大きさの差の程度ちょうど2つの注文を話しているとき、そこになります切り捨てられ、ハッシュ値の衝突なります。
それはもはや非現実的なものに近づくことさえありません-それはいつも起こります。

我々は両方の非現実小さかったデフォルトの略語を増加させ、必要がある人々はGitの設定ファイルにプロジェクトごとの自分のデフォルトを設定するための方法を追加します

core.abbrev

オブジェクト名が省略される長さを設定します。
指定されていない場合、多くのコマンドは7桁の16進数に短縮されます。これは、短縮されたオブジェクト名が十分に長い間一意であるには不十分な場合があります。

environment.c

int minimum_abbrev = 4, default_abbrev = 7;

注:としては、以下のコメントmarco.mcore.abbrevLengthに改名されたcore.abbrevのそれと同じGitの1.7.4.4にコミットa71f09f

名前をcore.abbrevlength元に戻すcore.abbrev

--abbrev=$n結局のところ、コマンドラインオプションに対応しています。


最近、Linusがコミットe6c587cに追加しました(Git 2.11、2016年第4四半期用):(Matthieu Moy回答で
述べたように)

かなり初期の段階で、オブジェクト名を7桁の16進数に短縮することにしましたが、プロジェクトが成長するにつれて、以前に作成されてログメッセージに記録されたこのような短いオブジェクト名が一意ではなくなる可能性が高まっています。

現在、Linuxカーネルプロジェクトでは11桁から12桁の16進数が必要ですが、Git自体ではオブジェクトを一意に識別するために10桁の16桁が必要ですが、小さなプロジェクトの多くは、元の7桁のデフォルトで問題ない場合があります。ワンサイズはすべてのプロジェクトに適合しません。

メカニズムを導入します。最初のリクエストでリポジトリ内のオブジェクト数を見積もり、デフォルト設定でオブジェクト名を省略して、リポジトリの適切なデフォルトを作成します。2^(2N)最初のNビットに短縮されたオブジェクト名を使用すると、リポジトリとオブジェクトの衝突が発生するという予想に基づいて、リポジトリ内のオブジェクトの数をカバーするのに十分な数の16進数を使用します。
短縮名に追加する16進数(4ビット)ごとに、リポジトリ内に4倍(2ビット)のオブジェクトを含めることができます。

Linus Torvalds()によるcommit e6c587c(01 Oct 2016)を参照してください。Junio C Hamano()によるcommit 7b5b772commit 65acfea(2016年10月1日)を 参照してください。(による合併Junio C浜野- -bb188d0コミット、2016年10月3日)をtorvalds
gitster
gitster

その新しいプロパティ(SHA1の省略値の妥当なデフォルトを推測する)は、Gitがreleaseの独自のバージョン番号を計算する方法に直接影響します。


3
この回答は、単一のリポジトリで最も長い「短縮された」ハッシュが何であるかを確認する方法を提供します:stackoverflow.com/a/32406103/1858225
Kyle Strand

1
core.abbrevLength名前が変更されていることに注意してくださいcore.abbrev
marco.m

@ marco.mありがとうございます。私はそれに応じて答えを修正しました。そして、の新しい名前を記録するGitコミットにリンクしましたcore.abbrev
VonC

これに追加して、実行git rev-parse --short=10 --verify HEADして10文字を生成できるようにします。を使用しましたがgit log -1 --format=%h、7文字しか生成されず、衝突が発生しました。
grayaii

説明をありがとう、ドキュメント(git-scm.com/docs/git-rev-parse)は古くなっています。
アンドレ・Werlang

36

これは誕生日の問題として知られています。

1/2未満の確率の場合、衝突の確率は次のように近似できます。

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

ここで、nはアイテムの数、mは各アイテムの可能性の数です。

16進文字列の可能性の数は16 cです。ここで、cは文字数です。

したがって、8文字と30Kコミットの場合

30K〜= 2 15

P〜=(N 2)/(2M)=〜((2 152)/(2×16 8は)2 = 30 /2 33 =を⅛

12文字に増やす

P〜=(N 2)/(2M)=〜((2 152)/(2 * 16 12)= 2 30 /2 49 = 2 -19


まさに私が解決しようとしていた質問、ありがとう!@Messaの回答にリンクされている確率表も役立ちます。
Kyle Chadha

すばらしい、これ以上のことは必要ありません。それが何であるかだけでなく、どうやって来るのかも説明してください...
workplaylifecycle

13

この質問は答えられましたが、背後にある数学を探している人のために-それは誕生日問題Wikipedia)と呼ばれています。

N人のグループから2人(またはそれ以上)の人が1年の同じ日に誕生日を迎える確率についてです。これは、リポジトリーからの2(またはそれ以上)のgitコミットの確率が、長さXの同じハッシュプレフィックスを持つ合計N個のコミットを持つことに類似しています。

確率表を見てください。たとえば、長さ8のハッシュ16進文字列の場合、リポジトリーに約9300項目(gitコミット)しかない場合、衝突の確率は1%に達します。11万回のコミットの場合、確率は75%です。ただし、長さが12のハッシュ16進文字列がある場合、100,000回のコミットでの衝突の確率は0.1%未満です。


2

Gitバージョン2.11(またはおそらく2.12?)には、短い識別子(たとえばgit log --oneline)で使用される文字数をプロジェクトのサイズに適合させる機能が含まれます。このようなバージョンのGitを使用すると、質問に対する答えは、「Gitが提供する長さを選択git log --onelineするだけで十分です」になります。

詳細については、「core.abbrev」のデフォルトの変更を参照してくださいGit Rev Newsエディション20での議論bb188d00f7のコミット。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.