设置并使用 Meld 作为 git difftool 和 mergetool

Setting up and using Meld as your git difftool and mergetool

虽然这个问答中的大部分信息都可以在 Whosebug 上找到,但它散布在很多页面和其他错误或误导性的答案中。我花了一些时间拼凑出我想知道的一切。

有很多不同的程序可以用作您的 git difftool 和 mergetool,但对于哪个是 最好的 肯定没有达成共识(意见、要求和操作系统将明显不同)。

Meld 是一种流行的免费、开源和跨平台(UNIX/Linux、OSX、Windows)选择,如 Whosebug 问题,What's the best visual merge tool for Git?,其中提出 Meld 的答案是其他任何工具的 3 倍以上。

以下2个问题将在我下面的回答中得到解答:

注意:difftool 和 mergetool 不必使用相同的程序,可以为两者设置不同的程序。

如何设置和使用 Meld 作为我的 git difftool?

git difftool 使用 GUI 差异程序(即 Meld)显示差异,而不是在终端中显示差异输出。

尽管您可以使用 -t <tool> / --tool=<tool> 在命令行上设置 GUI 程序,但在 .gitconfig 文件中配置它更有意义。 [注意:请参阅底部关于转义引号和 Windows 路径的部分。]

# Add the following to your .gitconfig file.
[diff]
    tool = meld
[difftool]
    prompt = false
[difftool "meld"]
    cmd = meld "$LOCAL" "$REMOTE"

[注意:这些设置不会改变 git diff 的行为,它将继续照常运行。]

您使用 git difftool 的方式与使用 git diff 的方式完全相同。例如

git difftool <COMMIT_HASH> file_name
git difftool <BRANCH_NAME> file_name
git difftool <COMMIT_HASH_1> <COMMIT_HASH_2> file_name

如果配置正确,Meld window 将打开并使用 GUI 界面显示差异。

Meld GUIwindow面板的顺序可以通过cmd$LOCAL$REMOTE的顺序来控制,也就是说显示哪个文件在左窗格中,在右窗格中。如果你想要它们反过来,只需像这样交换它们:

    cmd = meld "$REMOTE" "$LOCAL"

最后,prompt = false 行只是停止 git 提示您是否要启动 Meld,默认情况下 git 会发出提示。


如何设置和使用 Meld 作为我的 git mergetool?

git mergetool 允许您使用 GUI 合并程序(即 Meld)来解决合并期间发生的合并冲突。

与 difftool 一样,您可以使用 -t <tool> / --tool=<tool> 在命令行上设置 GUI 程序,但是,和以前一样,在 .gitconfig 文件中配置它更有意义。 [注意:请参阅底部关于转义引号和 Windows 路径的部分。]

# Add the following to your .gitconfig file.
[merge]
    tool = meld
[mergetool "meld"]
    # Choose one of these 2 lines (not both!) explained below.
    cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"
    cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"

您不使用 git mergetool 来执行实际合并。在使用 git mergetool 之前,您使用 git 以通常的方式执行合并。例如

git checkout master
git merge branch_name

如果有合并冲突git会显示如下:

$ git merge branch_name
Auto-merging file_name
CONFLICT (content): Merge conflict in file_name
Automatic merge failed; fix conflicts and then commit the result.

此时 file_name 将包含带有合并冲突信息的部分合并文件(即包含所有 >>>>>>><<<<<<< 条目的文件)。

Mergetool 现在可用于解决合并冲突。你可以很容易地启动它:

git mergetool

如果配置正确,Meld window 将打开并显示 3 个文件。每个文件都将包含在其 GUI 界面的单独窗格中。

在上面的示例 .gitconfig 条目中,建议使用 2 行作为 [mergetool "meld"] cmd 行。事实上,高级用户可以通过各种方式配置 cmd 行,但这超出了本答案的范围。

此答案有 2 条备选 cmd 行,它们之间可以满足大多数用户的需求,对于希望将该工具提升到下一个复杂级别的高级用户来说,这将是一个很好的起点。

首先这里是参数的含义:

  • $LOCAL是当前分支(例如master)中的文件。
  • $REMOTE 是正在合并的分支中的文件(例如 branch_name)。
  • $MERGED是部分合并后的文件,里面有合并冲突信息
  • $BASE$LOCAL$REMOTE 的共享提交祖先,这就是说包含 $REMOTE 的分支最初创建时的文件。

我建议您使用:

[mergetool "meld"]
    cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"

或:

[mergetool "meld"]
    cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"
    # See 'Note On Output File' which explains --output "$MERGED".

选择是在$LOCAL$REMOTE之间使用$MERGED还是$BASE

无论哪种方式,Meld 都会显示 3 个窗格,左侧和右侧窗格为 $LOCAL$REMOTE,中间窗格为 $MERGED$BASE

在这两种情况下,中间窗格是您应该编辑以解决合并冲突的文件。不同之处在于您更喜欢哪个开始编辑位置; $MERGED 用于包含具有合并冲突信息的部分合并文件的文件或 $BASE 用于 $LOCAL$REMOTE 的共享提交祖先。 [因为 cmd 这两行都很有用,所以我将它们都保存在我的 .gitconfig 文件中。大多数时候我使用 $MERGED 行,而 $BASE 行被注释掉,但如果我想使用 $BASE 行,可以交换注释掉。]

关于输出文件的注意事项:不要担心 cmd 中使用了 --output "$MERGED",而不管 [=29= 中之前是否使用了 $MERGED$BASE ] 线。 --output 选项只是告诉 Meld git 想要保存冲突解决文件的文件名。无论您使用 $MERGED 还是 [=46],Meld 都会将您的冲突编辑保存在该文件中=] 作为您的起始编辑点。

编辑中间窗格解决合并冲突后,只需保存文件并关闭 Meld window。 Git 将自动进行更新,当前分支(例如 master)中的文件现在将包含您在中间窗格中结束的任何内容。

git 将通过将 .orig 附加到原始文件名来备份部分合并的文件,其中包含合并冲突信息。例如file_name.orig。在确认您对合并和 运行 您可能希望进行的任何测试感到满意后,可以删除 .orig 文件。

此时您可以执行提交以提交更改。

如果在 Meld 中编辑合并冲突时,您希望放弃使用 Meld,请退出 Meld,而不在中间窗格中保存合并解决方案文件。 git 将用消息 file_name seems unchanged 进行响应,然后询问 Was the merge successful? [y/n],如果您回答 n 则合并冲突解决将中止并且文件将保持不变。请注意,如果您在任何时候将文件保存在 Meld 中,那么您将不会收到来自 git 的警告和提示。 [当然你也可以只删除文件并用 git 为你制作的备份 .orig 文件替换它。]

如果您有超过 1 个文件存在合并冲突,那么 git 将为每个文件打开一个新的 Meld window,一个接一个,直到它们全部完成。它们不会同时全部打开,但是当您完成一个冲突的编辑并关闭 Meld 时,git 将打开下一个,依此类推,直到所有合并冲突都已解决。

live 项目上使用它之前,创建一个虚拟项目来测试 git mergetool 的使用是明智的。请务必在测试中使用包含 space 的文件名,以防您的 OS 要求您转义 cmd 行中的引号,请参见下文。


转义引号字符

某些操作系统可能需要转义 cmd 中的引号。经验不足的用户应该记住配置命令行应该使用包含 spaces 的文件名进行测试,如果 cmd 行不适用于包含 spaces 的文件名然后尝试转义引号。例如

cmd = meld \"$LOCAL\" \"$REMOTE\"

在某些情况下,可能需要更复杂的引号转义。下面的 Windows 路径链接的第一个包含一个对每个引号进行三重转义的示例。这很无聊,但有时是必要的。例如

cmd = meld \\"$LOCAL\\" \\"$REMOTE\\"

Windows 路径

Windows 用户可能需要在 Meld cmd 行中添加额外的配置。他们可能需要使用 meldc 的完整路径,该路径旨在从命令行在 Windows 上调用,或者他们可能需要或想要使用包装器。他们应该阅读下面链接的 Whosebug 页面,这些页面是关于为 Windows 设置正确的 Meld cmd 行的。由于我是 Linux 用户,我无法测试各种 Windows cmd 行,除了推荐使用我的示例并添加完整路径外,没有关于该主题的更多信息到 Meld 或 meldc,或将 Meld 程序文件夹添加到您的 path

  • Git Diff and Meld on Windows
  • How to set Meld as git mergetool
  • Git mergetool with Meld on Windows

使用 Meld

忽略尾随白色space

Meld 有许多可以在 GUI 中配置的首选项。

在首选项 Text Filters 选项卡中,有几个有用的过滤器可以在执行差异时忽略评论等内容。虽然有过滤器可以忽略 All whitespaceLeading whitespace,但没有忽略 Trailing whitespace 过滤器(这在 Meld 邮件列表中被建议添加,但在我的版本中不可用)。

忽略尾随白色space 通常非常有用,尤其是在协作时,并且可以在 Meld 首选项 Text Filters 选项卡中使用简单的正则表达式轻松手动添加。

# Use either of these regexes depending on how comprehensive you want it to be.
[ \t]*$
[ \t\r\f\v]*$

希望对大家有所帮助

虽然其他答案是正确的,但这是继续将 Meld 配置为您的视觉差异工具的最快方法。只是 copy/paste 这个:

git config --global diff.tool meld
git config --global difftool.prompt false

现在 运行 git difftool 在一个目录中,Meld 将为每个不同的文件启动。

旁注:Meld is surprisingly slow at comparing CSV files, and no Linux diff tool I've found is faster than this Windows tool called Compare It!(最后更新于 2010 年)。

在头脑中计算 $MERGED 中不同部分的差异并应用它可能会很复杂。在我的设置中,meld 可以帮助您直观地显示这些差异,使用:

[merge]
    tool = mymeld
    conflictstyle = diff3

[mergetool "mymeld"]
    cmd = meld --diff $BASE $REMOTE --diff $REMOTE $LOCAL --diff $LOCAL --output $MERGED

它看起来很奇怪,但提供了一个非常方便的工作流程,使用三个选项卡:

  1. 在选项卡 1 中,您会看到(从左到右)您应该在选项卡 2 中进行更改以解决合并冲突。

  2. 在选项卡 2 的右侧应用“您应该进行的更改”并将整个文件内容复制到剪贴板(使用 ctrl-a 和 ctrl-c)。

  3. 在选项卡 3 中将右侧替换为剪贴板内容。如果一切正确,您现在将看到 - 从左到右 - 与选项卡 1 中所示的变化相同(但上下文不同)。保存在此选项卡中所做的更改。

备注:

  • 不要编辑选项卡 1 中的任何内容
  • 不要在选项卡 2 中保存任何内容,因为这会在选项卡 3 中产生烦人的弹出窗口

我更喜欢将 meld 设置为单独的命令,如下所示:

git config --global alias.meld '!git difftool -t meld --dir-diff'

这使得它类似于此处的 git-meld.pl 脚本: https://github.com/wmanley/git-meld

然后您可以 运行

git meld

为Windows。 运行 这些命令在 Git Bash:

git config --global diff.tool meld
git config --global difftool.meld.path "C:\Program Files (x86)\Meld\Meld.exe"
git config --global difftool.prompt false

git config --global merge.tool meld
git config --global mergetool.meld.path "C:\Program Files (x86)\Meld\Meld.exe"
git config --global mergetool.prompt false

(如果您的文件路径不同,请更新 Meld.exe 的文件路径。)

对于Linux。 运行 这些命令在 Git Bash:

git config --global diff.tool meld
git config --global difftool.meld.path "/usr/bin/meld"
git config --global difftool.prompt false

git config --global merge.tool meld
git config --global mergetool.meld.path "/usr/bin/meld"
git config --global mergetool.prompt false

您可以使用此命令验证 Meld 的路径:

which meld

这是一个主要针对使用 Windows 的开发人员的答案,因为 diff 工具的路径语法与其他平台不同。

我使用 Kdiff3 作为 git mergetool,但是要将 git difftool 设置为 Meld,我 首先从 Meldmerge.org 安装最新版本的 Meld 然后将以下内容添加到我的全局 .gitconfig 使用:

git config --global -e

请注意,如果您希望 Sublime Text 3 而不是默认的 Vim 作为核心编辑器,您可以 将此添加到 .gitconfig 文件:

[core]
editor = 'c:/Program Files/Sublime Text 3/sublime_text.exe'

然后你添加inn Meld作为difftool

[diff]
tool = meld
guitool = meld 

[difftool "meld"]
cmd = \"C:/Program Files (x86)/Meld/Meld.exe\" \"$LOCAL\" \"$REMOTE\" --label \"DIFF 
(ORIGINAL MY)\"
prompt = false
path = C:\Program Files (x86)\Meld\Meld.exe

注意上面cmd中的前导斜杠,在Windows上是必要的。

也可以设置一个别名来显示当前的 git diff --dir-diff 选项。这将在 Meld 中列出更改的文件,这在您更改了多个文件时非常方便(确实是一种非常常见的情况)。

别名在 .gitconfig 文件中看起来像这样,在 [alias] 部分下面:

showchanges = difftool --dir-diff

为了显示我对代码所做的更改,我只需输入以下命令:

git showchanges

下图显示了 --dir-diff 选项如何显示已更改文件的列表(示例):

然后可以单击每个文件并显示 Meld 中的更改。

对于 Windows 10,我不得不将它放在我的 .gitconfig 中:

[merge]
  tool = meld
[mergetool "meld"]
  cmd = 'C:/Program Files (x86)/Meld/Meld.exe' $LOCAL $BASE $REMOTE --output=$MERGED
[mergetool]
  prompt = false

你需要知道的其他一切都写在上面 mattst 的这篇很棒的 中。

PS:出于某种原因,这仅适用于 Meld 3.18.x,而某些 Meld 3.20.x 版本会给我一个错误。它应该与 TomasMolina 在下面的评论中提到的 Meld 3.20.4 一起使用。

我使用 meld 遵循这个简单的设置。 Meld 是免费的开源 diff 工具。您将看到任何代码更改的文件和目录的并排比较。

  1. 使用 yum/apt 在 Linux 中安装 meld。
  2. 在 ~/.gitconfig 文件中添加以下行
[diff]
    tool = meld
  1. 转到您的代码库并键入以下命令以查看上次提交的更改与当前工作目录之间的差异(未暂存未提交的更改)

git difftool --dir-diff ./

  1. 要查看最后提交的代码和暂存代码之间的区别,请使用以下命令

git difftool --cached --dir-diff ./

除此之外,@mattst 的出色回答没什么可补充的。对于使用 Windows 子系统 Linux (WSL2) 的人,您可以在 Linux 中开发,但对 Windows.

使用 Meld
cmd = "/mnt/c/Program Files (x86)/Meld/Meld.exe" "$LOCAL" "$REMOTE"

一个警告:我的所有代码都在 Windows 驱动器上,而不是 WLS2 虚拟驱动器,所以 YMMV。