주어진 코드베이스에서 변경 사항을 고유하게 식별하는 데 필요한 git sha의 양은 얼마나됩니까?


212

예를 들어 Git 리포지토리에서 커밋에 대한 디렉토리의 이름을 가진 디렉토리 구조를 만들려고 할 때 눈이 번지지 않도록 충분히 짧을 것이지만 충돌 할 가능성이 충분히 길기를 원한다면 무시할 수 있습니다. 일반적으로 SHA 하위 문자열이 얼마나 많이 필요합니까?

https://github.com/wycats/handlebars.js/commit/e62999f9ece7d9218b9768a908f8df9c11d7e920 을 고유하게 식별하고 싶다고 가정 해 봅시다.

처음 네 글자 만큼만 사용할 수 있습니다 : https://github.com/wycats/handlebars.js/commit/e629

그러나 나는 그것이 위험하다고 생각합니다. 그러나 몇 년 동안 30k 개의 변경 사항이있을 수있는 코드베이스를 가정하면 8자를 사용할 경우 충돌 가능성은 무엇입니까? 12? 이런 종류의 물건에 일반적으로 허용되는 숫자가 있습니까?


답변:


230

이 질문은 실제로 Pro Git 책의 7 장 에서 대답합니다 .

일반적으로 8-10 문자는 프로젝트 내에서 고유하기에 충분합니다. 가장 큰 Git 프로젝트 중 하나 인 Linux 커널은 고유성을 유지하기 위해 가능한 40 개 중 12자를 필요로합니다.

짧은 SHA의 경우 Git 기본값은 7 자리이므로 대부분의 프로젝트에 적합합니다. 커널 팀은 언급 한 것처럼 수십만 개의 커밋 이 있기 때문에 여러 차례 증가했습니다 . ~ 30k 커밋의 경우 8 자리 또는 10 자리가 완벽하게 좋습니다.


38
또한 git이것에 관해서는 상당히 똑똑합니다. 약어를 짧게 설정하고 4로 말하면 git가능한 한 많은 해시에 대해 4 자리 숫자를 사용하지만 약어가 고유하지 않다는 것을 알고 있으면 5 이상으로 전환합니다.
twalberg

31
그러나 이것은 물론 Git이 SHA를 인쇄하는 순간에만 적용됩니다. 축약 된 SHA (예 : 로그, 전자 메일, IM 등)를 "저장"하고 나중에이를 사용하여 커밋을 참조하면 더 이상 고유하지 않을 수 있습니다! 7-12 자와 같은 일반적인 길이는 확실하지 않지만 4 또는 5로 내려 가면 수만 개의 새로운 객체 (또는 상황에 따라 커밋)가 생기면 실제로 물릴 수 있습니다.
Nevik Rehnel

140

참고 : git rev-parse --short가장 짧지 만 고유 한 SHA1을 요청할 수 있습니다 .
자세한 내용은 " 일반 해시에서 짧은 해시를 얻을 수 힘내 "

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

예제에서 볼 수 있듯이 SHA1의 길이는 4를 지정하더라도 길이는 5입니다.


큰 리 포지션의 경우 2010 년 이후 7만으로는 충분하지 않으며 Linus Torvalds가 직접 dce9648커밋 합니다 (git 1.7.4.4, 2010 년 10 월) :

기본값 7은 git 개발 초기에 7 개의 16 진수가 많았을 때 발생합니다 (약 2 억 5 천만 + 해시 값 포함).
당시에는 65k 개정판이 많았고 (BK에서 맞닥뜨릴 예정 임) 각 개정판이 약 5-10 개의 새로운 객체 인 경향이 있으므로 백만 개의 객체가 많았습니다.

(BK = 비트 키퍼)

요즘 커널은 가장 큰 git 프로젝트가 아니며 커널조차 약 220k 개정 ( BK 트리보다 훨씬 큼 )이 있으며 우리는 2 백만 개의 객체에 접근하고 있습니다.
그 시점에서, 일곱 16 진수는 여전히 많은 고유이지만, 우리가 객체의 수와 해시 크기 사이의 크기 차이에 대한 두 주문을 얘기 할 때,이 잘립니다 해시 값의 충돌합니다.
더 이상 비현실적이지 않으며 항상 발생합니다.

우리는 모두 비현실적으로 작았 기본 약칭을 증가해야 하고 사람들이 자식 설정 파일에 당 프로젝트 자신의 기본값을 설정할 수있는 방법을 추가 .

core.abbrev

길이 개체 이름을 약자로 설정하십시오.
지정되지 않은 경우 많은 명령이 7 개의 16 진수로 축약되며, 축약 된 오브젝트 이름이 충분히 오랫동안 고유성을 유지하기에 충분하지 않을 수 있습니다.

environment.c:

int minimum_abbrev = 4, default_abbrev = 7;

참고 : marco.m 에 의해 아래언급 된 것처럼 커밋 a71f09f의 동일한 Git 1.7.4.4에서 이름이 변경되었습니다 .core.abbrevLengthcore.abbrev

core.abbrevlength다시 이름 바꾸기core.abbrev

결국 --abbrev=$n명령 행 옵션에 해당 합니다.


더 최근에 Linus는 커밋 e6c587c (Git 2.11, 2016 년 4 분기)에 추가했습니다 :
( Mathieu Moy답변 에서 언급했듯이 )

상당히 초기에는 객체 이름을 7 자리 숫자로 줄이기로 결정했지만 프로젝트가 커짐에 따라 이전에 만들어진 짧은 객체 이름이 더 이상 고유하지 않은 로그 메시지에 기록 될 가능성이 높아지고 있습니다.

현재 Linux 커널 프로젝트에는 11 ~ 12 개의 16 진수가 필요하지만, Git 자체는 객체를 고유하게 식별하기 위해 10 개의 16 진수가 필요하지만, 많은 소규모 프로젝트는 여전히 원래 7- 진수의 기본값으로 괜찮을 수 있습니다. 하나의 크기가 모든 프로젝트에 적합하지는 않습니다.

기본 설정으로 객체 이름을 축약하고 리포지토리에 대해 기본값을 설정하라는 요청이있을 때 리포지토리의 객체 수를 추정하는 메커니즘을 소개합니다. 2^(2N)첫 번째 N 비트로 단축 된 오브젝트 이름을 사용할 때 오브젝트 와의 저장소에서 충돌이 발생할 것으로 예상 함에 따라 저장소의 오브젝트 수를 포괄 할 수있는 충분한 16 진수를 사용하십시오.
단축 이름에 추가 한 각 16 진수 (4 비트)는 저장소에 4 배 (2 비트) 많은 객체를 가질 수 있습니다.

Linus Torvalds ( )의 commit e6c587c (2016 년 10 월 1 일)를 참조하십시오 . 참조 7b5b772 커밋 , 65acfea 커밋 으로 (01 년 10 월 2016) Junio C 하마노 ( ) . (가 합병 - Junio C 하마노 -bb188d0 커밋 2016 03 10 월)torvalds
gitster
gitster

이 새로운 속성 (SHA1 abbrev 값에 대한 합리적인 기본값을 추측)은 Git이 릴리스를 위해 자체 버전 번호를 계산 하는 방법에 직접적인 영향을 미칩니다 .


3
이 대답은 하나의 저장소에서 가장 긴 "단축"해시가 무엇인지 확인하는 방법을 제공합니다 stackoverflow.com/a/32406103/1858225
카일 해변

1
참고 core.abbrevLength로 이름이 바뀌 었습니다 core.abbrev.
marco.m 2016 년

@ marco.m 감사합니다. 이에 따라 답변을 수정했습니다. 그리고 나는 그 새로운 이름을 기록하는 Git 커밋에 링크했습니다 core.abbrev.
VonC

git rev-parse --short=10 --verify HEAD10 문자를 생성하기 위해 실행할 수 있도록 여기에 추가하겠습니다 . 우리는 사용 git log -1 --format=%h했지만 7 문자 만 생성했으며 충돌이 발생했습니다.
grayaii

설명 주셔서 감사합니다, 문서 ( git-scm.com/docs/git-rev-parse )는 오래되었습니다.
André Werlang 1

36

이것을 생일 문제라고합니다.

1/2보다 작은 확률의 경우 충돌 확률은 다음과 같이 추정 할 수 있습니다.

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

여기서 n은 항목 수이고 m은 각 항목의 가능성 수입니다.

16 진 문자열의 가능성은 16 c입니다. 여기서 c는 문자 수입니다.

따라서 8 자 및 30K 커밋

30K ~ = 2 15

~ P = (N 2 ) / (2m) ~ = ((2 15 ) 2 ) / (2 × 16 8 ) 2 = 30 / 2 33 = ⅛

12 자로 늘리기

~ P = (N 2 ) / (2m) ~ = ((2 15 ) 2 ) / (16 * 2 12 ) = 2 30 / 2 (49) = 2 -19


정확히 내가 해결하려고했던 질문, 감사합니다! @Messa의 답변에 연결된 확률 표도 도움이됩니다.
Kyle Chadha

우수, 우리는 이것 외에 다른 것이 필요하지 않습니다. 그것이 무엇 일뿐만 아니라 어떻게되는지 설명하십시오.
workplaylifecycle

13

이 질문에 대한 답은 있지만 수학을 찾는 사람에게는 생일 문제 ( Wikipedia ) 라고 합니다.

N 명 그룹에서 2 명 (또는 그 이상)의 사람들이 같은 날에 생일을 가질 확률이 있습니다. 이는 길이가 X의 동일한 해시 접두사를 갖는 총 N 개의 커밋을 가진 리포지토리에서 2 개 이상의 git 커밋과 유사합니다.

상기 봐 확률 테이블 . 예를 들어 길이가 8 인 해시 16 진 문자열의 경우 리포지토리에 약 9300 개의 항목 (git commit)이있을 때 충돌 가능성은 1 %에 이릅니다. 110 000 커밋의 경우 확률은 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 edition 20에서 토론하고 bb188d00f7을 커밋 합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.