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

fumotvh3  于 2022-12-25  发布在  Git
关注(0)|答案(9)|浏览(299)

虽然这个问题和答案中的大部分信息都可以在 StackOverflow 上找到,但它分散在很多页面上,以及其他错误或误导性的答案中。我花了一段时间才拼凑出我想知道的所有信息。
有很多不同的程序可以作为你的git difftool和mergetool使用,当然对于哪一个是最好的没有共识(观点、需求和操作系统都明显不同)。
StackOverflow 问题What's the best visual merge tool for Git?所示,Meld是一个流行的免费、开源和跨平台(UNIX/Linux、OSX、Windows)选择,其中建议使用Meld的答案获得的投票是任何其他工具的3倍多。
以下两个问题将在我的回答中得到回答:

    • 如何设置并使用Meld作为git difftool?*
    • 如何设置并使用Meld作为git合并工具?*

注意:没有必要使用同一个程序作为difftool和mergetool,可以为两者设置不同的程序。

xesrikrc

xesrikrc1#

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

git difftool使用GUI diff程序(即Meld)显示diff,而不是在终端中显示diff输出。
虽然您可以使用-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"

[Note:这些设置不会改变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

如果配置正确,将打开融合窗口,使用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

如果配置正确,将会打开一个显示3个文件的合并窗口。每个文件都包含在GUI界面的一个单独的窗格中。
在上面的.gitconfig条目示例中,建议将2行作为[mergetool "meld"]cmd行。实际上,高级用户可以通过各种方式配置cmd行,但这超出了本答案的范围。
这个答案有两个可供选择的cmd行,这两行可以满足大多数用户的需要,对于希望将该工具的复杂性提升到下一个级别的高级用户来说,这将是一个很好的起点。
首先,参数的含义如下:

  • $LOCAL是当前分支(例如主分支)中的文件。
  • $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还是$BASEcmd行前面使用过,--output选项只是告诉Meld git希望冲突解决文件保存在哪个文件名中。无论您使用$MERGED还是$BASE作为起始编辑点,Meld都会将冲突编辑保存在该文件中。
编辑中间窗格解决合并冲突后,保存文件并关闭合并窗口,Git会自动更新,当前分支(例如master)中的文件将包含你在中间窗格中得到的所有内容。
git会将部分合并文件的合并冲突信息添加到原文件名的后面,例如file_name.orig,并将其备份。在确认你对合并满意并运行了你想要的测试后,.orig文件就可以被删除了。
现在,您可以执行一次提交来提交更改。

如果您在编辑合并冲突时,不想使用合并,那么退出合并而不保存中间窗格中的合并解决方案文件。git会返回消息file_name seems unchanged,然后询问Was the merge successful? [y/n]:如果你回答n,那么合并冲突解决将被中止,文件将保持不变。请注意,如果你在任何时候将文件保存在Meld中,你都不会收到来自git的警告和提示。[当然,你也可以删除该文件,然后用git为你创建的.orig备份文件替换它。]
如果你有多个文件存在合并冲突,git会为每个文件打开一个新的合并窗口,一个接一个地打开,直到所有的合并冲突都被解决。它们不会同时打开,但是当你编辑完一个文件中的冲突并关闭Meld后,git会打开下一个文件,依此类推,直到所有的合并冲突都被解决。
live 项目上使用git mergetool之前,创建一个虚拟项目来测试它的使用是明智的。确保在测试中使用包含空格的文件名,以防操作系统要求您转义cmd行中的引号,请参见下文。

转义引号字符

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

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

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

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

Windows路径

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

忽略带有Meld的尾随空格

Meld有许多可在GUI中配置的首选项。
在preferencesText Filters选项卡中有几个有用的过滤器,可以在执行比较时忽略注解之类的东西。虽然有忽略All whitespaceLeading 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]*$
2izufjch

2izufjch2#

虽然另一个答案是正确的,但这里有一个最快的方法,你可以把Meld配置为你的可视化比较工具。

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

现在在一个目录中运行git difftool,然后为每个不同的文件启动Meld。
边注:Meld is surprisingly slow在比较CSV文件,没有Linux的diff工具,我发现比这个Windows工具称为Compare It!(最后更新在2010年)更快。

4smxwvx5

4smxwvx53#

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

nc1teljy4#

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

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

这使得它类似于下面的git-meld.pl脚本:https://github.com/wmanley/git-meld
你就可以跑了

git meld
daolsyd0

daolsyd05#

对于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版本给予了我一个错误,它应该适用于Meld 3. 20. 4,就像TomasMolina在下面的评论中提到的那样。

5q4ezhmt

5q4ezhmt6#

我用Meld做了这个简单的设置。Meld是免费的开源比较工具。你会看到很好的并排比较文件和目录的任何代码更改。
1.使用yum/apt在Linux中安装meld。
1.在~/.gitconfig文件中添加以下行

[diff]
    tool = meld

1.转到您的代码存储库并键入以下命令,以查看上次提交的更改与当前工作目录之间的差异(未暂存的未提交更改)
git差异工具--目录差异/
1.若要查看上次提交的代码和暂存代码之间的差异,请使用以下命令
git差异工具--缓存--目录差异。/

oalqel3c

oalqel3c7#

这个答案主要针对使用Windows的开发人员,因为diff工具的路径语法与其他平台不同。
我使用Kdiff 3作为git mergetool,但是为了将git difftool设置为Meld,我首先从Meldmerge.org安装了最新版本的Meld,然后使用以下命令将其添加到我的global .gitconfig:

git config --global -e

注意,如果你想用Sublime Text 3而不是默认的Vim作为核心编辑器,你可以把它添加到.gitconfig文件中:

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

然后添加inn 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

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

也可以设置一个别名来显示当前的git diff,并使用**--dir-diff选项,这样会在Meld中列出修改过的文件,这在修改多个文件时很方便(这是一个非常常见的场景)。
在.gitconfig文件中,别名如下所示,位于
[alias]**部分:

showchanges = difftool --dir-diff

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

git showchanges

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

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

wj8zmpe1

wj8zmpe18#

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

[merge]
    tool = mymeld
    conflictstyle = diff3

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

它看起来很奇怪,但提供了一个非常方便的工作流程,使用三个选项卡:
1.在选项卡1中,您可以看到(从左到右)您应该在选项卡2中进行的更改,以解决合并冲突。
1.在选项卡2的右边,你应用"你应该做的更改"并将整个文件内容复制到剪贴板(使用ctrl-a和ctrl-c)。
1.在选项卡3中,用剪贴板内容替换右侧。2如果一切正确,你现在将看到-从左到右-与选项卡1中所示相同的更改(但上下文不同)。3保存在此选项卡中所做的更改。
注:

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

4smxwvx59#

对于@mattst的精彩回答,除了这一点之外,没有什么可补充的。对于使用Windows Subsystem for Linux(WSL 2)的人来说,你可以在Linux中开发,但使用Meld for Windows。

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

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

相关问题