【问题标题】:How can I perform a git diff using a wildcard search?如何使用通配符搜索执行 git diff?
【发布时间】:2022-12-15 04:39:42
【问题描述】:

当我执行 git status 时,我得到如下信息:

modified   a/mega/super/duper/long/path/to/the/file/foo.php
modified   a/mega/super/duper/long/path/to/the/file/another/folder/bar.php
modified   a/mega/super/duper/long/path/to/the/file/someotherfolder/blahblah.php

如果我想查看 bar.php-file(第 2 行)有什么变化,我该怎么做?

我希望能够做这样的事情:

git diff */bar.php
git diff bar.php

那个 git 可以用制表符完成或读懂我的想法。 :-)


想法1:写出来:

必须写的内容非常广泛:

git diff a/mega/super/duper/long/path/to/the/file/another/folder/bar.php

思路二:使用鼠标+复制/粘贴

我可以使用鼠标和复制粘贴,但这似乎也是一个糟糕的解决方案。将手指从键盘上移开通常不是解决方案。我必须做很多。

思路三:Git添加补丁

通过运行git add -p,我自动进入交互模式,能够执行a bunch of stuff。但这并不是我所追求的。

想法4:使用sed

我发现了这个问题:git diff just the first file,这表明:

git diff $(git diff --name-only | sed -n '1 p')

然后我可以设置一个 Alfred-sn-p 或打印它的 bash 脚本。此后,我可以将 1 更改为我想查看的文件数。

这接近于好。

想法 5:将 nth 文件的文件名复制到剪贴板的 Bash 脚本

另一种方法是制作一个 bash 脚本,将 nth 文件复制到剪贴板。然后我可以用两个快速命令来完成,就像这样:

./copy-file-name-for-first-file-in-git-status.sh     # Named to make easy to understand.
git diff [PASTE]

这实际上也可以解决下面的奖金问题。


奖金问题 - git addgit log 的相同问题

同样的问题存在,如果我不想做git add .,但想在深层嵌套文件夹中单独添加文件。然后我还必须为每个文件键入整个路径。

【问题讨论】:

  • 您可以制作一个 bash 函数,使用 find 获取某个文件的完整路径,然后为您调用 git diff
  • git diff 可以接受多个值。但是您可以将其包含在函数中。你期望发生什么?总是从find开始走第一条路?如果找到多个文件则取消?
  • git diff -- **/bar.php 工作正常(当 shopt -s globstar 之前已运行时)。你想问什么?
  • 顺便说一句,anything $(find ...) 是一种反模式,代码天生就有问题,should never be run by anyone。一个典型的更安全的替代品看起来像find ... -exec anything {} +
  • 顺便说一句,要注意的一件事是对 glob 进行评估通过你的外壳,在您正在运行的命令(如 git)启动之前。所以git没有机会寻找历史的不存在的文件:glob 被替换为当前存在的匹配文件列表在 git 启动之前只要存在任何此类文件。

标签: bash git


【解决方案1】:

为了便于使用,Git 别名而不是外部函数怎么样?您可以将它放在您的全局配置中,而不必费心记住新函数或将其添加到路径中。

正如您在下面看到的那样,它将仅使用一个(可能)非常短的子字符串来运行差异来标识文件。这是一种正则表达式搜索,当您指定一个不匹配任何文件或匹配多个文件的正则表达式时,它会优雅地处理案例。

将此添加到您的 git 配置中:

[alias]
        diffr = "!a() { myfile=$(git status | awk '/modified:/ {print $2}' |grep "$1") ; cnt=$(git status |awk '/modified:/ {print $2}'|grep "$1" |wc -l) ;if [ $cnt -eq 1 ] ; then git diff $myfile;else printf '%s Matched %s files
' $1 $cnt;fi; if ! [ $cnt -eq 0 ] ; then git status |grep "$1"; fi; }; a"

git diffr "<regex>"运行它

这是测试回购的状态:

me@mypc MINGW64 /c/repos/aliastest (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   mega/super/duper/long/path/to/the/file/another/folder/bar.php
        modified:   mega/super/duper/long/path/to/the/file/foo.php
        modified:   mega/super/duper/long/path/to/the/file/someotherfolder/blahblah.php

no changes added to commit (use "git add" and/or "git commit -a")

这是名称中带有“foo”的文件的成功差异(当它是唯一匹配的文件时):

me@mypc MINGW64 /c/repos/aliastest (master)
$ git diffr foo
warning: LF will be replaced by CRLF in mega/super/duper/long/path/to/the/file/foo.php.
The file will have its original line endings in your working directory
diff --git a/mega/super/duper/long/path/to/the/file/foo.php b/mega/super/duper/long/path/to/the/file/foo.php
index 90be1f3..294186e 100644
--- a/mega/super/duper/long/path/to/the/file/foo.php
+++ b/mega/super/duper/long/path/to/the/file/foo.php
@@ -1 +1 @@
-before
+after

这是它处理正则表达式匹配多个文件的无效情况的方式:

me@mypc MINGW64 /c/repos/aliastest (master)
$ git diffr "folder/b[al]"
folder/b[al] Matched 2 files
        modified:   mega/super/duper/long/path/to/the/file/another/folder/bar.php
        modified:   mega/super/duper/long/path/to/the/file/someotherfolder/blahblah.php

这里它正在处理一个没有文件匹配的正则表达式:

me@mypc MINGW64 /c/repos/aliastest (master)
$ git diffr "sirnotappearinginthisfilm"
sirnotappearinginthisfilm Matched 0 files

除了所有转义之外,它只是一个普通的 Bash 函数,因此您可以随意编辑它。您可以调用一个单独的可执行文件来代替 Bash 函数,但这样您就会有外部依赖项。 对脚本稍作调整也可以满足您的 git add 请求。如果我有时间写它,我会把它贴在这里。 git log 的类似功能似乎完全不同,因为您可能获得的结果可能非常巨大。

我有过同样的愿望,希望将我的手放在键盘上,也有同样的 Git 在命令行上的问题,但直到现在我还没有真正想到如何解决这个问题。从现在开始,无论其他人是否使用此解决方案,我都会使用此解决方案,因此感谢您的建议。

【讨论】:

    【解决方案2】:

    我认为这一定是相对较新的功能,因为有几个关于堆栈溢出的问题表明它不起作用,但这对我有用:

    git diff **/bar.php 
    

    【讨论】:

      猜你喜欢
      • 2022-01-11
      • 2011-08-10
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多