设置和使用 Meld 作为你的 git difftool 和 mergetool
Posted
技术标签:
【中文标题】设置和使用 Meld 作为你的 git difftool 和 mergetool【英文标题】:Setting up and using Meld as your git difftool and mergetool 【发布时间】:2016-03-11 05:55:24 【问题描述】:虽然*** 上提供了此问题和答案中的大部分信息,但它分布在许多页面上,并且在其他答案中存在错误或误导性。我花了一段时间才拼凑出我想知道的一切。
有很多不同的程序可以用作你的 git difftool 和 mergetool,对于哪个是最好的肯定没有共识(意见、要求和操作系统会明显不同)。
Meld 是一种流行的免费、开源和跨平台(UNIX/Linux、OSX、Windows)选择,如 *** 问题 What's the best visual merge tool for Git? 所示,其中提出的答案Meld 的投票数是其他任何工具的 3 倍以上。
以下2个问题将在我的回答中得到解答:
如何设置和使用 Meld 作为我的 git difftool? 如何设置和使用 Meld 作为我的 git 合并工具?注意:difftool 和 mergetool 不需要使用相同的程序,可以为两者设置不同的程序。
【问题讨论】:
相关帖子 - 如何configure a diff tool in Git in general. 【参考方案1】:从 $MERGED 中的不同部分计算你的头脑中的差异并应用它可能很复杂。在我的设置中,meld 可以帮助您直观地显示这些差异,使用:
[merge]
tool = mymeld
conflictstyle = diff3
[mergetool "mymeld"]
cmd = meld --diff $BASE $REMOTE --diff $REMOTE $LOCAL --diff $LOCAL --output $MERGED
它看起来很奇怪,但提供了一个非常方便的工作流程,使用三个选项卡:
在选项卡 1 中,您会看到(从左到右)您应该在选项卡 2 中进行的更改以解决合并冲突。
在选项卡 2 的右侧,您应用“您应该进行的更改”并将整个文件内容复制到剪贴板(使用 ctrl-a 和 ctrl-c)。
在选项卡 3 中,将右侧替换为剪贴板内容。如果一切正确,您现在将看到 - 从左到右 - 与选项卡 1 中所示相同的更改(但具有不同的上下文)。保存在此选项卡中所做的更改。
注意事项:
不要在标签 1 中编辑任何内容 不要在选项卡 2 中保存任何内容,因为这会在选项卡 3 中产生烦人的弹出窗口【讨论】:
这是否比单个选项卡中的 3 路合并(本地/基本/远程)更好? @AndréWerlang 在单个选项卡中进行 3 路合并的优点是您只需要处理冲突的更改(其他更改会自动合并)。但我更喜欢“我的”方法,因为在 3-way 合并中很难理解发生了什么变化,以及如何以保留所有变化的方式进行合并。如果在某个时候 3 路合并不再让我感到困惑,那么我可能会切换回它。 正如用户 mattst 指出的那样,您可以使用$BASE
而不是 $MERGED
开始合并操作【参考方案2】:
除此之外,@mattst 的出色答案没什么可补充的。对于使用 Windows Subsystem for Linux (WSL2) 的人,您可以在 Linux 中进行开发,但使用 Meld for Windows。
cmd = "/mnt/c/Program Files (x86)/Meld/Meld.exe" "$LOCAL" "$REMOTE"
一个警告:我的所有代码都在 Windows 驱动器上,而不是 WLS2 虚拟驱动器上,所以是 YMMV。
【讨论】:
【参考方案3】:我使用 meld 遵循这个简单的设置。 Meld 是免费的开源差异工具。对于任何代码更改,您都会看到文件和目录的并排比较。
-
使用 yum/apt 在您的 Linux 中安装 meld。
在 ~/.gitconfig 文件中添加以下行
[diff] tool = meld
-
转到您的代码仓库并键入以下命令以查看上次提交的更改与当前工作目录之间的差异(未暂存的未提交更改)
git difftool --dir-diff ./
-
要查看最后提交的代码和暂存代码之间的区别,请使用以下命令
git difftool --cached --dir-diff ./
【讨论】:
【参考方案4】:虽然其他答案是正确的,但这是继续将 Meld 配置为视觉差异工具的最快方法。只需复制/粘贴:
git config --global diff.tool meld
git config --global difftool.prompt false
现在在目录中运行git difftool
,Meld 将为每个不同的文件启动。
旁注:Meld is surprisingly slow 在比较 CSV 文件时,我发现没有任何 Linux diff 工具比这个名为 Compare It! 的 Windows 工具更快(最后更新于 2010 年)。
【讨论】:
你可能也想要一个git config --global difftool.meld.cmd 'meld "$LOCAL" "$REMOTE"'
行。这是“默认”,但是一旦您配置了mergetool
,如果未找到差异配置,difftool
将开始使用 mergetool 配置作为默认配置。由于合并通常配置为通过三个文件进行 3 路合并,这意味着您的 meld
diff 窗口将突然有三个没有任何意义的窗格。
为什么不检查配置,用 $git config -l 设置后【参考方案5】:
对于 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 超级 answer 中。
PS:由于某种原因,这只适用于 Meld 3.18.x,Meld 3.20.x 给我一个错误。
【讨论】:
【参考方案6】:如何设置和使用 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 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 窗口,使用 GUI 界面显示差异。
Meld GUI 窗口窗格的顺序可以通过cmd
中$LOCAL
和$REMOTE
的顺序来控制,即哪个文件显示在左窗格中,哪个文件显示在右窗格中。如果你想要它们相反,只需像这样交换它们:
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
将包含带有合并冲突信息的部分合并文件(即包含所有>>>>>>>
和<<<<<<<
条目的文件)。
Mergetool 现在可用于解决合并冲突。你可以很容易地开始它:
git mergetool
如果配置正确,将打开一个 Meld 窗口,显示 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
行,注释掉可以交换。]
关于输出文件的注意事项:不要担心--output "$MERGED"
会在cmd
中使用,无论$MERGED
还是$BASE
之前在cmd
行中使用过。 --output
选项只是告诉 Meld git 希望将冲突解决文件保存在哪个文件名中。无论您使用 $MERGED
还是 $BASE
作为起始编辑点,Meld 都会将您的冲突编辑保存在该文件中。
编辑中间窗格以解决合并冲突后,只需保存文件并关闭 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
文件替换。]
如果您有超过 1 个文件存在合并冲突,那么 git 将为每个文件打开一个新的 Meld 窗口,一个接一个,直到它们全部完成。它们不会同时打开,但是当您完成对一个冲突的编辑并关闭 Meld 时,git 会打开下一个,依此类推,直到所有合并冲突都已解决。
在live 项目中使用git mergetool
之前,创建一个虚拟项目来测试它的使用是明智的。请务必在测试中使用包含空格的文件名,以防操作系统要求您转义 cmd
行中的引号,请参见下文。
转义引号字符
某些操作系统可能需要对cmd
中的引号进行转义。经验不足的用户应该记住,配置命令行应该使用包含空格的文件名进行测试,如果 cmd
行不适用于包含空格的文件名,请尝试转义引号。例如
cmd = meld \"$LOCAL\" \"$REMOTE\"
在某些情况下,可能需要更复杂的引号转义。下面的第一个 Windows 路径链接包含对每个引号进行三次转义的示例。这很无聊,但有时是必要的。例如
cmd = meld \\\"$LOCAL\\\" \\\"$REMOTE\\\"
Windows 路径
Windows 用户可能需要在 Meld cmd
行中添加额外的配置。他们可能需要使用 meldc
的完整路径,该路径旨在从命令行在 Windows 上调用,或者他们可能需要或想要使用包装器。他们应该阅读下面链接的 *** 页面,这些页面是关于为 Windows 设置正确的 Meld cmd
行。由于我是 Linux 用户,因此我无法测试各种 Windows cmd
行,并且除了建议使用我的示例并添加 Meld 或 meldc
的完整路径或添加将程序文件夹合并到您的path
。
使用 Meld 忽略尾随空格
Meld 有许多可以在 GUI 中配置的首选项。
在首选项Text Filters
选项卡中,有几个有用的过滤器可以在执行差异时忽略诸如 cmets 之类的内容。虽然有过滤器可以忽略 All whitespace
和 Leading whitespace
,但没有忽略 Trailing whitespace
过滤器(这已被建议作为 Meld 邮件列表中的附加项,但在我的版本中不可用)。
忽略尾随空格通常非常有用,尤其是在协作时,并且可以使用 Meld 首选项Text Filters
选项卡中的简单正则表达式轻松手动添加。
# Use either of these regexes depending on how comprehensive you want it to be.
[ \t]*$
[ \t\r\f\v]*$
希望对大家有所帮助。
【讨论】:
谢谢,在~/.gitconfig
中使用[mergetool "meld"]
cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"
要容易得多,然后只需解决中间盘中以红色突出显示的冲突并保存!它应该是默认设置。
$LOCAL $MERGED $REMOTE
是我大部分时间使用的设置,当只有一些冲突可以解决时,它非常好,也是我的默认设置。 $LOCAL $BASE $REMOTE
当有很多事情要做并且您确切地知道哪些代码段来自哪个文件时,它会真正发挥作用;共享的提交祖先可以是一个很好的无杂乱的起点,有时冲突突出显示实际上会阻碍并且更清洁的基础是一种祝福。
注意: 如果您在 OSX 上并通过自制软件安装了 meld,则输出参数将需要 =
,如下所示:cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output="$MERGED"
对于安装了 .dmg 并发现“meld”不在他们的路径中的 Mac 用户,请务必按照此处的备用说明进行操作:yousseb.github.io/meld
这比Git Configuration - git mergetool 的解释好多了。非常感谢您解释 $MERGED 和 $BASE 之间的区别。让我免于发疯!【参考方案7】:
这是一个主要针对使用 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 内部的更改。
【讨论】:
【参考方案8】:适用于 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
【讨论】:
我在运行 git difftool "The diff tool meld is not available as 'D:\software\melddiff\Meld.exe'"时出错 @AllenVork:您确认 Meld.exe 在您指定的文件夹中吗?你能在 Git 之外成功运行它吗?当你运行git config --global --get-regex diff*
时,Git 会返回什么?
我解决了。我将其更改为“D:/software/melddiff/Meld.exe”,它可以工作。.gitconfig 的格式是 ubuntu 而不是 windows。
不应该是:git config --global difftool.meld.path "C:\Program Files (x86)\Meld\Meld.exe"
?
@AllenVork,你在用 git for cygwin 吗?【参考方案9】:
我更喜欢将 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
部分。)以上是关于设置和使用 Meld 作为你的 git difftool 和 mergetool的主要内容,如果未能解决你的问题,请参考以下文章
使用 git 和 meld 进行交互式变基的 3 路合并中的三个文件是啥?