Biorąc pod uwagę skrót obiektu blob, czy istnieje sposób na uzyskanie listy zatwierdzeń, które mają ten obiekt blob w swoim drzewie?
git
version-control
Tylko czytać
źródło
źródło
git hash-object
orsha1("blob " + filesize + "\0" + data)
, a nie po prostu suma sha1 zawartości obiektu blob.git log --follow filepath
(i użyć tego, aby przyspieszyć rozwiązanie Arystotelesa, jeśli chcesz).~/.bin
i nazwij gogit-find-object
. Możesz go następnie używać zgit find-object
.git describe <hash>
: Zobacz moją odpowiedź poniżej .Odpowiedzi:
Oba poniższe skrypty przyjmują wartość SHA1 obiektu BLOB jako pierwszy argument, a po nim opcjonalnie wszystkie
git log
zrozumiałe argumenty . Na przykład,--all
aby przeszukać wszystkie gałęzie zamiast tylko bieżącej, lub-g
przeszukać reflog, lub cokolwiek innego, co chcesz.Oto skrypt powłoki - krótki i słodki, ale powolny:
I zoptymalizowana wersja w Perlu, wciąż dość krótka, ale znacznie szybsza:
źródło
git rev-parse --verify $theprefix
my $blob_arg = shift; open my $rev_parse, '-|', git => 'rev-parse' => '--verify', $blob_arg or die "Couldn't open pipe to git-rev-parse: $!\n"; my $obj_name = <$rev_parse>; chomp $obj_name; close $rev_parse or die "Couldn't expand passed blob.\n"; $obj_name eq $blob_arg or print "(full blob is $obj_name)\n";
obj_name="$1" shift git log --all --pretty=format:'%T %h %s %n' -- "$@" | while read tree commit cdate subject ; do if [ -z $tree ] ; then continue fi if git ls-tree -r $tree | grep -q "$obj_name" ; then echo "$cdate $commit $@ $subject" fi done
--all
jako dodatkowy argument. (Znalezienie wszystkich zatwierdzeń w całym repozytorium jest ważne w przypadkach takich jak usuwanie dużego pliku z historii repozytorium ).Niestety skrypty były dla mnie trochę powolne, więc musiałem trochę zoptymalizować. Na szczęście miałem nie tylko hash, ale także ścieżkę do pliku.
źródło
<hash>
podaną wartość<path>
, wtedy usunięcie<path>
argumentu zgit log
will zadziała. Pierwszym zwróconym wynikiem jest poszukiwane zatwierdzenie.Z Git 2.16 (Q1 2018)
git describe
byłoby dobrym rozwiązaniem, ponieważ nauczono go kopać głębiej drzewa, aby znaleźć obiekt,<commit-ish>:<path>
który odnosi się do danego obiektu typu blob.Zobacz zatwierdzenie 644eb60 , zatwierdzenie 4dbc59a , zatwierdzenie cdaed0c , zatwierdzenie c87b653 , zatwierdzenie ce5b6f9 (16 listopada 2017) i zatwierdzenie 91904f5 , zatwierdzenie 2deda00 (02 listopada 2017) autorstwa Stefana Bellera (
stefanbeller
) .(Scalone przez Junio C Hamano -
gitster
- w zatwierdzeniu 556de1a , 28 grudnia 2017)Oznacza to, że
git describe
strona podręcznika dodaje do celów tego polecenia:Ale:
źródło
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | awk '/^blob/ {print substr($0,6)}' | sort --numeric-sort --key=2 -r | head -n 20
, który zwraca 20 największych obiektów blob. Następnie możesz przekazać identyfikator obiektu BLOB z powyższego wyjścia dogit describe
. Działał jak urok! Dzięki!Pomyślałem, że byłoby to ogólnie przydatne, więc napisałem mały skrypt w Perlu, aby to zrobić:
Umieszczę to na githubie, kiedy wrócę do domu wieczorem.
Aktualizacja: Wygląda na to, że ktoś już to zrobił . Ten używa tego samego ogólnego pomysłu, ale szczegóły są inne, a implementacja jest znacznie krótsza. Nie wiem, co byłoby szybsze, ale wydajność prawdopodobnie nie jest tutaj problemem!
Aktualizacja 2: Bez względu na to, co jest warte, moja implementacja jest szybsza o rząd wielkości, szczególnie w przypadku dużego repozytorium. To
git ls-tree -r
naprawdę boli.Aktualizacja 3: Należy zauważyć, że moje uwagi dotyczące wydajności powyżej odnoszą się do implementacji, do której dołączyłem powyżej w pierwszej aktualizacji. Realizacja Arystotelesa działa porównywalnie z moją. Więcej szczegółów w komentarzach dla ciekawskich.
źródło
git rev-parse $commit^{}
Chociaż pierwotne pytanie o to nie pyta, myślę, że warto również sprawdzić obszar przemieszczania, aby zobaczyć, czy odwołuje się do obiektu blob. Zmodyfikowałem oryginalny skrypt basha, aby to zrobić, i znalazłem odwołanie do uszkodzonego obiektu blob w moim repozytorium:
źródło
Więc ... Musiałem znaleźć wszystkie pliki przekraczające podany limit w repozytorium o rozmiarze ponad 8 GB, z ponad 108 000 wersji. Zaadaptowałem skrypt Perla Arystotelesa wraz ze skryptem rubinowym, który napisałem, aby osiągnąć to kompletne rozwiązanie.
Po pierwsze
git gc
- zrób to, aby upewnić się, że wszystkie obiekty znajdują się w plikach paczek - nie skanujemy obiektów, których nie ma w plikach paczek.Następnie Uruchom ten skrypt, aby zlokalizować wszystkie obiekty blob w bajtach CUTOFF_SIZE. Przechwyć dane wyjściowe do pliku takiego jak „large-blobs.log”
Następnie edytuj plik, aby usunąć wszystkie obiekty blob, na które nie czekasz, i bity INPUT_THREAD u góry. kiedy masz już tylko linie dla sha1, które chcesz znaleźć, uruchom następujący skrypt w ten sposób:
Gdzie
git-find-blob
skrypt jest poniżej.Wynik będzie wyglądał następująco:
I tak dalej. Wyświetlone zostanie każde zatwierdzenie zawierające duży plik w swoim drzewie. jeśli usuniesz
grep
linie zaczynające się od tabulatora,uniq
będziesz mieć listę wszystkich ścieżek, które możesz usunąć za pomocą filtra lub możesz zrobić coś bardziej skomplikowanego.Powtórzę: ten proces przebiegał pomyślnie na repozytorium 10 GB ze 108 000 zatwierdzeń. Trwało to znacznie dłużej niż przewidywałem, gdy działałem na dużej liczbie plamek, ale ponad 10 godzin będę musiał sprawdzić, czy zapamiętywanie działa ...
źródło
-- --all
. (Znalezienie wszystkich zatwierdzeń w całym repozytorium jest ważne w przypadkach takich jak dokładne usunięcie dużego pliku z historii repozytorium ).Ponadto
git describe
wspomniałem o tym w mojej poprzedniej odpowiedzi ,git log
agit diff
teraz również korzysta z opcji „--find-object=<object-id>
” ograniczającej wyniki do zmian dotyczących nazwanego obiektu.To jest w Git 2.16.x / 2.17 (Q1 2018)
Zobacz commit 4d8c51a , commit 5e50525 , commit 15af58c , commit cf63051 , commit c1ddc46 , commit 929ed70 (4 stycznia 2018) autor: Stefan Beller (
stefanbeller
) .(Scalone przez Junio C Hamano -
gitster
- w zatwierdzeniu c0d75f0 , 23 stycznia 2018 r.)źródło