यह कौन सा अपराध है?


149

एक बूँद के हैश को देखते हुए, क्या उन पेड़ों में इस बूँद के होने की सूची प्राप्त करने का कोई तरीका है?


2
"हैश ऑफ़ ए ब्लॉब" वह है जो git hash-objectया तो लौटाया जाता है sha1("blob " + filesize + "\0" + data), न कि केवल बूँद सामग्री का शटसम।
इवान हैमिल्टन

1
मैंने मूल रूप से सोचा था कि यह प्रश्न मेरे प्रश्न से मेल खाता है, लेकिन ऐसा लगता है कि यह नहीं है। मैं एक कमेटी को जानना चाहता हूं जिसने पहली बार इस बूँद को भंडार में पेश किया था।
जेसी ग्लिक

यदि आप फ़ाइलपथ को जानते हैं, तो आप git log --follow filepath(और यदि आप चाहें तो अरस्तू के समाधान को गति देने के लिए इसका उपयोग कर सकते हैं)।
ज़ाज़

ProTip ™: एक belew स्क्रिप्ट को ~/.binइसमें डालें और नाम दें git-find-object। फिर आप इसके साथ उपयोग कर सकते हैं git find-object
ज़ाज़

1
नोट: Git 2.16 (Q1 2018) के साथ, आप बस विचार कर सकते हैं git describe <hash>: नीचे मेरा जवाब देखें
वॉन

जवाबों:


107

निम्न स्क्रिप्ट के दोनों पहले तर्क के रूप में बूँद SHA1 लेते हैं, और इसके बाद, वैकल्पिक रूप से, कोई भी तर्क जो git logसमझ में आएगा। उदाहरण के --allलिए, केवल वर्तमान एक के बजाय सभी शाखाओं में खोज करने के लिए, या -gरिफ्लॉग में खोज करने के लिए, या जो भी आप कल्पना करते हैं।

यहाँ यह एक शेल स्क्रिप्ट के रूप में है - छोटी और प्यारी, लेकिन धीमी:

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

और पर्ल में एक अनुकूलित संस्करण, अभी भी काफी छोटा लेकिन बहुत तेज है:

#!/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 करें आपको बूँद के पूर्ण SHA का उपयोग करना होगा। एक उपसर्ग, भले ही अद्वितीय हो, काम नहीं करेगा। एक उपसर्ग से पूर्ण SHA पाने के लिए आपको उपयोग कर सकते हैंgit rev-parse --verify $theprefix
जॉन Douthat

1
इस टिप्पणी के लिए @JohnDouthat धन्यवाद। यहाँ बताया गया है कि इसे उपरोक्त लिपि में कैसे शामिल किया जाए (टिप्पणियों में inlining के लिए खेद है): 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
मिक्सोलॉजिक

7
जब तक आप एक अतिरिक्त तर्क के रूप में पारित नहीं करते, तब तक यह केवल वर्तमान शाखा पर ही होता है --all। ( रेपो इतिहास से बड़ी फ़ाइल को हटाने जैसे मामलों में रेपो-वाइड सभी कमिट करना महत्वपूर्ण है )।
पीटररन ने

1
युक्ति: शेल स्क्रिप्ट (ऑब्जेक्ट आईडी के बाद) के लिए -g फ्लैग को पास करने के लिए रिफ्लग की जांच करें।
ब्रैम शोनेमेकर्स

24

दुर्भाग्य से स्क्रिप्ट मेरे लिए थोड़ी धीमी थी, इसलिए मुझे थोड़ा अनुकूलन करना पड़ा। सौभाग्य से मेरे पास न केवल हैश था, बल्कि एक फ़ाइल का मार्ग भी था।

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

1
उत्कृष्ट उत्तर क्योंकि यह बहुत सरल है। बस उचित धारणा बनाकर कि रास्ता जाना जाता है। हालांकि, किसी को पता होना चाहिए कि यह उस प्रतिबद्धता को लौटाता है, जहां दिए गए हैश के लिए रास्ता बदल गया था।
अनपिड्रा

1
एक नवीनतम चाहता है युक्त प्रतिबद्ध <hash>में दिया <path>है, तो दूर करने <path>से तर्क git logइच्छा काम करते हैं। पहला लौटा परिणाम वांछित कमेटी है।
अनपिड्रा

10

एक बूँद के हैश को देखते हुए, क्या उन पेड़ों में इस बूँद के होने की सूची प्राप्त करने का कोई तरीका है?

Git 2.16 (Q1 2018) के साथ, git describeएक अच्छा समाधान होगा, क्योंकि यह एक गहरी <commit-ish>:<path>बूँद वस्तु को संदर्भित करने के लिए पेड़ों को खोदने के लिए सिखाया गया था ।

देखें , 644eb60 , 4dbc59a , कमिटेड cced0c , प्रतिबद्ध c87b653 , प्रतिबद्ध ce5b6f9 (16 Nov 2017), और 91904f5 कमिट करें , Stefan Beller ( ) द्वारा 2deda00 (02 Nov 2017 ) देखें(द्वारा विलय Junio सी Hamano - - में 556de1a प्रतिबद्ध , 28 दिसंबर 2017)stefanbeller
gitster

builtin/describe.c: एक बूँद का वर्णन करें

कभी-कभी उपयोगकर्ताओं को किसी वस्तु का हैश दिया जाता है और वे इसे और आगे पहचानना चाहते हैं (उदा।: verify-packसबसे बड़े ब्लब्स को खोजने के लिए उपयोग करें , लेकिन ये क्या हैं? या यह बहुत ही प्रश्न है "यह कौन सी प्रतिबद्धता है? "

जब हम वर्णन करते हैं, तो हम उन्हें टैग या रेफरी के लिए लंगर देने की कोशिश करते हैं, क्योंकि ये वैचारिक रूप से प्रतिबद्ध से उच्च स्तर पर हैं। और अगर कोई रेफ या टैग नहीं है जो वास्तव में मेल खाता है, तो हम भाग्य से बाहर हैं।
इसलिए हम प्रतिबद्ध के लिए एक नाम बनाने के लिए एक अनुमानी को नियुक्त करते हैं। ये नाम अस्पष्ट हैं, अलग-अलग टैग हो सकते हैं या लंगर के लिए रेफरी हो सकते हैं, और डीएजी में अलग-अलग रास्ते हो सकते हैं ताकि वे कम से कम यात्रा कर सकें।

एक बूँद का वर्णन करते समय, हम एक उच्च परत से बूँद के रूप में अच्छी तरह से वर्णन करना चाहते हैं, जो (commit, deep/path)कि पेड़ की वस्तुओं को शामिल करने के बजाय एकतरफा है।
एक ही बूँद को कई हिट द्वारा संदर्भित किया जा सकता है, इसलिए हम कैसे तय करते हैं कि किसके उपयोग के लिए प्रतिबद्ध है?

यह पैच इस पर एक भोली दृष्टिकोण लागू करता है: जैसा कि बूँदें से कमिट्स में कोई बैक पॉइंटर्स नहीं होते हैं, जिसमें बूँद होती है, हम उपलब्ध किसी भी टिप्स से चलना शुरू कर देंगे, कमिट के क्रम को सूचीबद्ध करते हुए और एक बार हमने पाया। बूँद, हम पहली सूची लेंगे जो बूँद सूचीबद्ध है

उदाहरण के लिए:

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

हमें बताता है कि Makefileजैसा कि 7672db2v0.99 में पेश किया गया था ।

चलने को रिवर्स ऑर्डर में प्रदर्शन किया जाता है ताकि इसकी अंतिम घटना के बजाय एक बूँद का परिचय दिखाया जा सके।

इसका मतलब है कि इस आदेश के उद्देश्यों में git describeमैन पेज शामिल है :

इसके बजाय केवल सबसे हाल ही में टैग किए गए टैग का उपयोग करते हुए एक कमिट का वर्णन करने के बजाय, git describeवास्तव में एक वस्तु को एक मानव पठनीय नाम देगा जो उपलब्ध रेफरी के आधार पर उपयोग किया जाता है git describe <blob>

दिए गए वस्तु एक ब्लॉब को संदर्भित करता है, यह के रूप में वर्णित किया जाएगा <commit-ish>:<path>, ब्लॉब में पाया जा सकता है कि इस तरह के <path>में <commit-ish>है, जो खुद का वर्णन पहले प्रतिबद्ध है, जिसमें इस ब्लॉब सिर से एक रिवर्स संशोधन की पैदल दूरी में होता है।

परंतु:

बग

ट्री ऑब्जेक्ट्स के साथ-साथ टैग ऑब्जेक्ट्स जो कमिट्स पर इंगित नहीं करते हैं, उन्हें वर्णित नहीं किया जा सकता है
जब ब्लॉब्स का वर्णन किया जाता है, तो ब्लब्स पर इंगित करने वाले हल्के टैग को अनदेखा कर दिया जाता है, लेकिन <committ-ish>:<path>हल्के टैग के अनुकूल होने के बावजूद भी बूँद का वर्णन किया जाता है ।


1
के साथ संयोजन के रूप में उपयोग करने के लिए अच्छा है 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, जो आपको शीर्ष 20 सबसे बड़े ब्लब्स देता है। फिर आप उपरोक्त आउटपुट से बूँद आईडी पास कर सकते हैं git describe। एक आकर्षण के रूप में काम किया! धन्यवाद!
अलेक्जेंडर पोगरेबनेक

7

मैंने सोचा था कि यह आम तौर पर उपयोगी चीज होगी, इसलिए मैंने इसे करने के लिए एक छोटी सी पटकथा लिखी:

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

जब मैं आज शाम को घर आऊँगा, तब इसे जीथब पर रखूँगा।

अद्यतन: ऐसा लगता है कि किसी ने पहले से ही ऐसा किया है । यह एक ही सामान्य विचार का उपयोग करता है लेकिन विवरण अलग हैं और कार्यान्वयन बहुत छोटा है। मुझे नहीं पता कि यह तेज़ होगा लेकिन प्रदर्शन शायद यहाँ चिंता का विषय नहीं है!

अद्यतन 2: इसके लायक क्या है, मेरे कार्यान्वयन में तेजी से परिमाण के आदेश हैं, खासकर एक बड़े भंडार के लिए। यह git ls-tree -rवास्तव में दर्द होता है।

अद्यतन 3: मुझे ध्यान देना चाहिए कि ऊपर दिए गए मेरे प्रदर्शन की टिप्पणियां पहले अद्यतन में मेरे द्वारा लिंक किए गए कार्यान्वयन पर लागू होती हैं। अरस्तू का कार्यान्वयन मेरा तुलनात्मक रूप से करता है। जो लोग उत्सुक हैं उनके लिए टिप्पणियों में अधिक विवरण।


हम्म, यह इतना तेज़ कैसे हो सकता है ? आप वैसे भी पेड़ पर चल रहे हैं, क्या आप नहीं हैं? क्या काम करता है git-ls-tree जिससे आप बचते हैं? (एनबी: grep पहले मैच में जमानत देगा, SITPIPE'it git-ls-tree।) जब मैंने इसे आज़माया, तो मुझे 30 सेकंड के बाद आपकी स्क्रिप्ट को Ctrl-C करना पड़ा; मेरा 4. में किया गया था
अरस्तू पगलतज़िस

1
मेरी स्क्रिप्ट% पेड़ हैश में उपशीर्षक के परिणामों को कैश करती है, इसलिए इसे उन उपशीर्षक को खोजते नहीं रहना है जो नहीं बदले हैं।
ग्रेग हेविगिल

असल में, मैं जीथब पर पाए जाने वाले क्रियान्वयन की कोशिश कर रहा था, जिससे मैं जुड़ा था। आपका कुछ मामलों में तेज़ है, लेकिन यह बहुत हद तक इस बात पर निर्भर करता है कि आप जिस फ़ाइल की तलाश कर रहे हैं वह ls-tree सूची के आरंभ या अंत में है या नहीं। मेरी रिपॉजिटरी में अभी 9574 फाइलें हैं।
ग्रेग हेवगिल

यह मेरे साथ भी होता है कि कुछ नॉनलाइनर प्रोजेक्ट हिस्टरी के कारण मेरी स्क्रिप्ट को बहुत अधिक काम करने की आवश्यकता हो सकती है (यह तय किया जा सकता है)। यह हो सकता है कि आपको चलने में लंबा समय लगे। मेरी प्रतिक्रियाशिका एक तोड़फोड़ भंडार का एक git-svn दर्पण है, इसलिए यह अच्छी तरह से रैखिक है।
ग्रेग हेविल

पेड़ को प्राप्त करने के लिए बिल्ली को git rev-parse $commit^{}
पालने की

6

हालांकि मूल प्रश्न इसके लिए नहीं पूछता है, मुझे लगता है कि यह देखने के लिए कि यदि एक बूँद को संदर्भित किया जाता है, तो मचान क्षेत्र की जांच करना भी उपयोगी है। मैंने इसे करने के लिए मूल बैश स्क्रिप्ट को संशोधित किया और पाया कि मेरी रिपॉजिटरी में एक भ्रष्ट ब्लॉब का क्या उल्लेख था:

#!/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
मैं सिर्फ यह श्रेय देना चाहूंगा कि यह कहां है: धन्यवाद मुझे बीएसओडी बनाने के लिए राम भ्रष्टाचार और मुझे अपने गिट रेपो की मरम्मत के लिए मजबूर करना।
मारियो

4

तो ... मुझे 108,000 से अधिक संशोधनों के साथ, 8GB आकार में रेपो में दी गई सीमा पर सभी फ़ाइलों को खोजने की आवश्यकता थी। मैंने अरस्तू की पर्ल स्क्रिप्ट को रूबी स्क्रिप्ट के साथ अनुकूलित किया, जिसे मैंने इस संपूर्ण समाधान तक पहुंचने के लिए लिखा था।

सबसे पहले, git gc- यह सुनिश्चित करने के लिए कि सभी ऑब्जेक्ट्स पैकफाइल्स में हैं - हम ऑब्जेक्ट्स को पैक फाइलों में नहीं स्कैन करते हैं।

इसके बाद CUTOFF_SIZE बाइट्स पर सभी ब्लॉब्स का पता लगाने के लिए इस स्क्रिप्ट को चलाएँ। "बड़े-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

इसके बाद, किसी भी ऐसे ब्लब्स को निकालने के लिए फ़ाइल को संपादित करें जिसे आप प्रतीक्षा नहीं करते हैं और शीर्ष पर INPUT_THREAD बिट्स। एक बार जब आपके पास केवल उन sha1s के लिए लाइनें होती हैं जिन्हें आप खोजना चाहते हैं, तो निम्न स्क्रिप्ट को इस तरह से चलाएं:

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

जहां git-find-blobस्क्रिप्ट नीचे है।

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

आउटपुट इस तरह दिखेगा:

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

और इसी तरह। हर कमिटमेंट जिसमें एक बड़ी फाइल होती है, उसके पेड़ को सूचीबद्ध किया जाएगा। यदि आप grepएक टैब से शुरू होने वाली रेखाओं को बाहर निकालते हैं, और uniqआपके पास उन सभी रास्तों की सूची होगी, जिन्हें हटाने के लिए आप फ़िल्टर-शाखा कर सकते हैं, या आप कुछ अधिक जटिल कर सकते हैं।

मुझे फिर से दोहराएं: यह प्रक्रिया सफलतापूर्वक चली, 10GB रेपो पर 108,000 कमिट्स के साथ। जब मैंने 10 घंटे से अधिक की बड़ी संख्या में बूँदें चल रही थीं, तो मुझे यह अनुमान लगाने में अधिक समय लगा, मुझे यह देखना होगा कि मेमोराइज़ बिट काम कर रहा है या नहीं ...


1
ऊपर दिए गए अरस्तू के जवाब की तरह, यह केवल वर्तमान शाखा पर कमिट्स पाता है जब तक कि आप अतिरिक्त तर्क पास नहीं करते हैं -- --all:। ( रेपो इतिहास से एक बड़ी फ़ाइल को पूरी तरह से हटाने जैसे मामलों में रेपो-वाइड सभी कमिट करना महत्वपूर्ण है )।
पेट्रेलिनन

4

इसके अलावा git describe, जिसका मैं अपने पिछले उत्तर में उल्लेख करता हूं , git logऔर git diffअब लाभ के साथ-साथ " --find-object=<object-id>" विकल्प से निष्कर्षों को उन परिवर्तनों को सीमित करने का विकल्प देता है जिनमें नामित वस्तु शामिल है।
यह Git 2.16.x / 2.17 (Q1 2018) में है

देखें 4d8c51a प्रतिबद्ध , प्रतिबद्ध 5e50525 , 15af58c प्रतिबद्ध , cf63051 प्रतिबद्ध , c1ddc46 प्रतिबद्ध , प्रतिबद्ध 929ed70 से (04 जनवरी 2018) Stefan बेलर ( stefanbeller) )
( जूनियो सी gitsterहमानो द्वारा विलय - - में प्रतिबद्ध c0d75f0 , 23 जनवरी 2018)

diffcore: एक विशिष्ट बूँद खोजने के लिए एक पिकैक्स विकल्प जोड़ें

कभी-कभी उपयोगकर्ताओं को किसी ऑब्जेक्ट का हैश दिया जाता है और वे इसे और अधिक पहचानना चाहते हैं (उदा।: सबसे बड़े ब्लब्स को खोजने के लिए वेरिफिकेशन-पैक का उपयोग करें, लेकिन ये क्या हैं? या यह स्टैक ओवरफ्लो प्रश्न "यह किस ब्लब के लिए प्रतिबद्ध है? ")

किसी git-describeको भी बूँद के साथ काम करने के लिए विस्तारित करने के लिए लुभाया जा सकता है , जैसे कि git describe <blob-id>विवरण: '।'
इसे यहां लागू किया गया था ; जैसा कि प्रतिक्रियाओं की सरासर संख्या (> 110) से पता चलता है, यह सही होने के लिए मुश्किल है।
सही पाने के लिए कठिन हिस्सा सही 'कमिट-ईश' उठा रहा है क्योंकि यह कमिट किया जा सकता है कि (पुनः) ने बूँद को हटा दिया है या बूँद को हटा दिया है; बूँद विभिन्न शाखाओं में मौजूद हो सकती है।

जूनियो ने इस समस्या को हल करने के एक अलग दृष्टिकोण पर संकेत दिया, जिसे यह पैच लागू करता है। जो दिखाया गया है उसकी जानकारी को सीमित करने के लिए मशीनरी को एक और झंडा
सिखाएं diff
उदाहरण के लिए:

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

हम देखते हैं कि Makefileजैसा कि इसके साथ भेज दिया 2.0गया था v1.9.2-471-g47fbfded53और इसमें दिखाई दिया था v2.0.0-rc1-5-gb2feb6430b
V2.0.0 से पहले इन दोनों के होने का कारण दुष्ट विलय है जो इस नए तंत्र का उपयोग करके नहीं पाया जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.