让'git log'忽略某些路径的更改

jq6vz3qz  于 2023-02-11  发布在  Git
关注(0)|答案(3)|浏览(153)
    • 如何让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这看起来很有希望,但线程似乎已经枯竭。

c0vxltue

c0vxltue1#

它现在已经实现了(git 1.9/2.0,Q1 2014),引入了**pathspec magic :(exclude)和它的缩写形式:!**在commit ef79b1fcommit 1649612中,由Nguyễn Thái Ngọc Duy ( 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'

作为Kenny Evitt noted
如果您在bash shell中运行git,例如':!sub'":\!sub",请不要忘记使用单引号或在双引号中使用适当的转义。
注意:Git 2.13(2017年第2季度)将添加同义词^!
参见commit 859b7f1commit 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的意义在于如果我们有一个

*/Makefile

我们正在检查目录路径,如

src/module/component

我们要将其视为匹配项,以便递归到目录中,因为_might_在下面某处具有名为Makefile的文件。
但是,当我们使用排除模式时,例如,我们有一个如下所示的路径规范

:(exclude)*/Makefile

我们不想说目录路径像

src/module/component

是(负)匹配。
虽然在该目录下的某个地方 * 可能 * 有一个名为'Makefile'的文件,但也可能有其他文件,我们不能预先排除该目录下的所有文件;我们需要递归然后检查单个文件。
调整DO_MATCH_LEADING_PATHSPEC逻辑,使其仅对正路径规格激活。

f8rj6qna

f8rj6qna2#

时间;日期:shopt -s extglob && git log !(unwanted/glob|another/unwanted/glob)
如果您使用Bash,您应该能够使用**extended globbing**功能仅获取您需要的文件:

$ 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结合使用以实现递归操作。

ncgqoxb0

ncgqoxb03#

您可以使用以下命令 * 暂时 * 忽略文件中的更改:

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

接下来,git statusgit commit -a等会忽略对这些文件的所有更改。当您准备提交这些文件时,只需反向操作即可:

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

像往常一样提交。

相关问题