为什么`git diff`不适用于进程替换?

use*_*928 16 git bash git-diff

为什么不git diff使用流程替换?

$ echo hallo > hallo
$ echo holla > holla

$ git diff hallo holla  # works

$ git diff hallo <(cat holla)  # works not

diff --git a/hallo b/hallo
deleted file mode 100644
index 4cf5aa5..0000000
--- a/hallo
+++ /dev/null
@@ -1 +0,0 @@
-hallo
diff --git a/dev/fd/63 b/dev/fd/63
new file mode 120000
index 0000000..864a6ca`
Run Code Online (Sandbox Code Playgroud)

与...相同git diff --no-index.

它适用于普通diff.cat只是一个简单的例子,可以用一个非平凡的sed表达式代替.

解决方法:

$ cat holla | git diff hallo -  # works
Run Code Online (Sandbox Code Playgroud)

但是如果两个参数都应该受到进程替换的影响,那就不会起作用,就像许多diff和进程替换的例子中所描述的那样.

mar*_*cin 12

git diff不适用于进程替换,因为忽略了添加了进程替换处理的补丁.

  • 该补丁于 2014 年提交(并被忽略) - 到 2022 年,我们_仍然_仍然遭受同样缺乏进程替代的困扰! (2认同)

Von*_*onC 6

不再 ” unsupported file type”!

\n

现在,git diff --no-index holla <(cat hallo)应该可以工作了,正如这里讨论的那样

\n

在 Git 2.42(2023 年第 3 季度)中,“ git diff --no-indexman学会了从命名管道中读取数据,就好像它们是常规文件一样,以允许“ git diff <(process) <(substitution)”某些 shell 支持。

\n

请参阅Phillip Wood的提交 1e3f265提交 df52146提交 4e61e0f提交 4981984(2023 年 7 月 05 日。\n (由Junio C Hamano 合并 -- --提交 9187b27中,2023 年 7 月 17 日)phillipwood
gitster

\n
\n

diff --no-index:支持从命名管道读取

\n

帮助者:Junio C Hamano
\n签署者:Phillip Wood

\n
\n
\n

在某些 shell 中,例如 bash 和 zsh,可以使用命令替换将命令的输出作为文件参数提供给另一个进程,如下所示:

\n
diff -u <(printf "a\\nb\\n") <(printf "a\\nc\\n")\n
Run Code Online (Sandbox Code Playgroud)\n

但是,此语法不会使用“ git diff --no-index( man ) " 产生有用的结果。
\n在 macOS 上,该命令的参数是 /dev/fd 下的命名管道,并且 \' git diff\' 不知道如何处理命名管道。
\在 Linux 上,参数是管道的符号链接,因此git diff有助于区分这些符号链接,比较它们的目标,例如“ pipe:[1234]”和“ pipe:[5678]”。

\n

为了解决这个问题,“ diff --no-index”被更改,以便如果命令行上给定的路径是命名管道或解析为命名管道的符号链接,那么我们读取数据以与该管道进行比较。
\n这是通过概括已经存在的代码来实现的,该代码用于在用户传递路径“ -”时处理从 stdin 的读取。

\n

如果用户尝试将命名管道与目录进行比较,那么我们就会像尝试将 stdin 与目录进行比较一样死亡。

\n

由于 POSIX 不支持进程替换,因此通过使用管道和管道的符号链接来测试此更改。

\n
\n
\n

注意:“ git diff --no-index-R <(one) <(two)` " ( man ) " 无法正常工作,已使用 Git 2.43(2023 年第 4 季度)进行更正。

\n

请参阅Ren\xc3\xa9 Scharfe ( )的提交 48944f2(2023 年 9 月 10 日)。\n (由Junio C Hamano 合并 -- --提交 7435d51中,2023 年 9 月 20 日)rscharfe
gitster

\n
\n

diff --no-index:用标准输入修复-R

\n

报告人:Martin Storsj\xc3\xb6
\n签署人:Ren\xc3\xa9 Scharfe

\n
\n
\n

-R给定时,queue_diff()交换两个文件的模式和名称变量以产生反向差异。
\n 1e3f265 ("diff --no-index: 支持从命名管道读取", 2023-07-05, Git v2.42.0-rc0 -- merge returned in batch #11 ) 添加了指示文件是否特殊的变量,即命名管道或-标准输入。
\n不过,这些新变量没有交换,这破坏了 stdin 与 with 的处理-R
\n像其他元数据变量一样交换它们。

\n
\n


Sch*_*ern 2

git diff不能用作 的替代品diff。它不会区分磁盘上的两个任意文件,除非您位于 Git 存储库之外传入标志--no-index

$ git diff --no-index holla hallo
diff --git a/holla b/hallo
index 5cf9d44..ba1a6c1 100644
--- a/holla
+++ b/hallo
@@ -1 +1,2 @@
-holla
+hallo
+new line

$ cat hallo | git diff --no-index holla -
diff --git a/holla b/-
index 5cf9d44..0000000 100644
--- a/holla
+++ b/-
@@ -1 +1,2 @@
-holla
+hallo
+new line
Run Code Online (Sandbox Code Playgroud)

这一切都有效,因为git diff只是从 STDIN 读取,而且这是如此标准,他们必须努力使其不起作用。

至于流程替代...

$ git diff --no-index holla <(cat hallo)
error: /dev/fd/63: unsupported file type
fatal: cannot hash /dev/fd/63
Run Code Online (Sandbox Code Playgroud)

我可以从中解释的是,Git 正在尝试在命名管道上运行其哈希算法,否则 Git 无法操作,并且会拒绝,因为它不是文件,而是管道。没有理由在 Git 存储库中拥有管道,因此也没有理由git diff支持它们。

git diff用作的替代品是个坏主意diff。Git 是一个适用于文件的内容跟踪器,而不是通用的差异工具。“我将在 Git 存储库之外默默地进行类似 diff 的工作”是那些过于灵活的设计选择之一,只会让用户感到困惑。

  • “使用 git diff 来替代 diff 是一个坏主意。” 多年来我一直将 diff 别名为“git diff --no-index”,并且 99% 的时间它都更好。只有偶尔出现像此流程替换问题这样的边缘情况。 (21认同)