【问题标题】:Why doesn't `git diff` invoke external diff tool?为什么`git diff`不调用外部差异工具?
【发布时间】:2014-09-17 22:19:50
【问题描述】:

在我的存储库中,如果我键入

$ git diff some-file

$ git difftool some-file

我得到了终端差异显示。我认为这不应该发生,因为我已经设置了一个外部差异工具,如git config -l的输出所示:

$ git config -l
user.name=blah blah
user.email=blah blah
http.sslverify=true
diff.external=/home/daniel/bin/git-diff  <--This is the important line
push.default=simple
core.filemode=false
core.editor=gedit
alias.tree=log --all --graph --decorate=short --color --format=format:'%C(bold blue)%h%C(reset) %C(auto)%d%C(reset)
         %C(black)[%cr]%C(reset)  %x09%C(black)%an: %s %C(reset)'
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
remote.origin.url=https://daniel@skynet/git/pyle.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
branch.daniel.remote=origin
branch.daniel.merge=refs/heads/daniel

diff.external 行中引用的 git-diff 文件如下所示

#!/bin/bash

meld $2 $5

git diff 为什么不调用 meld?

如果我设置git config -l 具有以下行,我会得到相同的行为:

diff.tool = meld

diff.external = usr/bin/meld

注意:我机器上的其他仓库没有这个问题。

相关但不等价的 SO 问题:

  1. What is the difference between git diff and git difftool?
  2. Cannot make git diff use diff.external for external diff tool

【问题讨论】:

  • 你为什么使用第二个和第五个参数?
  • @merlin2011:我的理解是 git diff 将七个参数传递给外部 diff 工具,而 meld 只需要其中两个。

标签: git diff meld


【解决方案1】:

我得到了终端差异显示。我这不应该发生,因为我已经设置了一个外部差异工具

是的,它应该:diff.external 用于“终端差异显示”。

(来自git config man page

diff.external

如果设置了此配置变量,不会使用内部差异机制生成差异,而是使用给定的命令
可以用GIT_EXTERNAL_DIFF 环境变量覆盖。
该命令使用 git(1) 中“git Diffs”中描述的参数调用。注意:如果您只想在文件的子集上使用外部差异程序,您可能需要改用gitattributes(5)

question you link 解释了为什么 meld 不能扮演“外部差异”的角色。

Viewing a diff visually with another tool 完成:

git difftool --dir-diff shaOfHisCheckIn^!
git difftool --tool=meld --dir-diff shaOfHisCheckIn^!
git difftool -t meld -d shaOfHisCheckIn^!

meld 可以在 Windows 上配置为 difftool:请参阅“Git Diff and Meld on Windows”。


如果你想为 git diff 配置 meld,你可以(on Ubuntu) use the diff.external, but with a wrapper script:

使用以下内容创建一个名为 git-diff.sh 的文件:

#!/bin/bash
meld "$2" "$5" > /dev/null 2>&1

将其保存到/usr/local/bin 等位置,赋予其可执行权限:

$ sudo mv git-diff.sh /usr/local/bin/
$ sudo chmod +x /usr/local/bin/git-diff.sh

最后一步是打开您的$HOME/.gitconfig 文件并添加以下几行:

[diff]
        external = /usr/local/bin/git-diff.sh

下次您在有更改的 Git 项目中键入 git diff 时,Meld 将启动,向您显示拆分窗格差异查看器。
请注意,在打开下一个差异查看器之前,您需要关闭打开的 meld 实例。


willthe comments 中的注释:

该包装脚本在我的 Ubuntu 系统上运行良好。

我确实发现了一个问题:我像这样分离了meld 命令:

meld "$2" "$5" > /dev/null 2>&1 &

一直无法打开 $2 文件(临时文件)。
发生什么了?好吧,一旦包装器退出,git 就会删除 $2
我的建议,如果您想分离复制 tmp 文件,请调用 meld 并自己删除 tmp 文件。

将提议the gist gist-meld.bash,使用meld --newtab,作为seen here

#!/bin/bash
#  * expects meld to be on your default PATH
#
function detach_meld()
{
    local f1="/tmp/mld1-$(basename "$1")"
    local f2="/tmp/mld2-$(basename "$2")"
    
##  echo "f1 = ${f1}"
##  echo "f2 = ${f2}"

    cp "$1" "${f1}"
    cp "$2" "${f2}"
#
    (meld  --newtab  "${f1}" "${f2}" ; rm  "${f1}"  "${f2}" ) > /dev/null 2>&1  &    
}

detach_meld  "$2"  "$5"

【讨论】:

  • git difftool 似乎是解决方案。我尝试使用包装脚本,但由于某种原因不起作用。
  • 该包装脚本在我的 Ubuntu 系统上运行良好。我确实发现了一个gottcha。我将meld 命令分离为:meld "$2" "$5" &gt; /dev/null 2&gt;&amp;1 &amp;。一直无法打开$2 文件(临时文件)。发生什么了?好吧,一旦包装器退出,git 就会删除 $2。我的建议是,如果您想分离 tmp 文件,请调用 meld 并自己删除 tmp 文件。
  • @will 感谢您的反馈。我已将您的评论包含在答案中以提高知名度。
  • @VonC .. 又是我。今天我发现了分支差异操作:git diff main...mybranch——当你使用meld包装脚本时,它比较两个临时文件。由于上述相同的“临时文件”原因,一个始终为空白。我更改了包装脚本以制作两个副本临时文件——Works!!
  • 我提出一个要点:git-meld.bash。如果您确实比较分支,请准备好弹出大量融合窗口。分支中的每个文件一个。如果您知道如何在 meld 中将文件作为选项卡打开,请留下一个表扬?
【解决方案2】:

似乎git diff(至少,从git 版本1.7.12.4 开始)不会对处于“都已修改”状态的文件运行除内部的、仅限控制台的差异之外的任何内容。不过,git mergetool 可以处理此类文件。

【讨论】:

  • 对于 git 1.9.1 版本仍然如此,真是烦人!我只是浪费了一个小时试图弄清楚为什么我的 difftool 的 git config 设置突然停止工作。
  • git version 2.5.4 (Apple Git-61) 上的情况仍然如此。仅控制台的 3 路合并工作流程是一个很大的痛点。功能强大的控制台原生差异工具确实非常短缺。我相信我将采取的路径是允许 git 将冲突标记转储到文件中,然后使用我将编写的简单工具来处理这些以生成可读的差异输出。
  • 啊哈! @trebor-rude,你刚刚挽救了我的理智,想知道为什么我的 difftool 选择都不起作用
【解决方案3】:

我通常只想检查我即将签入的更改是否正确。所以我遵循了here 建议的程序(类似于 VonC 指出的程序)。但是,运行git difftool 仍然没有打开融合。然后我创建了一个别名:

alias git-diff='git difftool $(git rev-parse HEAD)'

将其保存在您的 .bashrc 或 .zshrc 或您的 shell 的相应配置中。这实质上是将分支的状态与分支上的先前提交进行比较。

执行git-diff 以查看每个文件的更改或git-diff --dir 以查看目录视图中的所有更改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    相关资源
    最近更新 更多