Git이 파일에 SHA1 해시를 할당 할 때이 SHA1은 내용에 따라 파일에 고유합니다.
결과적으로 파일이 한 저장소에서 다른 저장소로 이동하면 파일의 SHA1은 내용이 변경되지 않은 것과 동일하게 유지됩니다.
Git은 SHA1 다이제스트를 어떻게 계산합니까? 압축되지 않은 전체 파일 내용에서 수행됩니까?
SHA1을 Git 외부에 할당하는 것을 모방하고 싶습니다.
Git이 파일에 SHA1 해시를 할당 할 때이 SHA1은 내용에 따라 파일에 고유합니다.
결과적으로 파일이 한 저장소에서 다른 저장소로 이동하면 파일의 SHA1은 내용이 변경되지 않은 것과 동일하게 유지됩니다.
Git은 SHA1 다이제스트를 어떻게 계산합니까? 압축되지 않은 전체 파일 내용에서 수행됩니까?
SHA1을 Git 외부에 할당하는 것을 모방하고 싶습니다.
답변:
다음은 Git이 파일 (또는 Git 용어로 "블롭")에 대한 SHA1을 계산하는 방법입니다.
sha1("blob " + filesize + "\0" + data)
따라서 Git을 설치하지 않고도 쉽게 직접 계산할 수 있습니다. "\ 0"은 2 바이트 문자열이 아닌 NULL 바이트입니다.
예를 들어, 빈 파일의 해시 :
sha1("blob 0\0") = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"
$ touch empty
$ git hash-object empty
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
다른 예시:
sha1("blob 7\0foobar\n") = "323fae03f4606ea9991df8befbb2fca795e648fa"
$ echo "foobar" > foo.txt
$ git hash-object foo.txt
323fae03f4606ea9991df8befbb2fca795e648fa
다음은 Python 구현입니다.
from hashlib import sha1
def githash(data):
s = sha1()
s.update("blob %u\0" % len(data))
s.update(data)
return s.hexdigest()
TypeError: Unicode-objects must be encoded before hashing
하면 첫 번째 s.update()
줄 에서 예외 가 발생 합니다.
s.update(("blob %u\0" % filesize).encode('utf-8'))
해야합니다 TypeError
.
작은 케이크 : 쉘
echo -en "blob ${#CONTENTS}\0$CONTENTS" | sha1sum
echo -en "blob ${#CONTENTS}\0$CONTENTS" | sha1sum
출력 과 비교 하여 git hash-object path-to-file
다른 결과를 낳습니다. 그러나 echo -e ...
후행이있는 경우를 제외하고 올바른 결과를 생성합니다 -
( 후행 문자가 git hash-object
생성 되지 않음 ). 이것이 내가 걱정해야 할 것입니까?
-
은 sha1sum
파일이 아닌 stdin에서 해시를 계산 한 경우 사용됩니다 . 걱정할 것이 없습니다. 에 대한 이상한 것은 -n
에코가 일반적으로 추가하는 줄 바꿈을 억제해야합니다. 우연히 파일에 빈 마지막 줄이 있는데 CONTENTS
변수 에 추가하는 것을 잊었 습니까?
cat file | sha1sum
대신 sha1sum file
더 많은 프로세스와 파이프 를 사용 하는 경우 동일한 출력을 얻을 수 있습니다
git이 설치되어 있지 않은 경우 bash 쉘 함수를 사용하여 쉽게 계산할 수 있습니다.
git_id () { printf 'blob %s\0' "$(ls -l "$1" | awk '{print $5;}')" | cat - "$1" | sha1sum | awk '{print $1}'; }
(stat --printf="blob %s\0" "$1"; cat "$1") | sha1sum -b | cut -d" " -f1
.
git-hash-object 의 매뉴얼 페이지를 살펴보십시오 . 특정 파일의 git 해시를 계산하는 데 사용할 수 있습니다. 내가 생각하는 그 자식 피드 더 해시 알고리즘으로 파일의 내용 만 이상, 그러나 나는 확실히 알고하지 않으며,이 여분의 데이터에 공급 않는 경우에, 나는 그것이 무엇인지 알지 못한다.
/// Calculates the SHA1 for a given string
let calcSHA1 (text:string) =
text
|> System.Text.Encoding.ASCII.GetBytes
|> (new System.Security.Cryptography.SHA1CryptoServiceProvider()).ComputeHash
|> Array.fold (fun acc e ->
let t = System.Convert.ToString(e, 16)
if t.Length = 1 then acc + "0" + t else acc + t)
""
/// Calculates the SHA1 like git
let calcGitSHA1 (text:string) =
let s = text.Replace("\r\n","\n")
sprintf "blob %d%c%s" (s.Length) (char 0) s
|> calcSHA1
이것은 F #의 솔루션입니다.
완전한 Python3 구현 :
import os
from hashlib import sha1
def hashfile(filepath):
filesize_bytes = os.path.getsize(filepath)
s = sha1()
s.update(b"blob %u\0" % filesize_bytes)
with open(filepath, 'rb') as f:
s.update(f.read())
return s.hexdigest()
펄에서 :
#!/usr/bin/env perl
use Digest::SHA1;
my $content = do { local $/ = undef; <> };
print Digest::SHA1->new->add('blob '.length($content)."\0".$content)->hexdigest(), "\n";
쉘 명령으로 :
perl -MDigest::SHA1 -E '$/=undef;$_=<>;say Digest::SHA1->new->add("blob ".length()."\0".$_)->hexdigest' < file
그리고 Perl에서 ( http://search.cpan.org/dist/Git-PurePerl/의 Git :: PurePerl 참조 )
use strict;
use warnings;
use Digest::SHA1;
my @input = <>;
my $content = join("", @input);
my $git_blob = 'blob' . ' ' . length($content) . "\0" . $content;
my $sha1 = Digest::SHA1->new();
$sha1->add($git_blob);
print $sha1->hexdigest();
자바 스크립트에서
const crypto = require('crypto')
const bytes = require('utf8-bytes')
function sha1(data) {
const shasum = crypto.createHash('sha1')
shasum.update(data)
return shasum.digest('hex')
}
function shaGit(data) {
const total_bytes = bytes(data).length
return sha1(`blob ${total_bytes}\0${data}`)
}
분명히 Git은 해시되기 전에 데이터 끝에 줄 바꿈 문자를 추가한다는 점에 주목하는 것이 흥미 롭습니다. "Hello World!"이외의 것을 포함하는 파일 980a0d5의 블롭 해시를 얻습니다.
$ php -r 'echo sha1("blob 13" . chr(0) . "Hello World!\n") , PHP_EOL;'
git hash-object
. 일을하는 것이 있습니다 echo "Hello World!" | git hash-object --stdin
주는 980a0d5...
사용이 동안 echo -n
의 해시주는 c57eff5...
대신합니다.