「git log」に特定のパスの変更を無視させる


121

git log指定したファイル以外のファイルを変更したコミットのみを表示するにはどうすればよいですか?

を使用するとgit log、表示されたコミットをフィルタリングして、特定のパスのセットに関連するコミットを表示できます。私が欲しいのは、そのフィルターを反転させて、指定されたもの以外のタッチパスのコミットのみがリストされるようにすることです。

私は欲しいものを手に入れることができます

git log --format="%n/%n%H" --name-only | ~/filter-log.pl | git log --stdin --no-walk

ここfilter-log.plで:

#!/usr/bin/perl
use strict;
use warnings;

$/ = "\n/\n";
<>;

while (<>) {
    my ($commit, @files) = split /\n/, $_;

    if (grep { $_ && $_ !~ m[^(/$|.etckeeper$|lvm/(archive|backup)/)] } @files) {
        print "$commit\n";
    }
}

それよりも少しエレガントなものが欲しいのですが。

gitにファイルを無視させる方法を尋ねているのではないことに注意してください。これらのファイル追跡してコミットする必要があります。それは、ほとんどの場合、私はそれらを見ることに興味がないということだけです。

関連する質問:`git log --grep = <pattern>`を反転する方法またはパターン一致しないgitログを表示する方法パスではなくコミットメッセージを除いて同じ質問です。

2008年からのこのテーマに関するフォーラムディスカッション:Re:git-diffからのファイルの除外これは有望に見えましたが、スレッドが枯渇しているようです。


組み込みの方法があるかどうかはわかりませんが、perlソリューションはかなりまともです。コマンドライン引数としてパスを受け入れるように変更する場合、のようなエイリアスを作成するか!f() { git log ... | path/to/filter-log.pl "$@" | git log --stdin --no-walk; f、そのパイプラインの一部をスクリプトにラップすることもできます。
Cascabel

回避策として、findコミットを表示したくないディレクトリを除外するために使用します。私はルートレベルのディレクトリに行われたコミットからログエントリを無視したい場合はSiteConfig、その後、私は言う:git log `find . -type d -mindepth 1 -maxdepth 1 ! -name *SiteConfig`
ノアサスマン

Git 1.9 / 2.0(2014年第1四半期)については、以下の私の回答を参照しください:git log --oneline --format=%s -- . ":!sub"動作します(パススペックマジック:(exclude)とその短縮形で:!
VonC

回答:


214

NguyễnTháiNgọcDuy(よるcommit ef79b1fおよびcommit 1649612の導入pathspec magic :(exclude)およびその短い形式:!で、現在実装されています(git 1.9 / 2. 0、2014年第1四半期。ドキュメントはここにありますpclouds

これで、サブフォルダーのコンテンツを除くすべてをログに記録できます。

git log -- . ":(exclude)sub"
git log -- . ":!sub"

または、そのサブフォルダ内の特定の要素を除外できます

  • 特定のファイル:

      git log -- . ":(exclude)sub/sub/file"
      git log -- . ":!sub/sub/file"
    
  • 内の任意のファイルsub

      git log -- . ":(exclude)sub/*file"
      git log -- . ":!sub/*file"
      git log -- . ":(exclude,glob)sub/*/file"
    

この除外ケースで大文字と小文字を区別しないようにすることができます。

git log -- . ":(exclude,icase)SUB"

以下のようケニーEvittは指摘しました

GitをBashシェルで実行している場合は、':!sub'または":\!sub"を使用してエラーを回避しますbash: ... event not found


注:Git 2.13(2017年第2四半期)では同義語が追加さ^れます!

Linus Torvalds()によるcommit 859b7f1commit 42ebeb9(2017年2月8日)を参照してください。(合併によりJunio C浜野- -015fba3コミットし、2017年2月27日)をtorvalds
gitster

PATHSPEC魔法:「追加^」の別名として「!

!負のpathspec に「」を選択すると、最終的にリビジョンに対して何を行うかが一致しないだけでなく、引用が必要になるため、シェルの展開にとって恐ろしい文字になります。

したがって^、除外パススペックエントリの代替エイリアスとして「」を追加します。


Git 2.28(2020年第3四半期)より前は、作業ツリーで追跡されていないパスを含むパスを収集する際に、負のpathspecを使用することはできませんでした。

Elijah Newren()によるcommit f1f061e(2020年6月5日)を参照してください。(合併によりJunio C浜野- -64efa11コミットし、2020年6月18日)をnewren
gitster

dir:否定されたパススペックの扱いを修正

報告者:John Millikin
署名者:Elijah Newren

do_match_pathspec()match_pathspec_depth_1()正確性のために生命が始まったのは、からのみ呼ばれることになっていたmatch_pathspec_depth() match_pathspec_depth()は後にに名前が変更されたmatch_pathspec()ので、今日期待される不変条件は、のdo_match_pathspec()外部に直接の呼び出し元がないことですmatch_pathspec()

残念ながら、この意図は2つの関数の名前変更により失われ、追加の呼び出しdo_match_pathspec()がコミット75a6315f74( " ls-files:add pathspec matching for submodules"、2016-10-07、Git v2.11.0-rc0- mergeリストに追加されましたバッチ#11)と89a1f4aaf7( " dir:パス指定がdirの下のファイルと一致する場合は、そこに再帰する"、2019-09-17、Git v2.24.0-rc0)。

もちろん、do_match_pathspec()重要な利点がありましたmatch_pathspec()- match_pathspec()フラグを2つの値のいずれかにハードコードし、これらの新しい呼び出し元はフラグに他の値を渡す必要がありました。

また、do_match_pathspec()直接の呼び出しは正しくありませんでしたが、バグは単にfill_diretory()不要なディレクトリに再帰することを意味していたため、観察可能な最終出力に違いはありませんでした。

ディレクトリの下の個々のパスに対する後続のdos-this-path-matchチェックにより、これらの余分なパスがフィルターで除外されるため、間違った関数を使用した場合の唯一の違いは、不要な計算でした。

これらへの悪い呼び出しの2番目はdo_match_pathspec()、直接の移動またはコピー+編集のいずれかを介して、後のいくつかのリファクタリングに関係していました。

コミット777b420347( " dir:同期treat_leading_path()およびread_directory_recursive()"、2019-12-19、Git v2.25.0-rc0- merge)、8d92fb2927( " dir:replace exponential algorithm with a linear one" "、2020-04-01、Git v2.27.0を参照してください。 -rc0- バッチ#5にリストされているマージ)、および95c11ecc73(「エラーが発生しやすいAPIを修正、一致のみを返すようにする」、2020-04-01、Git v2.27.0-rc0- バッチ#5にリストされているマージ) 。fill_directory()

最後のものdo_match_pathspec()は個々のファイルでのの使用を導入したため、本来あるべきではない個々のパスが返されました。

do_match_pathspec()代わりにを呼び出すことの問題match_pathspec()は、 '`:!unwanted_pa​​th``などの否定されたパターンが無視されることです。

match_pathspec_with_flags()否定されたパターンを正しくチェックしながら特別なフラグを指定するニーズを満たす新しい関数を追加し、do_match_pathspec()他のユーザーが誤用しないように上記の大きなコメントを追加し、do_match_pathspec()代わりにmatch_pathspec()またはを使用するように現在の呼び出し元を修正しますmatch_pathspec_with_flags()

最後の注意点の1つは、を使用DO_MATCH_LEADING_PATHSPECするときに特別な考慮が必要なことDO_MATCH_EXCLUDEです。

ポイントDO_MATCH_LEADING_PATHSPECは、次のようなパススペックがある場合

*/Makefile

そして、私たちはディレクトリパスをチェックしています

src/module/component

一致すると見なして、ディレクトリに再帰できるようにします。これ_mightは、Makefile下に名前の付いたファイルがあるためです。

ただし、除外パターンを使用している場合、つまり次のようなパススペックがある場合

:(exclude)*/Makefile

次のようなディレクトリパスは必要ありません。

src/module/component

(負の)一致です。

そのディレクトリの下のどこかに「Makefile」という名前のファイルがある可能性がありますが、他のファイルも存在する可能性があり、そのディレクトリの下のすべてのファイルを事前に除外することはできません。再帰して個々のファイルをチェックする必要があります。

DO_MATCH_LEADING_PATHSPEC正のパス仕様に対してのみアクティブ化されるようにロジックを調整します。


7
複数のファイルを作成できますか?
ジャスティントーマス

12
@JustinThomas私は(まだテストされていません)そのパス除外パターンを複数回繰り返すことができる":(exclude)pathPattern1" ":(exclude)pathPattern2"ため、複数のフォルダー/ファイルを無視できると考えています。
VonC 2014年

7
BashシェルでGitを実行している場合は、':!sub'代わりにを使用してエラー回避しbash: ... event not foundます。":\!sub"動作しません。
ケニーエビット2017

1
@KennyEvitt編集とコメントをありがとうございます。視認性を高めるために、後者を回答に含めました。
VonC 2017

2
この機能に関する公式ドキュメントがどこにあるのか疑問に思う方は、git help glossarygit help -g[で提案されたものgit help] にリストされていることがわかりました)を参照してください。
ravron、

4

tl; dr: shopt -s extglob && git log !(unwanted/glob|another/unwanted/glob)

あなたが使用している場合バッシュを、あなたは使用することができるはず延長グロブ必要なファイルだけを取得する機能を:

$ cd -- "$(mktemp --directory)" 
$ git init
Initialized empty Git repository in /tmp/tmp.cJm8k38G9y/.git/
$ mkdir aye bee
$ echo foo > aye/foo
$ git add aye/foo
$ git commit -m "First commit"
[master (root-commit) 46a028c] First commit
 0 files changed
 create mode 100644 aye/foo
$ echo foo > bee/foo
$ git add bee/foo
$ git commit -m "Second commit"
[master 30b3af2] Second commit
 1 file changed, 1 insertion(+)
 create mode 100644 bee/foo
$ shopt -s extglob
$ git log !(bee)
commit ec660acdb38ee288a9e771a2685fe3389bed01dd
Author: My Name <jdoe@example.org>
Date:   Wed Jun 5 10:58:45 2013 +0200

    First commit

これをglobstar再帰アクションと組み合わせることができます。


7
存在しないファイルに影響するコミットは表示されません。非常に近く、素晴らしいハックです。
Anonymoose 2013年

-2

次のコマンドを使用すると、ファイルの変更を一時的に無視できます。

git update-index --skip-worktree path/to/file

今後、これらのファイルに対するすべての変更は無視されますgit statusgit commit -aあなたはそれらのファイルをコミットする準備ができたら、それを逆に、など、:

git update-index --no-skip-worktree path/to/file

通常どおりコミットします。


9
これは少し異なる状況に対処しているようです。すでに行われたコミットをフィルタリングすることはgit update-index --skip-worktreeありませんgit log
Anonymoose 2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.