256

たとえば、ディレクトリが Git リポジトリのコミットの名前が付けられているディレクトリ構造を構築しようとしていて、目が出血しないように十分に短く、衝突の可能性が十分にあるように十分に長くしたい場合SHA 部分文字列のどれくらいが一般的に必要ですか?

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

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

しかし、それはリスクが高いと感じています。しかし、コードベースが数年で、たとえば 30,000 の変更を加える可能性があると仮定すると、8 文字を使用した場合、衝突の可能性はどのくらいになるでしょうか? 12? この種のことに対して一般的に許容されると考えられる数値はありますか?

4

5 に答える 5

284

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

一般に、プロジェクト内で一意であるには、8 ~ 10 文字で十分です。最大の Git プロジェクトの 1 つである Linux カーネルは、一意性を維持するために、可能な 40 文字のうち 12 文字が必要になり始めています。

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

于 2013-08-08T19:54:41.357 に答える
173

git rev-parse --short注:最短でありながら一意の SHA1 を求めることができます。
git get short hash from regular hash」を参照してください

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

この例でわかるように、長さ 4 を指定した場合でも、SHA1 の長さは 5 です。


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

デフォルトの 7 は、7 桁の 16 進数が多かった (約 2 億 5000 万以上のハッシュ値をカバーする) git 開発のかなり初期の段階から来ています。
当時、私は 65,000 のリビジョンは多いと思っていました (これは、BK でヒットしようとしていたことです)。各リビジョンは約 5 ~ 10 個の新しいオブジェクトになる傾向があるため、100 万個のオブジェクトは大きな数でした。

(BK = ビットキーパー)

最近では、カーネルは最大の git プロジェクトではありません。カーネルでさえ、約 220,000 のリビジョン (これまでの BK ツリーよりもはるかに大きい) を持ち、200 万個のオブジェクトに近づいています。その時点で、16 進数の 7 桁は多くのオブジェクトにとってまだ一意ですが、オブジェクトの数とハッシュ サイズの差が
2 桁しかない場合、切り捨てられたハッシュ値で競合が発生します。 それはもはや非現実的なことではありません - それは常に起こります。

非現実的なほど小さいデフォルトの省略形を増やし、git config file でプロジェクトごとに独自のデフォルトを設定する方法を追加する必要があります

core.abbrev

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

environment.c:

int minimum_abbrev = 4, default_abbrev = 7;

注:以下でmarco.mによってコメントされているように、コミット a71f09fの同じ Git 1.7.4.4 で名前core.abbrevLengthが変更されましたcore.abbrev

名前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 ( )によるコミット e6c587c (2016 年 10 月 1 日)を参照してください。commit 7b5b772commit 65acfea (2016 年 10 月 1 日) by Junio C Hamano ( ) を参照してください。( 2016 年 10 月 3 日コミット bb188d0Junio C Hamanoによってマージされました)torvalds
gitster
gitster

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

于 2014-01-09T08:25:01.127 に答える
15

この質問には回答がありますが、背後にある数学を探している人にとっては、誕生日の問題(ウィキペディア) と呼ばれています。

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

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

于 2016-08-20T20:13:24.533 に答える
2

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

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

于 2016-10-24T14:06:57.723 に答える