prosource

주어진 코드베이스의 변화를 고유하게 식별하기 위해 *일반적으로* 필요한 Gitsha는 얼마나 됩니까?

probook 2023. 5. 23. 22:00
반응형

주어진 코드베이스의 변화를 고유하게 식별하기 위해 *일반적으로* 필요한 Gitsha는 얼마나 됩니까?

예를 들어, Git 저장소의 커밋을 위해 디렉터리 이름이 지정된 디렉터리 구조를 만들고 눈에 피가 나지 않을 정도로 짧지만 충돌 가능성은 무시할 수 있을 정도로 길기를 원한다면 일반적으로 얼마나 많은 SHA 하위 문자열이 필요합니까?

이러한 변화를 고유하게 식별하고 싶다고 가정해 보겠습니다. https://github.com/wycats/handlebars.js/commit/e62999f9ece7d9218b9768a908f8df9c11d7e920

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

하지만 저는 그것이 위험하다고 생각합니다.하지만 2년에 걸쳐 3만 개의 코드베이스가 변경될 수 있다고 가정하면, 8자를 사용하면 충돌 가능성이 얼마나 됩니까? 12자? 일반적으로 이런 종류의 것에 허용되는 숫자가 있습니까?

이 질문은 Pro Git 책의 7장에서 실제로 답변되었습니다.

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

짧은 SHA의 경우 7자리 숫자가 Git 기본값이므로 대부분의 프로젝트에서 괜찮습니다.커널 팀은 수십만 개의 커밋을 가지고 있기 때문에 언급한 것처럼 몇 배로 커밋했습니다.따라서 30,000개의 커밋에 대해서는 8자리 또는 10자리가 완벽하게 좋습니다.

참고: 가장 짧고 고유한 SHA1을 요청할 수 있습니다.
"일반 해시에서 짧은 해시 가져오기"를 참조하십시오.

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

제 예에서 볼 수 있듯이 SHA1의 길이는 4로 지정해도 5입니다.


빅 저장소의 경우 2010년 이후 7개로는 충분하지 않으며, Linus Torvalds가 직접 commit 9648(git 1.7.4.4, 2010년 10월):

기본값 7은 7자리의 16진수가 많았을 때(약 2억 5천만 개 이상의 해시 값 포함) 상당히 초기의 비트 개발에서 나온 것입니다.
당시 저는 65,000개의 리비전이 많은 것으로 생각했습니다(BK에서 다루려고 했던 것입니다). 그리고 각 리비전은 약 5-10개의 새로운 객체인 경향이 있기 때문에 100만개의 객체가 큰 숫자였습니다.

(BK = 비트 키퍼)

요즘 커널은 가장 큰 git 프로젝트도 아니며 커널에도 약 220k의 수정사항이 있으며(지금까지 BK 트리보다 훨씬 더 큽니다), 우리는 2백만 개의 객체에 접근하고 있습니다.
그 시점에서, 7자리 16진수는 여전히 많은 숫자에 대해 고유하지만, 개체 수와 해시 크기 간의 두 자릿수 차이에 대해 이야기하면 잘린 해시 값에서 충돌이 발생합니다.
그것은 더 이상 비현실적이지도 않습니다. 항상 일어나는 일입니다.

우리 둘 다 비현실적으로 작았던 기본 약어를 늘리고 사람들이 git 구성 파일에서 프로젝트별 기본값을 설정할 수 있는 방법을 추가해야 합니다.

core.abbrev

개체 이름의 약어 길이를 설정합니다.
지정되지 않은 경우 대부분의 명령은 7자리 16진수로 단축되며, 이는 생략된 개체 이름이 충분히 오랫동안 고유하게 유지되기에 충분하지 않을 수 있습니다.

environment.c:

int minimum_abbrev = 4, default_abbrev = 7;

참고: 아래 marco.m이 언급한 바와 같이,core.abbrevLength에서 이름이 변경되었습니다.core.abbrev71f09f를 커밋하는 동일한 Git 1.7.4.4에서.

이름 바꾸기core.abbrevlength로 돌아가다.core.abbrev

은 에해합니다당에 합니다.--abbrev=$n명령줄 옵션을 선택합니다.


보다 최근에 라이너스는 commit6c587c(Git 2.11, 2016년 4분기)에 다음과 같이 추가했습니다.
(마티외 모이의 답변에서 언급한 바와 같이)

꽤 초기에는 개체 이름을 7자리로 줄이기로 했습니다. 하지만 프로젝트가 성장함에 따라 이전에 만들어진 짧은 개체 이름이 더 이상 고유하지 않게 로그 메시지에 기록되는 경우가 점점 더 많아지고 있습니다.

현재 리눅스 커널 프로젝트는 11-12개의 16진수가 필요한 반면 Git 자체는 그들이 가진 객체를 고유하게 식별하기 위해 10개의 16진수가 필요합니다. 반면 많은 작은 프로젝트는 원래 7-16진수 기본값으로 여전히 문제가 없을 수 있습니다.단일 크기는 모든 프로젝트에 적합하지 않습니다.

첫 번째 요청 시 저장소의 개체 수를 추정하여 개체 이름을 기본 설정으로 축약하고 저장소에 대한 정상적인 기본값을 지정하는 메커니즘을 소개합니다.이 발생할 것이라는 예상을 바탕으로 합니다.2^(2N)개체 이름을 처음 N비트로 줄인 경우 저장소에 있는 개체 수를 포함할 수 있는 충분한 수의 16진수를 사용합니다.
단축된 이름에 16진수(4비트)를 추가하면 저장소에 있는 개체 수의 4배(2비트)를 가질 수 있습니다.

Linus Torvalds()torvaldscommit6c587c(2016년 10월 1일)를 참조하십시오.
커밋 7b5b772, 커밋 65acfea (2016년 10월 1일) 참조.gitster
(주니오 C 하마노에 의해 합병 -- -- 2016년 10월 3일 커밋 bb188d0에서)

새 속성(SHA1 약어 값에 대한 합리적인 기본값 추정)은 Git가 릴리스할 자체 버전 번호를 계산하는 방법에 직접적인 영향을 미칩니다.

이것은 생일 문제로 알려져 있습니다.

1/2 미만의 확률에 대해 충돌 확률은 다음과 같이 근사할 수 있습니다.

p ~=(n2)/(2m)

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

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

그래서 8개의 캐릭터와 30,000개의 커밋에 대해.

30K ~ = 215

p ~ = (n2)/ (2m) ~ = ((215)/(228*1630) = 233/2 = ⅛

12자로 늘리기

p ~= (n2)/(2m) ~= ((2)/(2215*1612) = 230/249 = 2-19

이 질문은 답을 얻었지만, 뒤에 있는 수학을 찾는 사람들을 위해, 그것은 생일 문제(위키피디아)라고 불립니다.

이는 N인 그룹에서 2명(또는 그 이상)의 사람들이 한 해에 같은 날에 생일을 맞이할 확률에 관한 것입니다.이는 길이 X의 동일한 해시 접두사를 가진 총 N개의 커밋을 가진 저장소에서 2개 이상의 Git 커밋을 갖는 것과 유사합니다.

확률 표를 봅니다.예를 들어 길이가 8인 해시 16진수 문자열의 경우 리포지토리에 약 9300개의 항목(깃 커밋)만 있을 때 충돌이 발생할 확률이 1%에 도달합니다.110,000 커밋의 경우 확률은 75%입니다.그러나 길이가 12인 해시 16진수 문자열이 있는 경우 100,000 커밋에서 충돌할 확률은 0.1% 미만입니다.

2 2식별자에 것입니다(예: Git 전 2.11(또 2.12?).에는 짧은 식별자에 사용되는 문자 수를 조정하는 기능(예:git log --oneline를로 표시합니다. 프로젝트의 크기로 표시됩니다.일단 당신이 Git의 그런 버전을 사용하면, 당신의 질문에 대한 대답은 "Git이 당신에게 주는 길이를 선택하는 것입니다.git log --oneline충분히 안전합니다."

자세한 내용은 Git Rev News 20판 및 commit bb188d00f7의 "core.abbrev"? 토론에 대한 기본값 변경을 참조하십시오.

언급URL : https://stackoverflow.com/questions/18134627/how-much-of-a-git-sha-is-generally-considered-necessary-to-uniquely-identify-a

반응형