Cam kết nào có blob này?


149

Với hàm băm của một blob, có cách nào để có được một danh sách các cam kết có blob này trong cây của họ không?


2
"Hash of a blob" được trả về bởi git hash-objecthoặc sha1("blob " + filesize + "\0" + data), và không chỉ đơn giản là sha1sum của nội dung blob.
Ivan Hamilton

1
Ban đầu tôi nghĩ câu hỏi này khớp với câu hỏi của tôi, nhưng có vẻ như không phải vậy. Tôi muốn biết một cam kết đầu tiên giới thiệu blob này vào kho lưu trữ.
Jesse Glick

Nếu bạn biết filepath, bạn có thể sử dụng git log --follow filepath(và sử dụng điều này để tăng tốc giải pháp của Aristotle, nếu bạn muốn).
Zaz

ProTip ™: Đặt một trong các tập lệnh tin vào ~/.binvà đặt tên cho nó git-find-object. Sau đó bạn có thể sử dụng nó với git find-object.
Zaz

1
Lưu ý: Với Git 2.16 (Q1 2018), bạn có thể xem xét đơn giản git describe <hash>: Xem câu trả lời của tôi dưới đây .
VonC

Câu trả lời:


107

Cả hai tập lệnh sau đều lấy SHA1 của blob làm đối số đầu tiên và sau đó, tùy ý, mọi đối số git logsẽ hiểu. Ví dụ: --allđể tìm kiếm trong tất cả các chi nhánh thay vì chỉ -gtìm kiếm hiện tại hoặc tìm kiếm trong reflog, hoặc bất cứ điều gì bạn thích.

Đây là kịch bản shell - ngắn và ngọt ngào, nhưng chậm:

#!/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

Và một phiên bản tối ưu hóa trong Perl, vẫn còn khá ngắn nhưng nhanh hơn nhiều:

#!/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 );
}

8
FYI bạn phải sử dụng SHA đầy đủ của blob. Một tiền tố, ngay cả khi duy nhất, sẽ không hoạt động. Để có được SHA đầy đủ từ tiền tố, bạn có thể sử dụnggit rev-parse --verify $theprefix
John Douthat

1
Cảm ơn @JohnDouthat cho nhận xét này. Dưới đây là cách kết hợp tập lệnh đó vào tập lệnh trên (xin lỗi vì nội dung trong các bình luận): 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

Có thể có lỗi trong kịch bản shell trên. Vòng lặp while chỉ thực thi nếu có nhiều dòng để đọc và vì lý do nào đó git log sẽ không đặt một crlf cuối cùng vào cuối. Tôi đã phải thêm một nguồn cấp dữ liệu và bỏ qua các dòng trống. 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
Điều này chỉ tìm thấy các xác nhận trên nhánh hiện tại trừ khi bạn vượt qua --allnhư một đối số bổ sung. (Tìm tất cả các cam kết trên toàn repo rất quan trọng trong các trường hợp như xóa một tệp lớn khỏi lịch sử repo ).
peterflynn

1
Mẹo: chuyển cờ -g vào tập lệnh shell (sau ID đối tượng) để kiểm tra reflog.
Bram Schoenmakers

24

Thật không may, các kịch bản hơi chậm đối với tôi, vì vậy tôi phải tối ưu hóa một chút. May mắn thay, tôi không chỉ có băm mà còn cả đường dẫn của một tập tin.

git log --all --pretty=format:%H -- <path> | xargs -n1 -I% sh -c "git ls-tree % -- <path> | grep -q <hash> && echo %"

1
Câu trả lời tuyệt vời vì nó rất đơn giản. Chỉ bằng cách đưa ra giả định hợp lý rằng con đường được biết đến. Tuy nhiên, người ta nên biết rằng nó trả về cam kết nơi đường dẫn đã được thay đổi thành hàm băm đã cho.
Unapiedra

1
Nếu ai đó muốn cam kết mới nhất chứa <hash>cái đã cho <path>, thì loại bỏ <path>đối số khỏi ý git logchí. Kết quả trả về đầu tiên là cam kết mong muốn.
Unapiedra

10

Với hàm băm của một blob, có cách nào để có được một danh sách các cam kết có blob này trong cây của họ không?

Với Git 2.16 (Q1 2018), git describesẽ là một giải pháp tốt, vì nó được dạy đào cây sâu hơn để tìm một <commit-ish>:<path>đề cập đến một đối tượng blob nhất định.

Xem cam kết 644eb60 , cam kết 4dbc59a , cam kết cdaed0c , cam kết c87b653 , cam kết ce5b6f9 (16 tháng 11 năm 2017) và cam kết 91904f5 , cam kết 2deda00 (02 tháng 11 năm 2017) của Stefan Beller ( stefanbeller) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 556de1a , ngày 28 tháng 12 năm 2017)

builtin/describe.c: mô tả một đốm màu

Đôi khi người dùng được cung cấp một hàm băm của một đối tượng và họ muốn xác định thêm về nó (ví dụ: Sử dụng verify-packđể tìm các đốm màu lớn nhất, nhưng đây là những gì? Hoặc câu hỏi rất SO này " Cam kết nào có blob này? ")

Khi mô tả các cam kết, chúng tôi cố gắng neo chúng vào các thẻ hoặc ref, vì đây là những khái niệm ở mức cao hơn so với cam kết. Và nếu không có ref hoặc thẻ khớp chính xác, chúng ta sẽ không gặp may.
Vì vậy, chúng tôi sử dụng một heuristic để tạo ra một tên cho cam kết. Các tên này không rõ ràng, có thể có các thẻ hoặc tham chiếu khác nhau để neo và có thể có đường dẫn khác nhau trong DAG để di chuyển đến chính xác cam kết.

Khi mô tả một đốm màu, chúng tôi cũng muốn mô tả các đốm màu từ một lớp cao hơn, đó là một tuple (commit, deep/path)vì các đối tượng cây liên quan là khá không thú vị.
Cùng một blob có thể được tham chiếu bởi nhiều cam kết, vậy làm thế nào để chúng ta quyết định sử dụng cam kết nào?

Bản vá này thực hiện một cách tiếp cận khá ngây thơ về vấn đề này: Vì không có con trỏ quay lại từ các đốm màu đến các cam kết xảy ra, chúng ta sẽ bắt đầu đi bộ từ bất kỳ mẹo nào có sẵn, liệt kê các đốm màu theo thứ tự của cam kết và một khi chúng ta tìm thấy blob, chúng tôi sẽ thực hiện cam kết đầu tiên liệt kê blob .

Ví dụ:

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

cho chúng tôi biết Makefilenhư đã v0.99được giới thiệu trong cam kết 7672db2 .

Việc đi bộ được thực hiện theo thứ tự ngược lại để hiển thị việc giới thiệu một đốm màu thay vì lần xuất hiện cuối cùng của nó.

Điều đó có nghĩa là git describetrang man thêm vào mục đích của lệnh này:

Thay vì chỉ mô tả một cam kết sử dụng thẻ gần đây nhất có thể truy cập từ nó, git describethực tế sẽ cung cấp cho một đối tượng một tên người có thể đọc được dựa trên một ref có sẵn khi được sử dụng như git describe <blob>.

Nếu đối tượng đã cho đề cập đến một blob, nó sẽ được mô tả như là <commit-ish>:<path>, có thể tìm thấy blob ở <path>trong <commit-ish>đó, chính nó mô tả cam kết đầu tiên trong đó blob này xảy ra trong một phiên bản sửa đổi ngược từ HEAD.

Nhưng:

GIỎI

Các đối tượng cây cũng như các đối tượng thẻ không trỏ vào các xác nhận, không thể được mô tả .
Khi mô tả các đốm màu, các thẻ nhẹ chỉ vào các đốm màu bị bỏ qua, nhưng các đốm màu vẫn được mô tả là <committ-ish>:<path>mặc dù thẻ nhẹ là thuận lợi.


1
Tốt để sử dụng kết hợp với 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, nó trả lại cho bạn 20 đốm màu lớn nhất. Sau đó, bạn có thể chuyển ID blob từ đầu ra ở trên sang git describe. Làm việc như một cơ duyên! Cảm ơn!
Alexander Pogrebnyak

7

Tôi nghĩ rằng đây sẽ là một điều thường hữu ích để có, vì vậy tôi đã viết lên một kịch bản perl nhỏ để làm điều đó:

#!/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);
}

Tôi sẽ đưa nó lên github khi tôi về nhà tối nay.

Cập nhật: Có vẻ như ai đó đã làm điều này . Cái đó sử dụng cùng một ý tưởng chung nhưng các chi tiết khác nhau và việc thực hiện ngắn hơn nhiều . Tôi không biết cái nào sẽ nhanh hơn nhưng hiệu suất có lẽ không phải là vấn đề đáng lo ngại ở đây!

Cập nhật 2: Đối với những gì đáng giá, việc triển khai của tôi là các đơn đặt hàng có cường độ nhanh hơn, đặc biệt là đối với một kho lưu trữ lớn. Điều đó git ls-tree -rthực sự đau lòng.

Cập nhật 3: Tôi cần lưu ý rằng các nhận xét về hiệu suất của tôi ở trên áp dụng cho việc triển khai tôi đã liên kết ở trên trong Bản cập nhật đầu tiên. Việc thực hiện của Aristotle tương đương với tôi. Thêm chi tiết trong các ý kiến ​​cho những người tò mò.


Hmm, làm thế nào nó có thể được rằng nhanh hơn nhiều? Dù sao bạn cũng đang đi trên cây phải không? Git-ls-tree làm công việc gì mà bạn tránh? (NB.: Grep sẽ bảo lãnh cho trận đấu đầu tiên, SIGPIPE'ing the git-ls-tree.) Khi tôi thử nó, tôi phải Ctrl-C script của bạn sau 30 giây; Của tôi đã được thực hiện trong 4.
Aristotle Pagaltzis

1
Kịch bản của tôi lưu trữ kết quả của các cây con trong% cây băm, do đó, nó không phải tiếp tục tìm kiếm các cây con không thay đổi.
Greg Hewgill

Trên thực tế, tôi đã thử thực hiện mà tôi tìm thấy trên github mà tôi liên kết đến. Bạn nhanh hơn trong một số trường hợp, nhưng nó phụ thuộc nhiều vào việc tập tin bạn đang tìm kiếm ở đầu hay cuối danh sách ls-tree. Kho lưu trữ của tôi có 9574 tệp trong đó ngay bây giờ.
Greg Hewgill

Nó cũng xảy ra với tôi rằng một số lịch sử dự án phi tuyến có thể khiến kịch bản của tôi thực hiện nhiều công việc hơn mức cần thiết (điều này có thể được sửa chữa). Đây có thể là lý do tại sao phải mất một thời gian dài để chạy cho bạn. Kho lưu trữ của tôi là một nhân bản git-svn của kho lưu trữ Subversion, vì vậy nó là tuyến tính độc đáo.
Greg Hewgill

Thay vì phân tích cú pháp tệp mèo để lấy cây, hãy thực hiệngit rev-parse $commit^{}
jthill

6

Mặc dù câu hỏi ban đầu không yêu cầu, tôi nghĩ cũng hữu ích khi kiểm tra khu vực tổ chức để xem một blob có được tham chiếu hay không. Tôi đã sửa đổi tập lệnh bash ban đầu để làm điều này và tìm thấy những gì đang tham chiếu một blob bị hỏng trong kho lưu trữ của tôi:

#!/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

3
Tôi chỉ muốn cung cấp tín dụng khi đến hạn: cảm ơn bạn đã làm hỏng RAM vì đã cho tôi một BSOD và buộc tôi phải sửa chữa repo git của mình.
Mario

4

Vì vậy, ... tôi cần tìm tất cả các tệp trong một giới hạn nhất định trong một repo có kích thước trên 8GB, với hơn 108.000 phiên bản. Tôi đã điều chỉnh kịch bản perl của Aristotle cùng với kịch bản ruby ​​mà tôi đã viết để đạt được giải pháp hoàn chỉnh này.

Đầu tiên, git gc- làm điều này để đảm bảo tất cả các đối tượng nằm trong packfiles - chúng tôi không quét các đối tượng không có trong các tệp pack.

Tiếp theo Chạy tập lệnh này để xác định tất cả các đốm màu trên CUTOFF_SIZE byte. Ghi đầu ra vào một tệp như "big-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

Tiếp theo, chỉnh sửa tệp để xóa bất kỳ đốm màu nào bạn không chờ đợi và các bit INPUT_THREAD ở trên cùng. một khi bạn chỉ có các dòng cho các sha1 bạn muốn tìm, hãy chạy đoạn script sau như sau:

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

Trường hợp git-find-blobkịch bản dưới đây.

#!/usr/bin/perl

# taken from: http://stackoverflow.com/questions/223678/which-commit-has-this-blob
# and modified by Carl Myers <cmyers@cmyers.org> 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;
}

Đầu ra sẽ như thế này:

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

Và như thế. Mỗi cam kết chứa một tệp lớn trong cây của nó sẽ được liệt kê. nếu bạn grepđưa ra các dòng bắt đầu bằng một tab và uniqđiều đó, bạn sẽ có một danh sách tất cả các đường dẫn bạn có thể lọc chi nhánh để loại bỏ hoặc bạn có thể làm điều gì đó phức tạp hơn.

Hãy để tôi nhắc lại: quá trình này đã chạy thành công, trên repo 10 GB với 108.000 cam kết. Mất nhiều thời gian hơn tôi dự đoán khi chạy trên một số lượng lớn các đốm màu, mặc dù vậy, sau hơn 10 giờ, tôi sẽ phải xem liệu bit ghi nhớ có hoạt động không ...


1
Giống như câu trả lời của Aristotle ở trên, điều này chỉ tìm thấy các cam kết trên nhánh hiện tại trừ khi bạn vượt qua các đối số bổ sung : -- --all. (Tìm tất cả các cam kết trên toàn repo rất quan trọng trong các trường hợp như xóa triệt để một tệp lớn khỏi lịch sử repo ).
peterflynn

4

Ngoài các git describe, mà tôi đề cập đến trong câu trả lời trước đây của tôi , git loggit diffgiờ đây lợi ích cũng từ " --find-object=<object-id>" tùy chọn để hạn chế những phát hiện những thay đổi có liên quan đến đối tượng được đặt tên.
Đó là trong Git 2.16.x / 2.17 (Q1 2018)

Xem cam kết 4d8c51a , cam kết 5e50525 , cam kết 15af58c , cam kết cf63051 , cam kết c1ddc46 , cam kết 929ed70 (04 tháng 1 năm 2018) của Stefan Beller ( stefanbeller) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết c0d75f0 , ngày 23 tháng 1 năm 2018)

diffcore: thêm tùy chọn pickaxe để tìm một blob cụ thể

Đôi khi người dùng được cung cấp một hàm băm của một đối tượng và họ muốn xác định thêm về nó (ví dụ: Sử dụng gói xác minh để tìm các đốm màu lớn nhất, nhưng đây là những gì? Hoặc câu hỏi Stack Overflow này " Cam kết nào có blob này? ")

Người ta có thể được khuyến khích mở rộng git-describeđể cũng làm việc với các đốm màu, ví dụ như git describe <blob-id>mô tả là ':'.
Điều này đã được thực hiện ở đây ; như được thấy bởi số lượng phản hồi tuyệt đối (> 110), hóa ra điều này là khó khăn để làm đúng.
Phần khó để có được đúng là chọn 'commit-ish' chính xác vì đó có thể là cam kết (giới thiệu lại) giới thiệu blob hoặc blob đã loại bỏ blob; các đốm có thể tồn tại trong các nhánh khác nhau.

Junio ​​gợi ý về một cách tiếp cận khác nhau để giải quyết vấn đề này, mà bản vá này thực hiện.
Dạy cho diffmáy móc một lá cờ khác để hạn chế thông tin cho những gì được hiển thị.
Ví dụ:

$ ./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:"

chúng tôi quan sát thấy rằng Makefilenhư được vận chuyển với 2.0đã xuất hiện trong v1.9.2-471-g47fbfded53và trong v2.0.0-rc1-5-gb2feb6430b.
Lý do tại sao các cam kết này xảy ra trước v2.0.0 là những sự hợp nhất xấu không được tìm thấy khi sử dụng cơ chế mới này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.