Jak rozumiem, kiedy Git przypisuje skrót SHA1 do pliku, ten SHA1 jest unikalny dla pliku na podstawie jego zawartości.
W rezultacie, jeśli plik jest przenoszony z jednego repozytorium do drugiego, SHA1 dla pliku pozostaje taka sama, ponieważ jego zawartość nie uległa zmianie.
Jak Git oblicza skrót SHA1? Czy robi to na pełnej nieskompresowanej zawartości pliku?
Chciałbym emulować przypisywanie SHA1 poza Git.
Odpowiedzi:
Oto jak Git oblicza SHA1 dla pliku (lub, mówiąc językiem Gita, „bloba”):
Możesz więc łatwo obliczyć to samodzielnie bez instalowania Git. Zauważ, że „\ 0” jest bajtem zerowym, a nie dwuznakowym ciągiem.
Na przykład hash pustego pliku:
Inny przykład:
Oto implementacja Pythona:
źródło
TypeError: Unicode-objects must be encoded before hashing
wyjątek w pierwszyms.update()
wierszu.s.update(("blob %u\0" % filesize).encode('utf-8'))
aby uniknąćTypeError
.Trochę goodie: w skorupce
źródło
echo -en "blob ${#CONTENTS}\0$CONTENTS" | sha1sum
do wynikówgit hash-object path-to-file
i dają różne wyniki. Jednakecho -e ...
daje prawidłowe wyniki, z wyjątkiem tego, że występuje końcowy-
( niegit hash-object
tworzy żadnych znaków końcowych). Czy to jest coś, o co powinienem się martwić?-
jest używany przez,sha1sum
jeśli obliczył skrót ze standardowego wejścia, a nie z pliku. Nie ma się o co martwić. Dziwna rzecz-n
, która powinna zablokować znak nowej linii zwykle dodawany przez echo. Czy Twój plik ma przypadkiem pustą ostatnią linię, której zapomniałeś dodać doCONTENTS
zmiennej?cat file | sha1sum
zamiastsha1sum file
(chociaż więcej procesów iJeśli nie masz zainstalowanego gita, możesz utworzyć funkcję powłoki bash, aby ją łatwo obliczyć.
źródło
(stat --printf="blob %s\0" "$1"; cat "$1") | sha1sum -b | cut -d" " -f1
.Spójrz na stronę podręcznika systemowego dla git-hash-object . Możesz go użyć do obliczenia skrótu git dowolnego konkretnego pliku. Myślę , że git przekazuje do algorytmu haszującego coś więcej niż tylko zawartość pliku, ale nie wiem na pewno, a jeśli dostarcza dodatkowe dane, nie wiem, co to jest.
źródło
To jest rozwiązanie w języku F #.
źródło
Pełna implementacja Python3:
źródło
W Perlu:
Jako polecenie powłoki:
źródło
Oraz w Perlu (zobacz także Git :: PurePerl na http://search.cpan.org/dist/Git-PurePerl/ )
źródło
Używając Rubiego, możesz zrobić coś takiego:
źródło
Mały skrypt Bash, który powinien dawać identyczne dane wyjściowe do
git hash-object
:źródło
W JavaScript
źródło
Warto zauważyć, że oczywiście Git dodaje znak nowej linii na końcu danych, zanim zostaną one zaszyfrowane. Plik zawierający tylko „Hello World!” pobiera skrót obiektu blob o wartości 980a0d5 ..., który jest taki sam jak ten:
źródło
git hash-object
. Zauważ, że robienieecho "Hello World!" | git hash-object --stdin
daje980a0d5...
, podczas gdy używanieecho -n
dajec57eff5...
zamiast tego hash of .