programing tip

git은 파일 해시를 어떻게 계산합니까?

itbloger 2020. 7. 14. 20:53
반응형

git은 파일 해시를 어떻게 계산합니까?


(에 의해 반환되는 트리 객체에 저장된 SHA1 해시 git ls-tree()에 의해 반환되는 파일 내용의 SHA1 해시 일치하지 않습니다 sha1sum)

$ git cat-file blob 4716ca912495c805b94a88ef6dc3fb4aff46bf3c | sha1sum
de20247992af0f949ae8df4fa9a37e4a03d7063e  -

git은 파일 해시를 어떻게 계산합니까? 해시를 계산하기 전에 내용을 압축합니까?


힘내는 개체 앞에 "blob", 길이 (사람이 읽을 수있는 정수), NUL 문자

$ echo -e 'blob 14\0Hello, World!' | shasum 8ab686eafeb1f44702738c8b0f24f2567c36da6d

출처 : http://alblue.bandlem.com/2011/08/git-tip-of-week-objects.html


나는 답변을 확장 @Leif Gruenwoldt하고 참조 에있는 내용을 자세히 설명 하고 있습니다.@Leif Gruenwoldt

스스로 해..

  • 1 단계. 저장소에 빈 텍스트 문서 (이름은 중요하지 않음)를 작성하십시오.
  • 2 단계. 문서 준비 및 커밋
  • 3 단계. Blob의 해시를 실행하여 식별 git ls-tree HEAD
  • 단계 4. Blob의 해시 찾기 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
  • 5 단계. 놀라움을 피하고 아래 내용을 읽으십시오

GIT는 커밋 해시를 계산하는 방법

    Commit Hash (SHA1) = SHA1("blob " + <size_of_file> + "\0" + <contents_of_file>)

텍스트 blob⎵는 상수 접두사이며 \0상수이며 NULL문자입니다. <size_of_file><contents_of_file>파일에 따라 달라집니다.

참조 : git commit 객체의 파일 형식은 무엇입니까?

그리고 모든 사람들입니다!

하지만 기다려! , 당신은이 통지 않았다 <filename>해시 계산에 사용되는 매개 변수가 아니다? 내용이 생성 된 날짜와 시간 및 이름과 동일하지 않은 경우 두 파일의 해시가 동일 할 수 있습니다. 이것이 Git이 다른 버전 제어 시스템보다 이동 및 이름 바꾸기를 처리하는 이유 중 하나입니다.

스스로해라 (Ext)

  • 6 단계. filename같은 디렉토리에 다른 빈 파일을 만듭니다.
  • 7 단계. 두 파일의 해시를 비교하십시오.

노트 :

링크는 tree객체가 해시되는 방법을 언급하지 않습니다 . 나는 알고리즘과 매개 변수를 확신하지 못하지만 내 관찰에서 아마도 포함 된 모든 blobstrees( 해시 해시)를 기반으로 해시를 계산합니다.


git hash-object

테스트 방법을 확인하는 빠른 방법입니다.

s='abc'
printf "$s" | git hash-object --stdin
printf "blob $(printf "$s" | wc -c)\0$s" | sha1sum

산출:

f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f
f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f  -

sha1sumGNU Coreutils는 어디에 있습니다.

그런 다음 각 객체 유형의 형식을 이해합니다. 우리는 이미 사소한 것을 다루었 blob습니다.


Based on Leif Gruenwoldt answer, here is a shell function substitute to git hash-object :

git-hash-object () { # substitute when the `git` command is not available
    local type=blob
    [ "$1" = "-t" ] && shift && type=$1 && shift
    # depending on eol/autocrlf settings, you may want to substitute CRLFs by LFs
    # by using `perl -pe 's/\r$//g'` instead of `cat` in the next 2 commands
    local size=$(cat $1 | wc -c | sed 's/ .*$//')
    ( echo -en "$type $size\0"; cat "$1" ) | sha1sum | sed 's/ .*$//'
}

Test:

$ echo 'Hello, World!' > test.txt
$ git hash-object test.txt
8ab686eafeb1f44702738c8b0f24f2567c36da6d
$ git-hash-object test.txt
8ab686eafeb1f44702738c8b0f24f2567c36da6d

I needed this for some unit tests in Python 3 so thought I'd leave it here.

def git_blob_hash(data):
    if isinstance(data, str):
        data = data.encode()
    data = b'blob ' + str(len(data)).encode() + b'\0' + data
    h = hashlib.sha1()
    h.update(data)
    return h.hexdigest()

I stick to \n line endings everywhere but in some circumstances Git might also be changing your line endings before calculating this hash so you may need a .replace('\r\n', '\n') in there too.

참고URL : https://stackoverflow.com/questions/7225313/how-does-git-compute-file-hashes

반응형