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

Setting up and using Meld as your git difftool and mergetool

尽管这个问题和答案中的大部分信息都可以在stackoverflow上找到,但它会散布在许多页以及其他错误或误导性的答案中。我花了一段时间才拼凑出我想知道的一切。

有很多不同的程序可以用作您的Git Difftool和Mergetool,对于哪种程序是最好的,肯定没有共识(意见、要求和OSE将明显不同)。

meld是一个流行的跨平台(unix/linux、osx、windows)选择,如stackoverflow问题所示,什么是Git最好的可视化合并工具?其中,提出meld的答案的投票数是任何其他工具的3倍以上。

以下两个问题将在我的回答中回答:

  • 如何设置和使用Meld作为Git Difftool?
  • 如何设置和使用Meld作为我的Git合并工具?

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


如何设置和使用Meld作为Git Difftool?

git difftool使用GUI diff程序(即meld)显示diff,而不是在终端中显示diff输出。好的。

虽然您可以使用-t / --tool=在命令行上设置GUI程序,但在.gitconfig文件中配置该程序更有意义。[注意:请参阅底部有关转义引号和窗口路径的部分。]好的。

1
2
3
4
5
6
7
# 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的方式完全相同。例如好的。

1
2
3
git difftool <COMMIT_HASH> file_name
git difftool <BRANCH_NAME> file_name
git difftool <COMMIT_HASH_1> <COMMIT_HASH_2> file_name

如果配置正确,将打开一个meld窗口,使用GUI界面显示diff。好的。

meld gui窗口窗格的顺序可以由cmd中的$LOCAL$REMOTE的顺序控制,即左窗格显示哪个文件,右窗格显示哪个文件。如果你想换一种方式,只需像这样交换它们:好的。

1
    cmd = meld"$REMOTE""$LOCAL"

最后,prompt = false行只是阻止git提示您是否要启动meld,默认情况下,git将发出提示。好的。如何设置和使用Meld作为我的Git合并工具?

Git合并工具允许您使用一个GUI合并程序(即meld)来解决合并期间发生的合并冲突。好的。

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

1
2
3
4
5
6
7
# 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进行合并。例如好的。

1
2
git checkout master
git merge branch_name

如果存在合并冲突,Git将显示如下内容:好的。

1
2
3
4
$ 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将包含带有合并冲突信息的部分合并文件(即包含所有>>>>>>><<<<<<<条目的文件)。好的。

现在可以使用合并工具来解决合并冲突。你可以很容易地从以下开始:好的。

1
git mergetool

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

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

这个答案有两条可选的cmd行,它们之间将满足大多数用户的需求,对于希望将工具带到下一个复杂程度的高级用户来说,这将是一个很好的起点。好的。

首先,参数的含义是:好的。

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

我建议您使用以下两种方法之一:好的。

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

或:好的。

1
2
3
[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;对于$LOCAL$REMOTE的共享提交祖先,$BASE。[由于两个cmd行都有用,所以我将它们都保存在.gitconfig文件中。大多数时候,我使用$MERGED行和$BASE行时都会被注释掉,但是如果我想使用$BASE行,注释掉的内容可以被交换过来。]好的。

输出文件说明:不要担心--output"$MERGED"cmd中使用,无论$MERGED$BASE是在cmd行中使用的。--output选项只告诉meld git希望将冲突解决文件保存在哪个文件名中。无论您是使用$MERGED还是$BASE作为起始编辑点,meld都会将冲突编辑保存在该文件中。好的。

编辑中间窗格以解决合并冲突后,只需保存文件并关闭合并窗口。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文件。]好的。

如果有多个合并冲突的文件,那么Git将为每个文件打开一个新的合并窗口,一个接一个,直到它们全部完成。它们不会同时打开,但是当您在一个中编辑完冲突并关闭meld后,git将打开下一个冲突,依此类推,直到所有合并冲突都解决为止。好的。

在将git mergetool用于活动项目之前,创建一个虚拟项目来测试它的使用是明智的。请确保在测试中使用包含空格的文件名,以防操作系统要求您转义cmd行中的引号,请参见下面的内容。好的。转义引号字符

有些操作系统可能需要对cmd中的报价进行转义。经验不足的用户应该记住,配置命令行应该使用包含空格的文件名进行测试,如果cmd行不使用包含空格的文件名,则尝试转义引号。例如好的。

1
cmd = meld "$LOCAL" "$REMOTE"

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

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

号Windows路径

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

  • 窗口上的Git Diff和Meld
  • 如何将meld设置为git mergetool
  • Git合并工具与Windows上的Meld

忽略带有meld的尾随空格

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

在Preferences Text Filters选项卡中,有几个有用的过滤器可以在执行差异时忽略注释等内容。尽管有过滤器可以忽略All whitespaceLeading whitespace,但没有忽略Trailing whitespace过滤器(建议在meld邮件列表中添加此过滤器,但在我的版本中不提供)。好的。

忽略尾随空格通常非常有用,尤其是在协作时,可以使用meld preferences Text Filters选项卡中的简单正则表达式轻松地手动添加尾随空格。好的。

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

我希望这对每个人都有帮助。好的。好啊。


虽然另一个答案是正确的,但下面是将meld配置为可视diff工具的最快方法。只需复制/粘贴:

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

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

旁注:meld在比较csv文件时速度惊人地慢,我发现没有任何一个linux diff工具比这个叫做compare it的windows工具快!(最近更新于2010年)。


对于Windows。在git bash中运行以下命令:

1
2
3
4
5
6
7
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中运行以下命令:

1
2
3
4
5
6
7
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的路径:

1
which meld


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

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

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

你就可以跑了

1
git meld


对于Windows 10,我必须将其放入.gitconfig:

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

你所需要知道的一切都写在这个超级答案中,由马特在上面更进一步。

PS:出于某种原因,这只对meld 3.18.x有效,meld 3.20.x给了我一个错误。


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

我使用kdiff3作为git合并工具,但要将git difftool设置为meld,我首先从meldmerge.org安装最新版本的meld然后使用将以下内容添加到我的global.gitconfig中:

1
git config --global -e

注意,如果您希望将文本3升华而不是默认的VIM作为核心编辑器,则可以将此添加到.gitconfig文件:

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

然后你加上旅馆作为比较工具

1
2
3
4
5
6
7
8
9
[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

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

也可以设置一个别名,用--dir diff显示当前的git diff。选项。这将列出meld中更改的文件,当您更改了多个文件时,这非常方便(实际上是一个非常常见的场景)。

在.gitconfig文件的[alias]部分下面,别名如下所示:

1
showchanges = difftool --dir-diff

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

1
git showchanges

下图显示了--dir diff选项如何显示已更改文件的列表(示例):Meld showing list of files with changes between the $LOCAL and $REMOTE

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


从$merged中的不同部分计算头部的diff并应用它可能会很复杂。在我的设置中,meld通过以下方式帮助您直观地显示这些差异:

1
2
3
4
5
6
[merge]
    tool = mymeld
    conflictstyle = diff3

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

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

  • 在选项卡1中,可以看到(从左到右)在选项卡2中为解决合并冲突而应进行的更改。

  • 在选项卡2的右侧,应用"应做的更改"并将整个文件内容复制到剪贴板(使用ctrl-a和ctrl-c)。

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

  • 笔记:

    • 不编辑选项卡1中的任何内容
    • 不要在选项卡2中保存任何内容,因为这样会在选项卡3中弹出令人讨厌的内容。