Który commit ma ten blob?

149

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?

Tylko czytać
źródło
2
„Hash of a blob” to zwracany przez git hash-objector sha1("blob " + filesize + "\0" + data), a nie po prostu suma sha1 zawartości obiektu blob.
Ivan Hamilton,
1
Początkowo myślałem, że to pytanie pasuje do mojego pytania, ale wydaje się, że nie. Chcę poznać jedyne zatwierdzenie, które jako pierwsze wprowadziło ten obiekt blob do repozytorium.
Jesse Glick
Jeśli znasz ścieżkę do pliku, możesz użyć git log --follow filepath(i użyć tego, aby przyspieszyć rozwiązanie Arystotelesa, jeśli chcesz).
Zaz
ProTip ™: Umieść jeden z belew skryptów ~/.bini nazwij go git-find-object. Możesz go następnie używać z git find-object.
Zaz
1
Uwaga: W przypadku Git 2.16 (Q1 2018) możesz po prostu rozważyć git describe <hash>: Zobacz moją odpowiedź poniżej .
VonC

Odpowiedzi:

107

Oba poniższe skrypty przyjmują wartość SHA1 obiektu BLOB jako pierwszy argument, a po nim opcjonalnie wszystkie git logzrozumiałe argumenty . Na przykład, --allaby przeszukać wszystkie gałęzie zamiast tylko bieżącej, lub -gprzeszukać reflog, lub cokolwiek innego, co chcesz.

Oto skrypt powłoki - krótki i słodki, ale powolny:

#!/bin/sh
obj_name="$1"
shift
git log "$@" --pretty=format:'%T %h %s' \
| while read tree commit subject ; do
    if git ls-tree -r $tree | grep -q "$obj_name" ; then
        echo $commit "$subject"
    fi
done

I zoptymalizowana wersja w Perlu, wciąż dość krótka, ale znacznie szybsza:

#!/usr/bin/perl
use 5.008;
use strict;
use Memoize;

my $obj_name;

sub check_tree {
    my ( $tree ) = @_;
    my @subtree;

    {
        open my $ls_tree, '-|', git => 'ls-tree' => $tree
            or die "Couldn't open pipe to git-ls-tree: $!\n";

        while ( <$ls_tree> ) {
            /\A[0-7]{6} (\S+) (\S+)/
                or die "unexpected git-ls-tree output";
            return 1 if $2 eq $obj_name;
            push @subtree, $2 if $1 eq 'tree';
        }
    }

    check_tree( $_ ) && return 1 for @subtree;

    return;
}

memoize 'check_tree';

die "usage: git-find-blob <blob> [<git-log arguments ...>]\n"
    if not @ARGV;

my $obj_short = shift @ARGV;
$obj_name = do {
    local $ENV{'OBJ_NAME'} = $obj_short;
     `git rev-parse --verify \$OBJ_NAME`;
} or die "Couldn't parse $obj_short: $!\n";
chomp $obj_name;

open my $log, '-|', git => log => @ARGV, '--pretty=format:%T %h %s'
    or die "Couldn't open pipe to git-log: $!\n";

while ( <$log> ) {
    chomp;
    my ( $tree, $commit, $subject ) = split " ", $_, 3;
    print "$commit $subject\n" if check_tree( $tree );
}
Arystoteles Pagaltzis
źródło
8
FYI musisz użyć pełnego SHA obiektu blob. Prefiks, nawet jeśli jest unikalny, nie będzie działał. Aby uzyskać pełny SHA z prefiksu, możesz użyćgit rev-parse --verify $theprefix
John Douthat
1
Dzięki @JohnDouthat za ten komentarz. Oto jak włączyć to do powyższego skryptu (przepraszam za wstawianie w komentarzach): 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";
Ingo Karkat
Może być błąd w skrypcie górnej powłoki. Pętla while jest wykonywana tylko wtedy, gdy jest więcej wierszy do przeczytania iz jakiegoś powodu git log nie umieszcza końcowego pliku crlf na końcu. Musiałem dodać nowy wiersz i zignorować puste wiersze. 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
Mixologic
7
Znajduje to tylko zatwierdzenia w bieżącej gałęzi, chyba że podasz --alljako dodatkowy argument. (Znalezienie wszystkich zatwierdzeń w całym repozytorium jest ważne w przypadkach takich jak usuwanie dużego pliku z historii repozytorium ).
peterflynn
1
Wskazówka: przekaż flagę -g do skryptu powłoki (po identyfikatorze obiektu), aby sprawdzić reflog.
Bram Schoenmakers
24

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.

git log --all --pretty=format:%H -- <path> | xargs -n1 -I% sh -c "git ls-tree % -- <path> | grep -q <hash> && echo %"
aragaer
źródło
1
Doskonała odpowiedź, bo to takie proste. Wystarczy przyjąć rozsądne założenie, że ścieżka jest znana. Należy jednak wiedzieć, że zwraca zatwierdzenie, w którym ścieżka została zmieniona na podany hash.
Unapiedra
1
Jeśli ktoś chce najnowszego zatwierdzenia zawierającego <hash>podaną wartość <path>, wtedy usunięcie <path>argumentu z git logwill zadziała. Pierwszym zwróconym wynikiem jest poszukiwane zatwierdzenie.
Unapiedra
10

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?

Z Git 2.16 (Q1 2018) git describebył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)

builtin/describe.c: opisz kroplę

Czasami użytkownicy otrzymują skrót obiektu i chcą go dokładniej zidentyfikować (np .: Użyj, verify-packaby znaleźć największe obiekty blob, ale co to jest? Lub to bardzo TAK pytanie „ Które zatwierdzenie ma ten obiekt blob? ”)

Podczas opisywania zatwierdzeń staramy się zakotwiczyć je w tagach lub odnośnikach, ponieważ są one koncepcyjnie na wyższym poziomie niż zatwierdzenie. A jeśli nie ma ref lub tagu, który dokładnie pasuje, nie mamy szczęścia.
Dlatego stosujemy heurystykę, aby nadać nazwę zatwierdzeniu. Nazwy te są niejednoznaczne, mogą istnieć różne tagi lub odniesienia do zakotwiczenia, a w DAG może istnieć inna ścieżka, którą należy podróżować, aby precyzyjnie dotrzeć do zatwierdzenia.

Opisując obiekt blob, chcemy również opisać go z wyższej warstwy, co jest krotką, (commit, deep/path)ponieważ obiekty drzewa, których to dotyczy, są raczej nieinteresujące.
Do tego samego obiektu blob może się odwoływać wiele zatwierdzeń, więc jak zdecydujemy, którego zatwierdzenia użyć?

Ta łatka implementuje raczej naiwne podejście do tego: ponieważ nie ma wskaźników wstecz od plamek do zatwierdzeń, w których występuje blob, zaczniemy chodzić od wszelkich dostępnych wskazówek, wymieniając obiekty w kolejności zatwierdzenia i gdy znajdziemy blob, weźmiemy pierwsze zatwierdzenie, które zawierało ten obiekt .

Na przykład:

git describe --tags v0.99:Makefile
conversion-901-g7672db20c2:Makefile

mówi nam, że Makefiletak jak było, v0.99zostało wprowadzone w zatwierdzeniu 7672db2 .

Spacer jest wykonywany w odwrotnej kolejności, aby pokazać wprowadzenie kropki, a nie jej ostatnie wystąpienie.

Oznacza to, że git describestrona podręcznika dodaje do celów tego polecenia:

Zamiast po prostu opisywać zatwierdzenie za pomocą najnowszego dostępnego z niego znacznika, w git describerzeczywistości nada obiektowi czytelną dla człowieka nazwę na podstawie dostępnego ref, gdy jest używany jako git describe <blob>.

Jeżeli dany obiekt odnosi się kropelka zostanie on opisany jako <commit-ish>:<path>tak, że kropelka można znaleźć w <path>w <commit-ish>, które z kolei opisano w którym pierwszy popełnić to nastąpi blob w odwrotnej zmiany odległości od głowy.

Ale:

ROBAKI

Nie można opisać obiektów drzewiastych ani obiektów znaczników, które nie wskazują na zatwierdzenia .
Podczas opisywania obiektów blob lekkie znaczniki wskazujące na obiekty blob są ignorowane, ale obiekt BLOB jest nadal opisywany jako <committ-ish>:<path>pomimo tego, że lekki znacznik jest korzystny.

VonC
źródło
1
Dobry w połączeniu z 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 do git describe. Działał jak urok! Dzięki!
Alexander Pogrebnyak
7

Pomyślałem, że byłoby to ogólnie przydatne, więc napisałem mały skrypt w Perlu, aby to zrobić:

#!/usr/bin/perl -w

use strict;

my @commits;
my %trees;
my $blob;

sub blob_in_tree {
    my $tree = $_[0];
    if (defined $trees{$tree}) {
        return $trees{$tree};
    }
    my $r = 0;
    open(my $f, "git cat-file -p $tree|") or die $!;
    while (<$f>) {
        if (/^\d+ blob (\w+)/ && $1 eq $blob) {
            $r = 1;
        } elsif (/^\d+ tree (\w+)/) {
            $r = blob_in_tree($1);
        }
        last if $r;
    }
    close($f);
    $trees{$tree} = $r;
    return $r;
}

sub handle_commit {
    my $commit = $_[0];
    open(my $f, "git cat-file commit $commit|") or die $!;
    my $tree = <$f>;
    die unless $tree =~ /^tree (\w+)$/;
    if (blob_in_tree($1)) {
        print "$commit\n";
    }
    while (1) {
        my $parent = <$f>;
        last unless $parent =~ /^parent (\w+)$/;
        push @commits, $1;
    }
    close($f);
}

if (!@ARGV) {
    print STDERR "Usage: git-find-blob blob [head ...]\n";
    exit 1;
}

$blob = $ARGV[0];
if (@ARGV > 1) {
    foreach (@ARGV) {
        handle_commit($_);
    }
} else {
    handle_commit("HEAD");
}
while (@commits) {
    handle_commit(pop @commits);
}

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 -rnaprawdę 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.

Greg Hewgill
źródło
Hmm, jak to może być o wiele szybsze? I tak chodzisz po drzewie, prawda? Jakiej pracy git-ls-tree robi, czego unikasz? (Uwaga: grep wyskoczy za pierwszym dopasowaniem, SIGPIPE'uje drzewo git-ls.) Kiedy próbowałem, musiałem Ctrl-C twój skrypt po 30 sekundach; mój został zrobiony w 4.
Arystoteles Pagaltzis
1
Mój skrypt buforuje wyniki poddrzew w hashu% trees, więc nie musi wyszukiwać poddrzew, które nie uległy zmianie.
Greg Hewgill
Właściwie to próbowałem implementacji, którą znalazłem na githubie, z którą się łączyłem. Twój jest szybszy w niektórych przypadkach, ale zależy to w dużej mierze od tego, czy plik, którego szukasz, znajduje się na początku czy na końcu listy ls-tree. W moim repozytorium znajduje się teraz 9574 plików.
Greg Hewgill
Wydaje mi się również, że niektóre nieliniowe historie projektów mogą powodować, że mój skrypt będzie wykonywał znacznie więcej pracy, niż musi (można to naprawić). Być może dlatego bieganie dla ciebie zajęło dużo czasu. Moje repozytorium to kopia lustrzana git-svn repozytorium Subversion, więc jest ładnie liniowa.
Greg Hewgill
Zamiast analizować plik kota, aby uzyskać drzewo, po prostu zróbgit rev-parse $commit^{}
jthill
6

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:

#!/bin/sh
obj_name="$1"
shift
git ls-files --stage \
| if grep -q "$obj_name"; then
    echo Found in staging area. Run git ls-files --stage to see.
fi

git log "$@" --pretty=format:'%T %h %s' \
| while read tree commit subject ; do
    if git ls-tree -r $tree | grep -q "$obj_name" ; then
        echo $commit "$subject"
    fi
done
Mario
źródło
3
Chciałbym tylko przyznać kredyt tam, gdzie to należy: dziękuję za uszkodzenie pamięci RAM za spowodowanie mi BSOD i zmuszenie mnie do ręcznej naprawy repozytorium git.
Mario
4

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”

#!/usr/bin/env ruby

require 'log4r'

# The output of git verify-pack -v is:
# SHA1 type size size-in-packfile offset-in-packfile depth base-SHA1
#
#
GIT_PACKS_RELATIVE_PATH=File.join('.git', 'objects', 'pack', '*.pack')

# 10MB cutoff
CUTOFF_SIZE=1024*1024*10
#CUTOFF_SIZE=1024

begin

  include Log4r
  log = Logger.new 'git-find-large-objects'
  log.level = INFO
  log.outputters = Outputter.stdout

  git_dir = %x[ git rev-parse --show-toplevel ].chomp

  if git_dir.empty?
    log.fatal "ERROR: must be run in a git repository"
    exit 1
  end

  log.debug "Git Dir: '#{git_dir}'"

  pack_files = Dir[File.join(git_dir, GIT_PACKS_RELATIVE_PATH)]
  log.debug "Git Packs: #{pack_files.to_s}"

  # For details on this IO, see http://stackoverflow.com/questions/1154846/continuously-read-from-stdout-of-external-process-in-ruby
  #
  # Short version is, git verify-pack flushes buffers only on line endings, so
  # this works, if it didn't, then we could get partial lines and be sad.

  types = {
    :blob => 1,
    :tree => 1,
    :commit => 1,
  }


  total_count = 0
  counted_objects = 0
  large_objects = []

  IO.popen("git verify-pack -v -- #{pack_files.join(" ")}") do |pipe|
    pipe.each do |line|
      # The output of git verify-pack -v is:
      # SHA1 type size size-in-packfile offset-in-packfile depth base-SHA1
      data = line.chomp.split(' ')
      # types are blob, tree, or commit
      # we ignore other lines by looking for that
      next unless types[data[1].to_sym] == 1
      log.info "INPUT_THREAD: Processing object #{data[0]} type #{data[1]} size #{data[2]}"
      hash = {
        :sha1 => data[0],
        :type => data[1],
        :size => data[2].to_i,
      }
      total_count += hash[:size]
      counted_objects += 1
      if hash[:size] > CUTOFF_SIZE
        large_objects.push hash
      end
    end
  end

  log.info "Input complete"

  log.info "Counted #{counted_objects} totalling #{total_count} bytes."

  log.info "Sorting"

  large_objects.sort! { |a,b| b[:size] <=> a[:size] }

  log.info "Sorting complete"

  large_objects.each do |obj|
    log.info "#{obj[:sha1]} #{obj[:type]} #{obj[:size]}"
  end

  exit 0
end

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:

cat edited-large-files.log | cut -d' ' -f4 | xargs git-find-blob | tee large-file-paths.log

Gdzie git-find-blobskrypt jest poniżej.

#!/usr/bin/perl

# taken from: http://stackoverflow.com/questions/223678/which-commit-has-this-blob
# and modified by Carl Myers <[email protected]> to scan multiple blobs at once
# Also, modified to keep the discovered filenames
# vi: ft=perl

use 5.008;
use strict;
use Memoize;
use Data::Dumper;


my $BLOBS = {};

MAIN: {

    memoize 'check_tree';

    die "usage: git-find-blob <blob1> <blob2> ... -- [<git-log arguments ...>]\n"
        if not @ARGV;


    while ( @ARGV && $ARGV[0] ne '--' ) {
        my $arg = $ARGV[0];
        #print "Processing argument $arg\n";
        open my $rev_parse, '-|', git => 'rev-parse' => '--verify', $arg or die "Couldn't open pipe to git-rev-parse: $!\n";
        my $obj_name = <$rev_parse>;
        close $rev_parse or die "Couldn't expand passed blob.\n";
        chomp $obj_name;
        #$obj_name eq $ARGV[0] or print "($ARGV[0] expands to $obj_name)\n";
        print "($arg expands to $obj_name)\n";
        $BLOBS->{$obj_name} = $arg;
        shift @ARGV;
    }
    shift @ARGV; # drop the -- if present

    #print "BLOBS: " . Dumper($BLOBS) . "\n";

    foreach my $blob ( keys %{$BLOBS} ) {
        #print "Printing results for blob $blob:\n";

        open my $log, '-|', git => log => @ARGV, '--pretty=format:%T %h %s'
            or die "Couldn't open pipe to git-log: $!\n";

        while ( <$log> ) {
            chomp;
            my ( $tree, $commit, $subject ) = split " ", $_, 3;
            #print "Checking tree $tree\n";
            my $results = check_tree( $tree );

            #print "RESULTS: " . Dumper($results);
            if (%{$results}) {
                print "$commit $subject\n";
                foreach my $blob ( keys %{$results} ) {
                    print "\t" . (join ", ", @{$results->{$blob}}) . "\n";
                }
            }
        }
    }

}


sub check_tree {
    my ( $tree ) = @_;
    #print "Calculating hits for tree $tree\n";

    my @subtree;

    # results = { BLOB => [ FILENAME1 ] }
    my $results = {};
    {
        open my $ls_tree, '-|', git => 'ls-tree' => $tree
            or die "Couldn't open pipe to git-ls-tree: $!\n";

        # example git ls-tree output:
        # 100644 blob 15d408e386400ee58e8695417fbe0f858f3ed424    filaname.txt
        while ( <$ls_tree> ) {
            /\A[0-7]{6} (\S+) (\S+)\s+(.*)/
                or die "unexpected git-ls-tree output";
            #print "Scanning line '$_' tree $2 file $3\n";
            foreach my $blob ( keys %{$BLOBS} ) {
                if ( $2 eq $blob ) {
                    print "Found $blob in $tree:$3\n";
                    push @{$results->{$blob}}, $3;
                }
            }
            push @subtree, [$2, $3] if $1 eq 'tree';
        }
    }

    foreach my $st ( @subtree ) {
        # $st->[0] is tree, $st->[1] is dirname
        my $st_result = check_tree( $st->[0] );
        foreach my $blob ( keys %{$st_result} ) {
            foreach my $filename ( @{$st_result->{$blob}} ) {
                my $path = $st->[1] . '/' . $filename;
                #print "Generating subdir path $path\n";
                push @{$results->{$blob}}, $path;
            }
        }
    }

    #print "Returning results for tree $tree: " . Dumper($results) . "\n\n";
    return $results;
}

Wynik będzie wyglądał następująco:

<hash prefix> <oneline log message>
    path/to/file.txt
    path/to/file2.txt
    ...
<hash prefix2> <oneline log msg...>

I tak dalej. Wyświetlone zostanie każde zatwierdzenie zawierające duży plik w swoim drzewie. jeśli usuniesz greplinie zaczynające się od tabulatora, uniqbę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 ...

cmyers
źródło
1
Jak odpowiedź Arystotelesa powyżej, to tylko znajdzie rewizje na bieżącej gałęzi chyba przekazać dodatkowe argumenty -- --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 ).
peterflynn
4

Ponadto git describewspomniałem o tym w mojej poprzedniej odpowiedzi , git loga git diffteraz 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.)

diffcore: dodaj opcję kilofa, aby znaleźć konkretną kroplę

Czasami użytkownicy otrzymują skrót obiektu i chcą go dokładniej zidentyfikować (np .: użyj pakietu weryfikacji, aby znaleźć największe obiekty blob, ale co to jest? Lub pytanie „ Które zatwierdzenie ma ten obiekt blob? ”)

Można ulec pokusie, aby rozszerzyć git-describepracę również z obiektami blob, które git describe <blob-id>dają opis jako „:”.
Zostało to zaimplementowane tutaj ; jak widać po samej liczbie odpowiedzi (> 110), okazuje się, że jest to trudne do uzyskania.
Najtrudniej jest wybrać poprawne „zatwierdzenie”, ponieważ może to być zatwierdzenie, które (ponownie) wprowadziło obiekt BLOB lub BLOB, który usunął obiekt BLOB; kropelka może istnieć w różnych gałęziach.

Junio ​​zasugerował inne podejście do rozwiązania tego problemu, które implementuje ta łatka.
Naucz diffmaszynę kolejnej flagi, aby ograniczyć informacje do tego, co jest pokazane.
Na przykład:

$ ./git log --oneline --find-object=v2.0.0:Makefile
  b2feb64 Revert the whole "ask curl-config" topic for now
  47fbfde i18n: only extract comments marked with "TRANSLATORS:"

obserwujemy, że produkt, z Makefilektórym 2.0został dostarczony, pojawił się v1.9.2-471-g47fbfded53w v2.0.0-rc1-5-gb2feb6430b.
Powodem, dla którego oba te zatwierdzenia występują przed wersją 2.0.0, są złe połączenia, których nie można znaleźć przy użyciu tego nowego mechanizmu.

VonC
źródło