使用 Meld 作为您的 Git 比较工具和合并工具的设置和使用方法

404
虽然这个问题和答案中的许多信息都可以在StackOverflow上找到,但是它们分散在许多页面和其他答案中,其中一些答案要么是错误的,要么是误导性的。我花了一些时间才把我想知道的所有东西拼凑起来。
有很多不同的程序可以用作git difftool和mergetool,显然没有共识认为哪个是最好的(意见、要求和操作系统显然会有所不同)。Meld是一种流行的免费、开源、跨平台(UNIX/Linux、OSX、Windows)选择,如在StackOverflow问题What's the best visual merge tool for Git?中所示,提出Meld的答案比任何其他工具的票数都多3倍以上。
下面的2个问题将在我的回答中得到解答:
- 如何设置并使用Meld作为我的git difftool? - 如何设置并使用Meld作为我的git mergetool?
注意:不必使用同一个程序作为您的difftool和mergetool,可以为两者设置不同的程序。

1
相关帖子 - 如何在Git中通常配置差异工具 - RBT
在Windows上进行版本控制浏览相对未经测试;它可能会工作,也可能不会,这取决于您使用的源代码控制软件。 - PythoNic
9个回答

638

如何设置和使用Meld作为我的git diff工具?

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 diff 一样使用 git difftool。例如:

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

如果正确配置,Meld窗口将打开并显示差异,使用GUI界面。可以通过cmd$LOCAL$REMOTE的顺序来控制Meld GUI窗口窗格的顺序,也就是说,左窗格显示哪个文件,右窗格显示哪个文件。如果你想要它们反过来,只需像这样交换它们的位置:
    cmd = meld "$REMOTE" "$LOCAL"

最后一行的prompt = false会阻止git询问您是否要启动Meld,因为默认情况下git会发出提示。
如何设置和使用Meld作为我的git合并工具? 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 包含了部分合并的文件和冲突信息(即该文件中包含所有的 >>>>>>><<<<<<< 条目)。

现在可以使用合并工具来解决合并冲突。您可以很容易地启动它:

git mergetool

如果正确配置,则会打开一个Meld窗口,显示3个文件。每个文件都将包含在其GUI界面的单独窗格中。
在上面的示例.gitconfig条目中,建议使用2行作为[mergetool "meld"] cmd行。实际上,高级用户可以以各种方式配置cmd行,但这超出了本答案的范围。
此答案有两个备选的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,如果要使用$LOCAL$REMOTE的共享提交祖先,则使用$BASE。 [由于这两个cmd行都有用,我将它们都保留在我的.gitconfig文件中。大多数时候,我使用$MERGED行,$BASE行被注释掉,但是注释可以交换,如果我想使用$BASE线。]

关于输出文件的说明:不要担心--output "$MERGED"cmd中是否被使用,无论之前在cmd行中使用了$MERGED还是$BASE--output选项只是告诉Meld git想要保存冲突解析文件的文件名。 Meld将在该文件中保存您的冲突编辑,无论您使用$MERGED还是$BASE作为起始编辑点。

在编辑中间面板以解决合并冲突后,只需保存文件并关闭Meld窗口即可。 Git会自动更新,当前分支(例如主分支)中的文件现在将包含您在中间面板中最终得到的内容。

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窗口,直到所有文件都处理完毕。它们不会同时打开,但是当您完成编辑其中一个文件中的冲突并关闭Meld时,git将打开下一个文件,以此类推,直到解决所有合并冲突。
在使用git mergetool之前,最好创建一个虚拟项目进行测试。请确保在测试中使用包含空格的文件名,以防您的操作系统需要转义cmd行中的引号,请参见下文。
转义引号字符
某些操作系统可能需要转义cmd中的引号。较不熟练的用户应记住,配置命令行应使用包含空格的文件名进行测试,如果cmd行在包含空格的文件名中无法正常工作,则尝试转义引号。例如:
cmd = meld \"$LOCAL\" \"$REMOTE\"

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

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

Windows路径

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

忽略Meld中的尾随空格

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

在首选项的文本过滤器选项卡中,有几个有用的过滤器可以在执行差异时忽略诸如注释之类的内容。虽然有过滤器可以忽略所有空格前导空格,但没有忽略尾随空格的过滤器(这已经被建议添加到Meld邮件列表中,但在我的版本中不可用)。

忽略尾随空格通常非常有用,特别是在协作时,可以在Meld首选项的文本过滤器选项卡中轻松手动添加一个简单的正则表达式。

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

4
и°ўи°ўпјҢдҪҝз”Ё ~/.gitconfig дёӯзҡ„ [mergetool "meld"] cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED" йқһеёёж–№дҫҝпјҢеҸӘйңҖиҰҒи§ЈеҶідёӯй—ҙзӘ—еҸЈдёӯжҳҫзӨәзҡ„зәўиүІеҶІзӘҒ并дҝқеӯҳеҚіеҸҜпјҒе®ғеә”иҜҘжҳҜй»ҳи®Өи®ҫзҪ®гҖӮ - KrisWebDev
4
$LOCAL $MERGED $REMOTE 是我最常使用的设置,当只有少数冲突需要解决时,它非常出色,也是我的默认设置。 当有很多工作要做并且您确切地知道哪些代码部分来自哪个文件时, $LOCAL $BASE $REMOTE 就真正发挥了作用;共享提交祖先可以成为一个无杂乱的起点,有时冲突的突出显示实际上会妨碍你的工作,更干净的基本内容就是一种福音。 - mattst
5
注意:如果您在OSX上通过Homebrew安装了meld,输出参数将需要一个=,就像这样:cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output="$MERGED" - Alteisen
3
针对安装了 .dmg 文件但无法找到“meld”路径的 Mac 用户,请务必按照此处提供的备用指令进行操作:https://yousseb.github.io/meld/ - KC Baltz
4
比起GIT Configuration - git mergetool的解释好太多了。非常感谢你特别解释了$MERGED和$BASE之间的区别,这拯救了我不至于变得疯狂! - ChrisG
显示剩余8条评论

121
虽然其他答案是正确的,但以下是最快的方法来配置Meld作为你的可视化比对工具。只需复制/粘贴以下内容:
git config --global diff.tool meld
git config --global difftool.prompt false

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

顺便提一下:对比CSV文件时,Meld的速度惊人地慢,而我找到的任何Linux差异工具都不如这个名为Compare It!的Windows工具快(最后更新于2010年)。


17
也许你需要在那里加入一行“git config --global difftool.meld.cmd 'meld "$LOCAL" "$REMOTE"'”。这是“默认”的配置,但是一旦你配置了一个“合并工具”,如果找不到差异配置,difftool 就会开始使用合并工具配置作为默认配置。由于合并通常配置为传递三个文件进行三方合并,这意味着你的 meld 差异窗口将突然出现三个面板,这没有任何意义。 - BeeOnRope
为什么不在使用 $git config -l 命令设置后检查配置呢? - agfe2

83

适用于 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工具meld不可用于'D:\software\melddiff\Meld.exe'”。 - Allen Vork
@AllenVork:你确认Meld.exe在你指定的文件夹中吗?你能否在Git之外成功运行它?当你运行git config --global --get-regex diff*时,Git返回什么? - MarredCheese
难道不应该是:git config --global difftool.meld.path "C:\Program Files (x86)\Meld\Meld.exe"吗? - Jonathan Rosenne
1
我遇到了以下错误: $ git difftool /mingw64/libexec/git-core/git-mergetool--lib: 第124行:meld:找不到命令 fatal: external diff died, stopping at src/main/java/com/MyController.java - Andrei
1
@Andrei 我曾经遇到过同样的问题,并通过在行 cmd = meld "$LOCAL" "$REMOTE" 中添加完整路径来解决它。现在我的行是这样的 **cmd = 'C:/Program Files (x86)/Meld/Meld.exe' "$LOCAL" "$REMOTE"**。 - hfunes.com
显示剩余2条评论

43
我更喜欢将meld设置为单独的命令,如下所示:
git config --global alias.meld '!git difftool -t meld --dir-diff'

这使得它类似于此处的git-meld.pl脚本: https://github.com/wmanley/git-meld 然后,您只需运行
git meld

我刚刚在Cygwin上使用meld,现在它坏了。这个修复了它。谢谢!(虽然我因个人喜好删除了“--dir-diff”部分。) - PfunnyGuy

7

对于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中工作。


我已经使用了这个代码片段,在Windows 10和Meld 3.20.4上无缝运行。 - TomasMolina

2

我使用Meld进行简单的设置。Meld是一款免费且开源的差异工具。您将看到任何代码更改的文件和目录的漂亮并排比较。

  1. 使用yum/apt在您的Linux中安装meld。
  2. 在您的~/.gitconfig文件中添加以下行
[diff]
    tool = meld
  1. 进入您的代码仓库,输入以下命令查看最后一次提交更改和当前工作目录(未暂存的未提交更改)之间的区别

git difftool --dir-diff ./

  1. 要查看最后一次提交的代码与已缓存代码之间的差异,请使用以下命令

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


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'

然后将Meld添加为差异工具。
[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]部分下如下所示:

showchanges = difftool --dir-diff

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

以下图片展示了如何使用 --dir-diff 选项显示更改文件的列表(示例): Meld showing list of files with changes between the $LOCAL and $REMOTE 然后,可以单击每个文件,在 Meld 中显示更改。

1

在 $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中产生烦人的弹出窗口

这个是否比单个标签中的三路合并(本地/基础/远程)更好? - André Werlang
1
@AndréWerlang 在单个选项卡中进行三方合并的好处在于您只需要处理有冲突的更改(其他更改会自动合并)。但是,在三方合并难以理解更改内容并且如何以保留所有更改的方式合并的情况下,我更喜欢“我的”方法。如果某个时刻我不再感到困惑,则可以切换回三方合并。 - mnieber
正如用户mattst所指出的那样,您可以使用$BASE而不是$MERGED来开始合并操作。 - André Werlang

0

除了@mattst的出色答案之外,没有什么可以补充的。对于使用Windows Subsystem for Linux(WSL2)的人来说,您可以在Linux中开发,但使用Meld for Windows。

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

一个注意事项:我的所有代码都在Windows驱动器上,而不是WLS2虚拟驱动器上,所以可能会有所不同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接