ファイル内の特定の行のコミットログを取得しますか?


503

ファイルの特定のに触れたコミットのみのコミットログをgitに取得させる方法はありますか?

同様にgit blame、しかし、git blameLASTは、特定の行に触れているコミットを紹介します。

私は本当に同じようなログを取得したいのですが、ファイル内の任意の場所へのコミットのリストではなく、特定の行に接触したコミットだけを取得します。


2
参照:Git
blame-

回答:


632

Git:さまざまな行に影響を与えたコミットを発見するも参照してください。


Gitの1.8.4以来git log持っている-L行の範囲の進化を表示します。

たとえば、git blameの出力を確認するとします。これ-L 150,+11は、「150行目から150 + 11行だけを見る」という意味です。

$ git blame -L 150,+11 -- git-web--browse.sh
a180055a git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:36 +0100 150)            die "The browser $browser is not
a180055a git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:36 +0100 151)    fi
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 152) fi
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 153) 
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 154) case "$browser" in
81f42f11 git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:38 +0100 155) firefox|iceweasel|seamonkey|iceape)
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 156)    # Check version because firefox < 2.0 do
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 157)    vers=$(expr "$($browser_path -version)" 
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 158)    NEWTAB='-new-tab'
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 159)    test "$vers" -lt 2 && NEWTAB=''
a0685a4f git-web--browse.sh (Dmitry Potapov   2008-02-09 23:22:22 -0800 160)    "$browser_path" $NEWTAB "$@" &

そして、現在155行目の履歴を知りたいとします。

次に、を使用しますgit log。ここで-L 155,155:git-web--browse.shは、「という名前のファイルの155行目から155行目の進化を追跡する」という意味git-web--browse.shです。

$ git log --pretty=short -u -L 155,155:git-web--browse.sh
commit 81f42f11496b9117273939c98d270af273c8a463
Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>

    web--browse: support opera, seamonkey and elinks

diff --git a/git-web--browse.sh b/git-web--browse.sh
--- a/git-web--browse.sh
+++ b/git-web--browse.sh
@@ -143,1 +143,1 @@
-firefox|iceweasel)
+firefox|iceweasel|seamonkey|iceape)

commit a180055a47c6793eaaba6289f623cff32644215b
Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>

    web--browse: coding style

diff --git a/git-web--browse.sh b/git-web--browse.sh
--- a/git-web--browse.sh
+++ b/git-web--browse.sh
@@ -142,1 +142,1 @@
-    firefox|iceweasel)
+firefox|iceweasel)

commit 5884f1fe96b33d9666a78e660042b1e3e5f9f4d9
Author: Christian Couder <chriscool@tuxfamily.org>

    Rename 'git-help--browse.sh' to 'git-web--browse.sh'.

diff --git a/git-web--browse.sh b/git-web--browse.sh
--- /dev/null
+++ b/git-web--browse.sh
@@ -0,0 +127,1 @@
+    firefox|iceweasel)

2
'git log --topo-order --graph -u -L 155,155:git-web--browse.sh'-これにより致命的なエラーが発生しました: '無効なオブジェクト名155,155'。Gitバージョン:1.8.3.2。助言がありますか?
BairDev 2013

12
Git 1.8.4以降にアップグレードします。
Matt McClure、

4
「commitAの155行目の履歴」を知りたい場合(HEADの155行目ではなく)。単純に使用できますgit log commitA-hash -L 155,155:file-nameか?
Ida

@Flimm、私は強い好みはありません。
Matt McClure

これは、ファイルが移動/名前変更されている場合を除いて、うまく機能します... --followは、行範囲の引数と組み合わせたくないようです。
Mike Ellery 2015

67

pick-axeを使用すると、一連のコミットを取得できます。

git log -S'the line from your file' -- path/to/your/file.txt

これにより、そのファイル内のテキストに影響を与えたすべてのコミットが提供されます。ファイルの名前が変更された場合は、-follow-parentを追加できます。

これらの各編集でコミットを検査したい場合は、その結果をgit showにパイプできます。

git log ... | xargs -n 1 git show

5
これがどのように役立つかわかりません。テキストが影響を受けた場合、行は同じではなくなるため、ツルハシは最新の変更のみを表示します。その後git log -S'the previous version of the line'、最終的にで行うのとまったく同じように、操作を行う必要がありますgit blame -L。またgit blame、指定された場所だけでなく、あらゆる場所でテキストを検索する必要があるため、に比べて非常に遅くなります。
Cascabel 2011

そこで正規表現を使用して、より受け入れやすくすることができます。現在、手の込んだスクリプトがなければ、「パッチをナビゲート」する方法はありません。gitkが将来的にパッチビューでこの機能を利用できるようになることを願っています。
Adam Dymitruk、2011

3
なぜこれはつるはしと呼ばれるのですか?:)
CiprianTomoiagă2018年


14

これを行う非常に簡単な方法は、vim-fugitiveを使用することです。vimでファイルを開き、使用する行を選択してV、次のように入力します。

:Glog

これでとを使用:cnext:cprevて、その行が変更されたファイルのすべてのリビジョンを確認できます。いつでも入力:Gblameして、sha、著者、日付の情報を確認できます。


13

@mattの答えを単純化する-

git blame -L14,15 -- <file_path>

ここでは、ラインのせいになります14 to 15

-LオプションはパラメーターRangeとして期待されるため、オプションBlameを使用して1行のを取得することはできません-L`

参照


10

これには何も組み込まれていないと思います。ファイルの残りの部分が大幅に変更されずに1行が数回変更されることはまれであるため、行番号が大幅に変更される傾向があるため、注意が必要です。

あなたのラインを常に持っていることをしている幸運に十分な場合は、いくつかの特定の特性を、名称変更したことがない変数への代入例えば、あなたがのための正規表現の選択肢を使用することができますgit blame -L。例えば:

git blame -L '/variable_name *= */',+1

しかし、これは最初のものだけを見つけますはその正規表現の一致ので、行を一致させるための適切な方法がない場合、あまり役に立ちません。

何かをハックできると思います。今すぐコードを書く時間はありませんが...これらの行に沿って何か。を実行しますgit blame -n -L $n,$n $file。最初のフィールドは変更された可能性があるため、変更された可能性があるため、前のコミットされたコミットであり、2番目のフィールドはそのコミットの行番号です。それらを取得して実行しますgit blame -n $n,$n $commit^ $file。つまり、ファイルが最後に変更される前のコミットから同じことを実行します。

(行を変更した最後のコミットがマージコミットの場合、これは失敗することに注意してください。行がマージ競合解決の一部として変更された場合、これが発生する主な方法です。)

編集:私は全体の起こったこのメーリングリストのポストと述べている、今日2011年3月からtiggit guiあなたがこれを行うに役立つ機能を持っています。機能自体はgit自体で検討されたようですが、完成していないようです。


6

これは、ファイルの行を表示するgit blameため意味のあるすべてのリビジョンを必要$LINEとします$FILE

git log --format=format:%H $FILE | xargs -L 1 git blame $FILE -L $LINE,$LINE

通常のように、非難は各行の先頭にリビジョン番号を示します。追加できます

| sort | uniq -c

集計結果を取得するには、この行を変更したコミットのリストのようなもの。(不正解です。コードが移動されただけの場合、行の異なる内容に対して同じコミットIDが2回表示される可能性があります。詳細な分析を行うには、git blame隣接するコミットの結果を遅らせて比較する必要があります。誰か? )


繰り返しますが、その行の以前の位置を追跡しないため、これは機能しません。つまり、2つのコミット前に行が追加された場合、別の行を見るでしょう
Vic Seedoubleyew

6

これはgitエイリアスを定義するソリューションです。そのため、そのように使用できます。

git rblame -M -n -L '/REGEX/,+1' FILE

出力例:

00000000 18 (Not Committed Yet 2013-08-19 13:04:52 +0000 728) fooREGEXbar
15227b97 18 (User1 2013-07-11 18:51:26 +0000 728) fooREGEX
1748695d 23 (User2 2013-03-19 21:09:09 +0000 741) REGEXbar

.gitconfigでエイリアスを定義するか、単に次のコマンドを実行します

git config alias.rblame !sh -c 'while line=$(git blame "$@" $commit 2>/dev/null); do commit=${line:0:8}^; [ 00000000^ == $commit ] && commit=$(git rev-parse HEAD); echo $line; done' dumb_param

これは醜いワンライナーなので、難読化されていない同等のbash関数を次に示します。

git-rblame () {
    local commit line
    while line=$(git blame "$@" $commit 2>/dev/null); do
        commit="${line:0:8}^"
        if [ "00000000^" == "$commit" ]; then
            commit=$(git rev-parse HEAD)
        fi
        echo $line
    done
}

つるはしソリューション(git log --pickaxe-regex -S'REGEX ')は、正規表現を含む行の他の変更ではなく、行の追加/削除のみを提供します。

このソリューションの制限はgit blameですが最初のREGEX一致のみを返すため、複数の一致が存在する場合、再帰が別の行に「ジャンプ」する可能性があることです。すべての履歴出力をチェックして、これらの「ジャンプ」を見つけ、寄生虫の線を無視するようにREGEXを修正してください。

最後に、各コミットでgit showを実行して完全な差分を取得する代替バージョンを次に示します。

git config alias.rblameshow !sh -c 'while line=$(git blame "$@" $commit 2>/dev/null); do commit=${line:0:8}^; [ 00000000^ == $commit ] && commit=$(git rev-parse HEAD); git show $commit; done' dumb_param

2

あなたは混在させることができますgit blameし、git logそれぞれの概要を取得するためのコマンドはgitの非難コマンドでコミットし、それらを追加します。次のbash + awkスクリプトのようなもの。コードのコメントとしてインラインでコミットの概要を追加します。

git blame FILE_NAME | awk -F" " \
'{
   commit = substr($0, 0, 8);
   if (!a[commit]) {
     query = "git log --oneline -n 1 " commit " --";
     (query | getline a[commit]);
   }
   print $0 "  // " substr(a[commit], 9);
 }'

1行で:

git blame FILE_NAME | awk -F" " '{ commit = substr($0, 0, 8); if (!a[commit]) { query = "git log --oneline -n 1 " commit " --"; (query | getline a[commit]); } print $0 "  // " substr(a[commit], 9); }'

2

私の場合、行番号は時間の経過とともに大きく変化しました。「git blame -L」で正規表現をサポートしていないgit 1.8.3も使用していました。(RHEL7にはまだ1.8.3があります)

myfile=haproxy.cfg
git rev-list HEAD -- $myfile | while read i
do
    git diff -U0 ${i}^ $i $myfile | sed "s/^/$i /"
done | grep "<sometext>"

一発ギャグ:

myfile=<myfile> ; git rev-list HEAD -- $myfile | while read i; do     git diff -U0 ${i}^ $i $myfile | sed "s/^/$i /"; done | grep "<sometext>"

もちろん、これをスクリプトまたは関数にすることもできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.