কোন প্রতিশ্রুতিবদ্ধ এই ব্লব আছে?


149

একটি ব্লবের হ্যাশ দেওয়া হয়েছে, তাদের গাছে এই ব্লব রয়েছে এমন কমিটের তালিকা পাওয়ার কোনও উপায় আছে কি?


2
"একটি ব্লবের হাশ" হ'ল এটি ব্লব বিষয়বস্তুর কেবলমাত্র শামসাম নয় git hash-objector sha1("blob " + filesize + "\0" + data)
ইভান হ্যামিল্টন

1
আমি প্রাথমিকভাবে ভেবেছিলাম এই প্রশ্নটি আমার প্রশ্নের সাথে মেলে, তবে মনে হয় এটি হয় না। আমি জানতে চাই এক কমিট যা প্রথম চালু সংগ্রহস্থলের এই ফোঁটা।
জেসি গ্লিক 13

যদি আপনি ফাইলপথটি জানেন তবে আপনি git log --follow filepath(এবং আপনি চাইলে এরিস্টটলের সমাধান দ্রুত করতে এটি ব্যবহার করতে পারেন) ব্যবহার করতে পারেন ।
জাজ

প্রোটিপ ™: বেলেলি স্ক্রিপ্টগুলির মধ্যে একটি রাখুন ~/.binএবং এর নাম দিন git-find-object। তারপরে আপনি এটি দিয়ে ব্যবহার করতে পারেন git find-object
জাজ

1
দ্রষ্টব্য: গিট 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
এফওয়াইআই আপনাকে ব্লবের পুরো এসএইচএ ব্যবহার করতে হবে। একটি উপসর্গ, এমনকি অনন্য হলেও, কাজ করবে না। একটি উপসর্গ থেকে সম্পূর্ণ এসএইচএ পেতে, আপনি ব্যবহার করতে পারেনgit rev-parse --verify $theprefix
জন দৌহাত

1
এই মন্তব্য করার জন্য @ জনডাউট ধন্যবাদ। উপরের লিপিটিতে এটি কীভাবে অন্তর্ভুক্ত করা যায় তা এখানে (মন্তব্যগুলিতে অন্তর্ভুক্তির জন্য দুঃখিত): 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

একটি ব্লবের হ্যাশ দেওয়া হয়েছে, তাদের গাছে এই ব্লব রয়েছে এমন কমিটের তালিকা পাওয়ার কোনও উপায় আছে কি?

গিট 2.16 (Q1 2018) সহ, git describeএটি একটি ভাল সমাধান হতে পারে, যেহেতু <commit-ish>:<path>কোনও প্রদত্ত ব্লব অবজেক্টকে বোঝায় এমন একটি সন্ধানের জন্য গাছগুলি আরও গভীরভাবে খুঁড়তে শেখানো হয়েছিল ।

দেখুন কমিট 644eb60 , 4dbc59a কমিট , cdaed0c কমিট , c87b653 কমিট , ce5b6f9 কমিট (16 নভেম্বর 2017), এবং 91904f5 কমিট , কমিট 2deda00 (02 নভেম্বর 2017) দ্বারা স্টিফান Beller ( stefanbeller)
(দ্বারা একীভূত junio সি Hamano - gitster- মধ্যে 556de1a কমিট , 28 ডিসেম্বর 2017)

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: আমার নোট করা উচিত যে উপরে আমার সম্পাদনার মন্তব্যগুলি প্রথম আপডেটে উপরে সংযুক্তি প্রয়োগের ক্ষেত্রে প্রযোজ্য। অ্যারিস্টটলের বাস্তবায়ন আমার সাথে তুলনামূলকভাবে সম্পাদন করে। যারা আগ্রহী তাদের মন্তব্যগুলিতে আরও বিশদ।


হুম, কিভাবে এটা হতে পারে যে অনেক দ্রুত? আপনি যেভাবেই গাছটি হাঁটছেন, আপনি না? গিট-এলএস-ট্রি আপনি কোন কাজ এড়ান? (এনবি: গ্রেপ প্রথম ম্যাচে জামিন দেবে, গিটার-এলএস-গাছের সংকেত দিবে) খনিটি 4-এ সম্পন্ন হয়েছিল
অ্যারিস্টটল পাগল্টজিস

1
আমার স্ক্রিপ্ট% টি গাছের হ্যাশগুলিতে সাবট্রির ফলাফলকে ক্যাশে করে, তাই এটি পরিবর্তিত হয়নি এমন সাবট্রিজগুলি সন্ধান করতে হবে না।
গ্রেগ হিউগিল

আসলে, আমি গিথুবকে আমি যে সংযুক্ত করেছিলাম তার প্রয়োগের চেষ্টা করছিলাম। আপনার ক্ষেত্রে কিছু ক্ষেত্রে দ্রুত, তবে আপনি যে ফাইলটি সন্ধান করছেন সেটি এলএস-ট্রি তালিকার শুরুতে বা শেষের দিকে নির্ভর করে it আমার সংগ্রহস্থলটির এখনই এটিতে 9574 টি ফাইল রয়েছে।
গ্রেগ হিউগিল

আমার কাছে এটিও ঘটে যে কিছু অফলাইন প্রকল্পের ইতিহাস আমার স্ক্রিপ্টের প্রয়োজনের তুলনায় আরও বেশি কাজ করতে পারে (এটি স্থির করা যেতে পারে)। এটি সম্ভবত আপনার জন্য দৌড়াতে দীর্ঘ সময় নিয়েছিল। আমার রিপোসিটোরিটি একটি সাবভার্সন সংগ্রহস্থলের একটি গিট-এসএনএন আয়না, সুতরাং এটি দুর্দান্ত রৈখিক।
গ্রেগ হিউগিল

গাছটি ঠিক করার জন্য ক্যাট-ফাইল 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
আমি যেখানে ঠিক সেখানে creditণ দিতে চাই: আমাকে বিএসওড তৈরি করার জন্য এবং আমার গিট রেপো মেরামত করতে বাধ্য করার জন্য র্যাম দুর্নীতির জন্য আপনাকে ধন্যবাদ।
মারিও

4

সুতরাং ... আমাকে 108,000 এরও বেশি সংশোধন সহ 8GB আকারের আকারের একটি রেপোতে প্রদত্ত সীমাতে সমস্ত ফাইলগুলি সন্ধান করতে হবে। এই সম্পূর্ণ সমাধানটিতে পৌঁছানোর জন্য আমি লিখেছিলাম একটি রুবি স্ক্রিপ্টের সাথে এরিস্টটলের পার্ল স্ক্রিপ্টটি মানিয়েছি।

প্রথম, git gc- সমস্ত বস্তু প্যাকফাইলে রয়েছে তা নিশ্চিত করতে এটি করুন - আমরা প্যাক ফাইলগুলিতে নয় এমন বস্তুগুলি স্ক্যান করি না।

পরবর্তী CUTOFF_SIZE বাইটে সমস্ত ব্লব সনাক্ত করতে এই স্ক্রিপ্টটি চালান। "লার্জ-ব্লবস.লগ" এর মতো কোনও ফাইলে আউটপুট ক্যাপচার করুন

#!/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 বিটগুলি সরাতে ফাইলটি সম্পাদনা করুন। আপনি যে শা 1 গুলি সন্ধান করতে চান তার জন্য একবার কেবল রেখা থাকলে, নিম্নলিখিত স্ক্রিপ্টটি এভাবে চালান:

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তা, আপনি মুছে ফেলার জন্য ফিল্টার-ব্রাঞ্চ করতে পারে এমন সমস্ত পাথের একটি তালিকা থাকবে বা আপনি আরও জটিল কিছু করতে পারেন।

আমাকে পুনরাবৃত্তি করা যাক: এই প্রক্রিয়াটি 10,000 জিপিওতে 108,000 কমিট করে সফলতার সাথে চলেছিল। বিপুল সংখ্যক ব্লবগুলিতে চলার সময় আমার পূর্বাভাসের তুলনায় এটি অনেক বেশি সময় নিয়েছে যদিও 10 ঘন্টােরও বেশি সময় ধরে, আমাকে দেখতে হবে যে মুখস্ত বিটটি কাজ করছে কিনা ...


1
উপরে অ্যারিস্টট্ল এর উত্তর ভালো লেগেছে, এই শুধুমাত্র করে খুঁজে বের করে বর্তমান ডালে যদি না আপনি অতিরিক্ত আর্গুমেন্ট পাস: -- --all। ( রেপো ইতিহাস থেকে কোনও বড় ফাইল পুঙ্খানুপুঙ্খভাবে মুছার মতো ক্ষেত্রে রিপো-ওয়াইডের সমস্ত কমিটস সন্ধান করা গুরুত্বপূর্ণ )।
পিটারফ্লিন

4

এর উপরন্তু git describe, আমি আমার আগের উত্তরে উল্লেখ , git logএবং git diffএখন "থেকে পাশাপাশি উপকার --find-object=<object-id>যে পরিবর্তন নামে বস্তুর জড়িত তথ্যও সীমিত করতে" বিকল্পটি।
এটি গিট 2.16.x / 2.17 (Q1 2018) এ রয়েছে

দেখুন 4d8c51a কমিট , কমিট 5e50525 , 15af58c কমিট , cf63051 কমিট , c1ddc46 কমিট , কমিট 929ed70 (04 জানু 2018) স্টিফান বেলার ( stefanbeller) দ্বারা
(দ্বারা একীভূত junio সি Hamano - gitster- মধ্যে কমিট c0d75f0 , 23 জানুয়ারী 2018)

diffcore: একটি নির্দিষ্ট ব্লব সন্ধানের জন্য একটি পিক্সে বিকল্প যুক্ত করুন

কখনও কখনও ব্যবহারকারীদের একটি বস্তুর একটি হ্যাশ দেওয়া হয় এবং তারা এটি আরও চিহ্নিত করতে চায় (উদাঃ: বৃহত্তম ব্লবগুলি খুঁজে পেতে ভেরিফিকেশন-প্যাকটি ব্যবহার করুন তবে এগুলি কী? বা এই স্ট্যাক ওভারফ্লো প্রশ্ন " কোন প্রতিশ্রুতিতে এই ব্লবটি আছে? ")

git-describeব্লবগুলির সাথেও কাজ করতে প্ররোচিত হতে পারে git describe <blob-id>যেমন ':' হিসাবে বর্ণনা দেয়।
এটি এখানে বাস্তবায়িত হয়েছিল ; প্রতিক্রিয়াগুলির নিখুঁত সংখ্যা (> ১১০) দ্বারা দেখা গেছে, এটি সঠিকভাবে পাওয়া কঠিন।
ডান পেতে শক্ত অংশটি সঠিক 'কমিট-ইশ' বাছাই করা হ'ল সেই প্রতিশ্রুতি হতে পারে যা (পুনরায়) ব্লবটি বা ব্লবটি সরিয়ে দেয় যা ব্লবটি সরিয়ে দেয়; অঙ্কুরটি বিভিন্ন শাখায় থাকতে পারে।

জুনিও এই সমস্যা সমাধানের জন্য একটি ভিন্ন পদ্ধতির ইঙ্গিত দিয়েছিল, যা এই প্যাচটি প্রয়োগ করে। যা দেখানো হয়েছে তাতে তথ্য সীমাবদ্ধ করার জন্য যন্ত্রপাতিটিকে অন্য পতাকা
শিখান 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 এর পূর্বে এই দু'টি প্রতিশ্রুতি উভয়ই হবার কারণ হ'ল অশুভ সংশ্লেষ যা এই নতুন পদ্ধতিটি ব্যবহার করে খুঁজে পাওয়া যায় না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.