如何让 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 忽略这些文件。这些文件应该被跟踪和提交。只是,大多数时候,我对看到它们不感兴趣。
相关问题:How to invert `git log --grep=<pattern>` or How to show git logs that don't match a pattern这是同一个问题,除了提交消息而不是路径。
2008 年关于此主题的论坛讨论:Re: Excluding files from git-diff这看起来很有希望,但线索似乎已经枯竭。
最佳答案
它现在已经实现(git 1.9/2.0,2014 年第一季度),引入了 pathspec magic :(exclude)
及其缩写形式 :!
强>在commit ef79b1f和 commit 1649612 , 经过
Nguyễn Thái Ngọc Duy (pclouds
) ,可以找到文档here .
您现在可以记录除子文件夹内容以外的所有内容:
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'
Don't forget to use single quotes or proper escaping in double quotes if you're running
git
in abash
shell, e.g.':!sub'
or":\!sub"
. Otherwise you will run intobash: ... event not found
errors
注意:Git 2.13(2017 年第 2 季度)将添加一个同义词 ^
到 !
参见 commit 859b7f1 , commit 42ebeb9 (2017 年 2 月 8 日)Linus Torvalds (torvalds
) .
(由 Junio C Hamano -- gitster
-- merge 于 commit 015fba3 ,2017 年 2 月 27 日)
pathspec magic: add '
^
' as alias for '!
'
The choice of '
!
' for a negative pathspec ends up not only not matching what we do for revisions, it's also a horrible character for shell expansion since it needs quoting.
因此添加“^
”作为排除路径规范条目的替代别名。
请注意,在 Git 2.28(2020 年第 3 季度)之前,在收集工作树中包括未跟踪路径在内的路径时,负路径规范的使用已被破坏。
参见 commit f1f061e (2020 年 6 月 5 日)作者:Elijah Newren (newren
) .
(由 Junio C Hamano -- gitster
-- merge 于 commit 64efa11 ,2020 年 6 月 18 日)
dir
: fix treatment of negated pathspecsReported-by: John Millikin
Signed-off-by: Elijah Newren
do_match_pathspec()
started life asmatch_pathspec_depth_1()
and for correctness was only supposed to be called frommatch_pathspec_depth()
.match_pathspec_depth()
was later renamed tomatch_pathspec()
, so the invariant we expect today is thatdo_match_pathspec()
has no direct callers outside ofmatch_pathspec()
.Unfortunately, this intention was lost with the renames of the two functions, and additional calls to
do_match_pathspec()
were added in commits 75a6315f74 ("ls-files
: add pathspec matching for submodules", 2016-10-07, Git v2.11.0-rc0 -- merge listed in batch #11) and 89a1f4aaf7 ("dir
: if our pathspec might match files under a dir, recurse into it", 2019-09-17, Git v2.24.0-rc0).Of course,
do_match_pathspec()
had an important advantge overmatch_pathspec()
--match_pathspec()
would hardcode flags to one of two values, and these new callers needed to pass some other value for flags.Also, although calling
do_match_pathspec()
directly was incorrect, there likely wasn't any difference in the observable end output, because the bug just meant thatfill_diretory()
would recurse into unneeded directories.Since subsequent does-this-path-match checks on individual paths under the directory would cause those extra paths to be filtered out, the only difference from using the wrong function was unnecessary computation.
The second of those bad calls to
do_match_pathspec()
was involved -- via either direct movement or via copying+editing -- into a number of later refactors.See commits 777b420347 ("
dir
: synchronizetreat_leading_path()
andread_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 -- merge listed in batch #5), and 95c11ecc73 ("Fix error-pronefill_directory()
API; make it only return matches", 2020-04-01, Git v2.27.0-rc0 -- merge listed in batch #5).The last of those introduced the usage of
do_match_pathspec()
on an individual file, and thus resulted in individual paths being returned that shouldn't be.The problem with calling
do_match_pathspec()
instead ofmatch_pathspec()
is that any negated patterns such as '`:!unwanted_path`` will be ignored.Add a new
match_pathspec_with_flags()
function to fulfill the needs of specifying special flags while still correctly checking negated patterns, add a big comment abovedo_match_pathspec()
to prevent others from misusing it, and correct current callers ofdo_match_pathspec()
to instead use eithermatch_pathspec()
ormatch_pathspec_with_flags()
.One final note is that
DO_MATCH_LEADING_PATHSPEC
needs special consideration when working withDO_MATCH_EXCLUDE
.The point of
DO_MATCH_LEADING_PATHSPEC
is that if we have a pathspec like*/Makefile
and we are checking a directory path like
src/module/component
that we want to consider it a match so that we recurse into the directory because it
_might
_ have a file namedMakefile
somewhere below.However, when we are using an exclusion pattern, i.e. we have a pathspec like
:(exclude)*/Makefile
we do NOT want to say that a directory path like
src/module/component
is a (negative) match.
While there might be a file named 'Makefile' somewhere below that directory, there could also be other files and we cannot pre-emptively rule all the files under that directory out; we need to recurse and then check individual files.
Adjust the
DO_MATCH_LEADING_PATHSPEC
logic to only get activated for positive pathspecs.
关于git - 使 'git log' 忽略某些路径的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5685007/