source

Git이 없는 파일에 Git SHA1을 할당하는 방법은 무엇입니까?

ittop 2023. 8. 26. 00:04
반응형

Git이 없는 파일에 Git SHA1을 할당하는 방법은 무엇입니까?

Git가 파일에 SHA1 해시를 할당할 때 이 SHA1은 내용에 따라 파일에 고유합니다.

따라서 파일이 한 리포지토리에서 다른 리포지토리로 이동하는 경우 파일의 SHA1은 내용이 변경되지 않은 상태로 유지됩니다.

Git는 SHA1 다이제스트를 어떻게 계산합니까?압축되지 않은 전체 파일 내용에 적용됩니까?

저는 Git 외부에 SHA1을 할당하는 것을 본받고 싶습니다.

다음은 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()

작은 구디: 껍질 속에.

echo -en "blob ${#CONTENTS}\0$CONTENTS" | sha1sum

git가 설치되어 있지 않으면 bash shell 함수를 만들어 쉽게 계산할 수 있습니다.

git_id () { printf 'blob %s\0' "$(ls -l "$1" | awk '{print $5;}')" | cat - "$1" | sha1sum | awk '{print $1}'; }

깃대가리개에 대한 man 페이지를 보세요.이를 사용하여 특정 파일의 Git 해시를 계산할 수 있습니다.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() 

Perl에서:

#!/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(Git:: 참조)에서도 확인할 수 있습니다.퓨어펄(http://search.cpan.org/dist/Git-PurePerl/ )

use strict;
use warnings;
use Digest::SHA1;

my @input = &lt;&gt;;

my $content = join("", @input);

my $git_blob = 'blob' . ' ' . length($content) . "\0" . $content;

my $sha1 = Digest::SHA1->new();

$sha1->add($git_blob);

print $sha1->hexdigest();

Ruby를 사용하면 다음과 같은 작업을 수행할 수 있습니다.

require 'digest/sha1'

def git_hash(file)
  data = File.read(file)
  size = data.bytesize.to_s
  Digest::SHA1.hexdigest('blob ' + size + "\0" + data)
end

동일한 출력을 생성해야 하는 작은 Bash 스크립트git hash-object:

#!/bin/sh
( 
    echo -en 'blob '"$(stat -c%s "$1")"'\0';
    cat "$1" 
) | sha1sum | cut -d\  -f 1

파일에도 동일하게 적용할 수 있습니다.

$ echo "foobar" > foo.txt
$ echo "$(cat foo.txt)"|(read f; echo -en "blob "$((${#f}+1))"\0$f\n" )|openssl sha1
323fae03f4606ea9991df8befbb2fca795e648fa

자바스크립트에서

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;'

언급URL : https://stackoverflow.com/questions/552659/how-to-assign-a-git-sha1s-to-a-file-without-git

반응형