【问题标题】:Allow different behaviour for external diff tool if git command is piped如果通过管道传输 git 命令,则允许外部差异工具的不同行为
【发布时间】:2022-09-29 00:23:29
【问题描述】:

我正在使用difftastic 来更好地可视化我的终端中的差异。这意味着我的配置是

git config --global diff.external difft

但是,当输出不是 tty 时,我宁愿让 git 使用它的内部 diff 工具(例如,与 git diff --no-ext-diff 相同,但无需我输入)。所以基本上

$ git diff # please use difft
# git diff | cat # please use no external diff tool

但是,我正在为此苦苦挣扎,因为我找不到将这些信息冒泡到我的差异工具中的方法。假设我有一些伪 diff 工具,它实际上只显示 argv 的内容、argc 的第一行并检查它的 stdout 是否是 tty:

#!/usr/bin/env ruby

require \"io/console\"
require \"logger\"
require \"pp\"

f = File.open(\"mygitdiff.log\", \"a\")
f.puts(\"\\n---- #{Time.now}\")
PP.pp(ARGV, f)
PP.pp(gets, f)
f.puts(\"STDOUT.tty? #{STDOUT.tty?}\")

无论我是否使用管道,此脚本都会打印相同的日志:

---- 2022-08-02 18:57:30 +0200
[\"bin/new\",
 \"/var/folders/v5/1p20ylgn0db5621r8wtdg5v80000gn/T//37FrIz_new\",
 \"c2a6c5aafc3485755f774cb3efcae4a2819a777f\",
 \"100755\",
 \"bin/new\",
 \"0000000000000000000000000000000000000000\",
 \"100755\"]
\"#!/usr/bin/env ruby\\n\"
STDOUT.tty? false

---- 2022-08-02 18:57:34 +0200
[\"bin/new\",
 \"/var/folders/v5/1p20ylgn0db5621r8wtdg5v80000gn/T//jaEmlN_new\",
 \"c2a6c5aafc3485755f774cb3efcae4a2819a777f\",
 \"100755\",
 \"bin/new\",
 \"0000000000000000000000000000000000000000\",
 \"100755\"]
\"#!/usr/bin/env ruby\\n\"
STDOUT.tty? false

如您所见,那里没有重大区别。您还有其他想法如何实现该目标吗?

还要注意第一行的argv,完全看不懂是什么意思

  • argv 值在GIT_EXTERNAL_DIFF 环境变量下的top level git manual page 中进行了描述。基本上git diff 可能必须提取一些仅由 Git 读取的内部 blob 对象内容,如果这样做,它会将提取的文件放入像/var/folders/v5/1p20y.... 这样的临时文件中,这样外部程序只需要读取一个普通的文件,而不是一些奇怪的压缩 Git 内部魔法。
  • 旁注:与其对 std(in,out,err)-is-a-tty 做一些深刻的魔术,不如设置一个运行 GIT_EXTERNAL_DIFF=whatever git diff 的 Git 别名(例如,设置 @987654334 @ 到 !GIT_EXTERNAL_DIFF=...)。然后,您的脚本可以对这两个文件调用 difftastic。然后只需运行git dt 来获得差异化差异,然后运行git diff 来获得常规差异。
  • 嘿,谢谢!我的目标是避免使用别名……但我猜 git 那时并没有给出这个选项。我想我可以有一个最后的手段,有一个包装 git 的命令,并在管道传输时设置一个 env 变量,然后我可以将它传输到我的 diff 工具
  • 是的,例如命名一个工具gd,然后让gd 检查stdout-is-a-tty 并运行您想要的任何命令。
  • @torek \“设置一个运行 GIT_EXTERNAL_DIFF=whatever git diff\ 的 Git 别名可能更明智”请注意,这正是我在 stackoverflow.com/a/73205880/341994 的评论中所说的。 OP仍然没有被说服。

标签: bash git git-diff


【解决方案1】:

一种解决方案是创建一个新的git bin 文件,并将其放在您的路径中的某个位置原始的 git 路径(对我来说是 /usr/bin)。包装器将根据标准输出状态决定是否应使用外部差异工具:

#!/usr/bin/env ruby

require "io/console"

if STDOUT.tty?
  system({ "GIT_EXTERNAL_DIFF" => "difft" }, "/usr/bin/git", *ARGV)
else
  system("/usr/bin/git", *ARGV)
end

exit($?.exitstatus)

C版使用速度

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    if (isatty(fileno(stdout)) && isatty(fileno(stderr))) {
        setenv("GIT_EXTERNAL_DIFF", "difft", 1);
    }

    execvp("/usr/bin/git", argv);
}

【讨论】:

    猜你喜欢
    • 2013-10-13
    • 2018-08-18
    • 2011-01-28
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-22
    • 2021-01-06
    相关资源
    最近更新 更多