设置并将Meld用作git difftool和mergetool


255

尽管此问题和答案中的许多信息都可以在StackOverflow上获得,但它分散在许多页面上,以及其他错误或误导的答案中。我花了一段时间才整理出所有我想知道的东西。

可以使用很多不同的程序作为git difftool和mergetool,并且对于哪一个最好是没有共识(意见,要求和OS显然会有所不同)。

Meld是一个流行的免费,开源和跨平台(UNIX / Linux,OSX,Windows)选择,如StackOverflow问题所示,什么是Git的最佳可视合并工具?,其中建议Meld的答案获得的票数是其他任何工具的3倍以上。

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

  • 如何设置并将Meld用作git difftool?
  • 如何设置并将Meld用作git mergetool?

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


1
相关的帖子-一般如何在Git中配置diff工具
RBT

Answers:


423

如何设置并将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

如果配置正确,将打开一个窗口,使用GUI界面显示差异。

所述MELD GUI窗玻璃的顺序可通过顺序进行控制$LOCAL$REMOTEcmd,即哪个文件在右窗格中的左窗格和其被示出。如果您想要它们的另一种方法,只需像这样交换它们:

    cmd = meld "$REMOTE" "$LOCAL"

最后,该prompt = false行仅阻止git提示您是否要启动Meld,默认情况下git将发出提示。


如何设置并将Meld用作git mergetool?

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

像difftool一样,您可以在命令行上使用来设置GUI程序,-t <tool> / --tool=<tool>但是像以前一样,在.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 mergetoolgit以通常的方式执行合并。例如

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

如果配置正确,“混合”窗口将打开,显示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".

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

无论哪种方式合并将显示3个面板与$LOCAL$REMOTE在左,右窗格,要么$MERGED$BASE在中间窗格中。

在两种情况下,中间窗格都是您应编辑以解决合并冲突的文件。不同之处在于您希望使用哪个开始编辑位置;$MERGED对于其中包含与合并冲突信息或部分地合并的文件的文件$BASE为共享提交的祖先$LOCAL$REMOTE。[由于这两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可以删除该文件。

此时,您现在可以进行提交以提交更改。

如果在编辑“合并”中的合并冲突时希望放弃使用“合并”,则退出“合并”而不在中间窗格中保存合并解析文件。git会响应该消息file_name seems unchanged,然后询问Was the merge successful? [y/n],如果您回答,n则合并冲突解决方案将被中止,文件将保持不变。请注意,如果您随时将文件保存在Meld中,则不会收到git的警告和提示。[当然,您可以删除该文件,然后将其替换为.origgit为您制作的备份文件。]

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

git mergetool实际项目中使用虚拟项目之前,先创建一个虚拟项目以测试其使用是明智的。如果您的操作系统要求您转义该cmd行中的引号,请确保在测试中使用包含空格的文件名,请参见下文。


转义引号字符

某些操作系统可能需要将引号cmd转义。经验不足的用户应记住,应该使用包含空格的文件名来测试config命令行,如果命令行cmd不适用于包含空格的文件名,请尝试转义引号。例如

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

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

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

Windows路径

Windows用户可能需要将其他配置添加到“熔断cmd线”中。他们可能需要使用的完整路径meldc,该路径旨在在Windows上从命令行调用,或者他们可能需要或想要使用包装器。他们应该阅读下面链接的StackOverflow页面,这些页面是关于cmd为Windows 设置正确的Meld 行。由于我是Linux用户,因此我无法测试各种Windows cmd系统,除了建议使用我的示例并添加完整的Meld路径meldc或将Meld程序文件夹添加到您的Windows之外,无法进一步了解该主题path

使用Meld忽略尾随空格

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

在首Text Filters选项选项卡中,有几个有用的过滤器可以在执行差异时忽略诸如注释之类的内容。尽管有可以忽略All whitespace和的过滤器Leading whitespace,但没有忽略Trailing whitespace过滤器(在“合并邮件”列表中建议添加此过滤器,但在我的版本中不可用)。

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

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

希望对大家有帮助。


2
谢谢,使用[mergetool "meld"] cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"起来非常容易~/.gitconfig,然后只需解决中间平底锅中红色突出显示的冲突并保存即可!它应该是默认设置。
KrisWebDev '16

1
$LOCAL $MERGED $REMOTE这是我大多数时候使用的设置,当只有少数冲突可以解决时,它是很好的设置,也是我的默认设置。$LOCAL $BASE $REMOTE当有很多工作要做时,它真正地变成了自己,并且您确切地知道哪些代码节来自哪个文件。共同的承诺祖先可以是一个无忧无虑的伟大起点,有时冲突的突出显示实际上会成为障碍,而更清洁的基础是一种祝福。
马特

4
注意:如果您在OSX上并通过自制程序安装了融合,则输出参数将要求=如下所示:cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output="$MERGED"
Alteisen

2
对于安装.dmg并发现'meld'不在其路径中的Mac用户,请务必按照此处的另一组说明进行操作: yousseb.github.io/meld
KC Baltz

3
这比Git Configuration-git mergetool中的解释要好得多。非常感谢您解释$ MERGED和$ BASE之间的区别。使我免于发疯!
克里斯格

81

尽管另一个答案是正确的,但这是将Meld配置为可视化差异工具的最快方法。只需复制/粘贴以下内容:

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

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

旁注:Meld在比较CSV文件时出奇地慢,而且我发现没有Linux diff工具比Windows名为Compare It的工具快(最后更新于2010年)。


13
您可能也想在git config --global difftool.meld.cmd 'meld "$LOCAL" "$REMOTE"'那条线。这是“默认值”,但是一旦您配置mergetooldifftool它将在没有找到diff配置的情况下开始使用mergetool配置作为默认值。由于通常将合并配置为传递3个文件以进行三向合并,因此这意味着meld 差异窗口将突然具有三个没有意义的窗格。
BeeOnRope

为什么不检查的配置,一套以$后混帐配置-l
agfe2

56

对于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

1
运行git difftool时出现错误,“ diff工具融合不可用'D:\ software \ melddiff \ Meld.exe'”
艾伦·沃克

@AllenVork:您是否已确认Meld.exe在您指定的文件夹中?您可以在Git之外成功运行它吗?当您跑步时,Git会返回什么git config --global --get-regex diff*
MarredCheese

我解决了 我将其更改为“ D:/software/melddiff/Meld.exe”,并且可以使用。.gitconfig的格式是ubuntu而不是Windows。
艾伦·沃克

不应该是git config --global difftool.meld.path "C:\Program Files (x86)\Meld\Meld.exe"吗?
乔纳森·罗森

@AllenVork,您在cygwin中使用git吗?
阿德里安

25

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

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

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

然后就可以跑步

git meld

我刚刚和Cygwin一起工作,但是现在破产了。这样就解决了。谢谢!(尽管我--dir-diff根据个人喜好删除了该部分。)
PfunnyGuy

3

对于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给我一个错误。


1

这是主要针对使用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上是必要的。

也可以使用--dir-diff 选项设置别名以显示当前git diff 。这将列出Meld内部的已更改文件,当您更改了多个文件时(这是非常常见的情况),这非常方便。

别名在.gitconfig文件中[alias]部分下的外观如下:

showchanges = difftool --dir-diff

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

git showchanges

下图显示了--dir-diff选项如何显示已更改文件的列表(示例): 合并显示在$ LOCAL和$ REMOTE之间更改的文件列表

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


0

从$ MERGED的不同部分中计算出一个差异并加以应用可能会很复杂。在我的设置中,meld可通过以下方式直观地向您显示这些差异:

[merge]
    tool = mymeld
    conflictstyle = diff3

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

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

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

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

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

笔记:

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

这比单个选项卡中的3路合并(本地/基本/远程)更好吗?
安德烈Werlang

@AndréWerlang在单个选项卡中进行三向合并的优点是,您只需要处理冲突的更改(其他更改会自动合并)。但是,如果在三向合并中难以理解更改的内容以及如何以保留所有更改的方式合并的情况下,我更喜欢“我的”方法。如果在某个时候三向合并不再让我感到困惑,那么我可以切换回去。
mnieber '17

当用户mattst指出的那样,你可以使用$BASE,而不是$MERGED开始合并操作
安德烈Werlang
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.