Skróty SHA1 przechowywane w obiektach drzewa (zwrócone przez git ls-tree
) nie pasują do skrótów SHA1 zawartości pliku (zwróconych przez sha1sum
)
$ git cat-file blob 4716ca912495c805b94a88ef6dc3fb4aff46bf3c | sha1sum
de20247992af0f949ae8df4fa9a37e4a03d7063e -
W jaki sposób git oblicza skróty plików? Czy kompresuje zawartość przed obliczeniem skrótu?
Odpowiedzi:
$ echo -e 'blob 14\0Hello, World!' | shasum 8ab686eafeb1f44702738c8b0f24f2567c36da6d
Źródło: http://alblue.bandlem.com/2011/08/git-tip-of-week-objects.html
źródło
echo 'Hello, World!' | git hash-object --stdin
. Opcjonalnie możesz określić,--no-filters
aby upewnić się, że konwersja crlf nie nastąpi, lub określić,--path=somethi.ng
aby git używał filtru określonego przezgitattributes
(również @ user420667). I-w
rzeczywiście złożyć blob.git/objects
(jeśli są w repo git).echo -e 'blob 16\0Hello, \r\nWorld!' | shasum
==echo -e 'Hello, \r\nWorld!' | git hash-object --stdin --no-filters
i będzie również równoważne z\n
i 15.echo
dołącza znak nowej linii do wyjścia, który jest również przekazywany do git. Dlatego ma 14 znaków. Aby użyć echa bez znaku nowej linii, napiszecho -n 'Hello, World!'
Rozszerzam tylko odpowiedź
@Leif Gruenwoldt
i szczegółowo opisuję, co jest w referencji dostarczonej przez@Leif Gruenwoldt
Zrób to sam..
Jak GIT oblicza skróty zatwierdzeń
Tekst
blob⎵
jest stałym przedrostkiem, a\0
także jest stały i jestNULL
znakiem.<size_of_file>
I<contents_of_file>
różnią się w zależności od pliku.Zobacz: Jaki jest format pliku obiektu git commit?
I to wszystko ludzie!
Ale poczekaj! , czy zauważyłeś, że
<filename>
parametr nie jest używany do obliczenia skrótu? Dwa pliki mogą potencjalnie mieć ten sam skrót, jeśli ich zawartość jest taka sama, niezależnie od daty i godziny ich utworzenia oraz nazwy. Jest to jeden z powodów, dla których Git radzi sobie z przenoszeniem i zmianą nazw lepiej niż inne systemy kontroli wersji.Zrób to sam (rozszerzenie)
Uwaga:
Odnośnik nie wspomina o tym, jak
tree
obiekt jest zahaszowany. Nie jestem pewien algorytmu i parametrów, ale z moich obserwacji prawdopodobnie wylicza hash na podstawie wszystkichblobs
itrees
(prawdopodobnie ich hashów), które zawieraźródło
SHA1("blob" + <size_of_file>
- czy między blobem a rozmiarem jest dodatkowa spacja? Czy rozmiar jest dziesiętny? Czy ma przedrostek zerowy?git hash-object
To szybki sposób na zweryfikowanie metody testowej:
Wynik:
gdzie
sha1sum
jest w GNU Coreutils.Następnie sprowadza się do zrozumienia formatu każdego typu obiektu. Już omówiliśmy trywialne
blob
, oto inne:źródło
$(printf "\0$s" | wc -c)
. Zwróć uwagę na dodany pusty znak. Oznacza to, że jeśli napisem jest „abc” z dodanym pustym znakiem na początku, długość dałoby 4, a nie 3. Następnie wyniki z sha1sum pasują do git hash-object.Opierając się na odpowiedzi Leifa Gruenwoldta , oto substytut funkcji powłoki
git hash-object
:Test:
źródło
Potrzebowałem tego do niektórych testów jednostkowych w Pythonie 3, więc pomyślałem, że zostawię to tutaj.
\n
Wszędzie trzymam się końcówek linii, ale w niektórych okolicznościach Git może również zmieniać zakończenia linii przed obliczeniem tego skrótu, więc możesz.replace('\r\n', '\n')
tam również potrzebować .źródło