- 如何让
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这看起来很有希望,但线程似乎已经枯竭。
3条答案
按热度按时间c0vxltue1#
它现在已经实现了(git 1.9/2.0,Q1 2014),引入了**pathspec magic
:(exclude)
和它的缩写形式:!
**在commit ef79b1f和commit 1649612中,由Nguyễn Thái Ngọc Duy (pclouds
)实现,文档可以在这里找到。现在,您可以记录除子文件夹内容以外的所有内容:
也可以排除该子文件夹中的特定元素
sub
中的任何给定文件:您可以使排除不区分大小写!
作为Kenny Evitt noted
如果您在
bash
shell中运行git
,例如':!sub'
或":\!sub"
,请不要忘记使用单引号或在双引号中使用适当的转义。注意:Git 2.13(2017年第2季度)将添加同义词
^
到!
参见commit 859b7f1、commit 42ebeb9(2017年2月8日)和Linus Torvalds (
torvalds
)。(由Junio C Hamano --
gitster
--合并到commit 015fba3,2017年2月27日)路径规范魔法:添加"
^
"作为"!
"的别名选择'
!
'作为负的路径规范,结果不仅与我们对修订版所做的不匹配,而且对于shell扩展来说也是一个可怕的字符,因为它需要引用。因此,添加'
^
'作为排除pathspec条目的替代别名。请注意,在Git 2.28(Q3 2020)之前,在收集工作树中包含未跟踪路径的路径时,使用否定路径规范是不可行的。
参见commit f1f061e(2020年6月5日)。
(2020年6月18日由Junio C Hamano --
gitster
--合并至commit 64efa11)dir
:否定路径规范的固定处理报告人:约翰·米利金
签署人:伊莱贾·纽伦
do_match_pathspec()
以match_pathspec_depth_1()
的形式出现,为了正确起见,只应该从match_pathspec_depth()
调用。match_pathspec_depth()
后来被重命名为match_pathspec()
,因此我们今天所期望的不变条件是do_match_pathspec()
在match_pathspec()
之外没有直接调用者。不幸的是,这一意图随着两个函数的重命名而消失,并且在提交75a6315f74("
ls-files
:添加子模块的路径规范匹配",2016年10月7日,Git v2.11.0-rc0--batch #11中列出的merge)和89a1f4aaf7("dir
:如果我们的pathspec可能匹配某个目录下的文件,递归到它",2019 - 09 - 17,Git v2.24.0-rc0).当然,
do_match_pathspec()
比match_pathspec()
有一个重要的优势--match_pathspec()
会将标志硬编码为两个值中的一个,而这些新的调用者需要为标志传递一些其他的值。此外,尽管直接调用
do_match_pathspec()
是不正确的,但在可观察到的最终输出中可能没有任何差异,因为该bug只是意味着fill_diretory()
将递归到不需要的目录中。由于随后对目录下的各个路径进行does-this-path-match检查会导致过滤掉那些额外的路径,因此与使用错误函数的唯一区别是不必要的计算。
对
do_match_pathspec()
的第二个错误调用涉及到--通过直接移动或通过复制+编辑--许多后来的重构。参见提交777b420347("
dir
:同步treat_leading_path()
和read_directory_recursive()
",2019年12月19日,Git v2.25.0-rc0--merge),8d92fb2927("dir
:用线性算法替换指数算法",2020年4月1日,Git v2.27.0-rc0--batch #5中列出的merge),以及95c11ecc73("修复易出错的fill_directory()
API;使它只返回匹配项",2020年4月1日,Git v2.27.0-rc0--merge列在batch #5中)。最后一个例子介绍了在单个文件上使用
do_match_pathspec()
,因此导致返回了不应该返回的单个路径。do_match_pathspec()
而不是match_pathspec()
的问题是,任何取反的模式(如':! unwanted_path')都将被忽略**。添加一个新的
match_pathspec_with_flags()
函数,以满足指定特殊标志的需要,同时仍然正确地检查求反模式,在do_match_pathspec()
上方添加一个大注解,以防止其他人误用它,并更正do_match_pathspec()
的当前调用方,以使用match_pathspec()
或match_pathspec_with_flags()
。最后要注意的是,在使用
DO_MATCH_EXCLUDE
时,DO_MATCH_LEADING_PATHSPEC
需要特别考虑。DO_MATCH_LEADING_PATHSPEC
的意义在于如果我们有一个我们正在检查目录路径,如
我们要将其视为匹配项,以便递归到目录中,因为
_might
_在下面某处具有名为Makefile
的文件。但是,当我们使用排除模式时,例如,我们有一个如下所示的路径规范
我们不想说目录路径像
是(负)匹配。
虽然在该目录下的某个地方 * 可能 * 有一个名为'Makefile'的文件,但也可能有其他文件,我们不能预先排除该目录下的所有文件;我们需要递归然后检查单个文件。
调整
DO_MATCH_LEADING_PATHSPEC
逻辑,使其仅对正路径规格激活。f8rj6qna2#
时间;日期:
shopt -s extglob && git log !(unwanted/glob|another/unwanted/glob)
如果您使用Bash,您应该能够使用**extended globbing**功能仅获取您需要的文件:
您可以将其与
globstar
结合使用以实现递归操作。ncgqoxb03#
您可以使用以下命令 * 暂时 * 忽略文件中的更改:
接下来,
git status
、git commit -a
等会忽略对这些文件的所有更改。当您准备提交这些文件时,只需反向操作即可:像往常一样提交。