冲突杀手meld -- git使用meld作为对比或合并工具_zhou

git 使用meld 作为 对比或合并工具


@author: 荒野无灯@80x86.io

@date: 2017-06-06


meld 下载: http://meldmerge.org/

github repo: https://github.com/GNOME/meld

gnome wiki: https://wiki.gnome.org/Apps/Meld


Meld 是GNOME 项目中的一款可视化的文件及目录对比(diff) / 合并 (merge) 工具,通过它你可以对两个或三个文件/目录进行对比,并以图形化的方式显示出它们的不同之处,

使用Python 编写,优点是跨平台(linux, windows, mac os x),简单易用, 支持和git等版本控制软件配合使用.


我的配置:


先是 配置 meld, 确保这里的配置与我们在git里的 配置 左右一一对应:

 
    
  1. [diff]
  2. tool = meld
  3. [difftool]
  4. prompt = false
  5. bc = trustExitCode
  6. [difftool "meld"]
  7. #path = /usr/bin/meld
  8. cmd = meld "$LOCAL" "$REMOTE"
  9. [difftool "bc"]
  10. path = /usr/bin/bcompare
  11. [difftool "vimdiff"]
  12. cmd = gvimdiff "$REMOTE" "$LOCAL" "$BASE"
  13. [merge]
  14. tool = meld
  15. [mergetool]
  16. prompt = false
  17. [mergetool "bc"]
  18. path = /usr/bin/bcompare
  19. bc = trustExitCode
  20. [mergetool "meld"]
  21. keepBackup = false
  22. path = /usr/bin/meld
  23. #the first is the default
  24. #cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"
  25. #cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"

-------
 
    
  1. [alias]
  2. co = checkout
  3. ci = commit
  4. st = status
  5. stn = status -uno
  6. br = branch
  7. cp = cherry-pick
  8. unstage = reset HEAD --
  9. dt = difftool
  10. dtd = difftool --dir-diff
  11. mt = mergetool

如果不写cmd, 对于merge git 默认的命令格式是:
/usr/bin/python2 /usr/bin/meld --output  "$MERGED" "$LOCAL" "$BASE" "$REMOTE"
对于 diff git 默认的命令格式是:
/usr/bin/python2 /usr/bin/meld "$LOCAL" "$REMOTE"

---------------------------------------------------
git for windows meld配置:
 
    
  1. [alias]
  2. co = checkout
  3. ci = commit
  4. st = status
  5. stn = status -uno
  6. br = branch
  7. cp = cherry-pick
  8. unstage = reset HEAD --
  9. dt = difftool
  10. dtd = difftool --dir-diff
  11. mt = mergetool
  12. [diff]
  13. tool = meld
  14. [difftool]
  15. prompt = false
  16. bc = trustExitCode
  17. [difftool "meld"]
  18. #path = /usr/bin/meld
  19. #path = C:\\Program Files (x86)\\Meld\\Meld.exe
  20. cmd = 'C:\\Program Files (x86)\\Meld\\Meld.exe' "$LOCAL" "$REMOTE"
  21. [merge]
  22. tool = meld
  23. [mergetool]
  24. prompt = false
  25. [mergetool "meld"]
  26. path = C:\\Program Files (x86)\\Meld\\Meld.exe
  27. #the first is the default
  28. #cmd = 'C:\\Program Files (x86)\\Meld\\Meld.exe' "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"
  29. #cmd = 'C:\\Program Files (x86)\\Meld\\Meld.exe' "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"
  30. keepBackup = false
  31. trustExitCode = false

windows注意:
 cmd 里的路径由于有空格,要用引号括起来,并且不能用双引号, 会有问题的.
反斜杠要转义.

windows diff 截图 :
 

如何使用meld来解决合并时的冲突:
遇到merge冲突的时候,执行 git mergetool 即可, 然后弹出的窗口中编辑中间的文件保存即可.
为方便使用,我给它设定了别名mt, 因此直接 git mt 就行了。

--------------------------------------

中间是 MERGED 的情况如下图示(请无视css代码,这不是重点,重点是diff效果):



中间是BASE的情况,如下图示:


小问题:
1. 当local 和 base 一样时,local那里没有向右的箭头来 take left.(如上图), 解决办法是直接删除base中不需要的行。
2. 当base 和 remote 不一致,且remote比base长时,右边的take right 箭头看不到.

目录对比

With git > 1.7.11, the git difftool command now supports diffing complete directories using the --dir-diff command. This can be used together with meld:
$ git difftool --tool=meld --dir-diff [commit-to-diff-against]


目录对比时:
/usr/bin/python2 /usr/bin/meld /tmp/git-difftool.Zra2Uk/left/ /tmp/git-difftool.Zra2Uk/right/

当前分支为a时:
/usr/bin/python2 /usr/bin/meld a.txt /tmp/iO1kbp_a.txt

当前分支为b时:
/usr/bin/python2 /usr/bin/meld /tmp/fZetjv_a.txt a.txt

------------------------------------------------------------------------------------------


关于LOCAL REMOTE BASE MERGED 这几个变量的解释, 参考下以下两个so的回答:


Git and DiffTool problems : What do LOCAL and REMOTE point to?

I think that means that $LOCAL is always the a/whatever in the diff output, while $REMOTE is the b/whatever. In other words, if you do:

 git difftool master experiment -- Makefile

$LOCAL will be a temporary file showing the the state of Makefile in the master branch, while $REMOTE will be a temporary file showing its state in the experiment branch.

If you just run:

git difftool

... that shows you the difference between the index and your working tree, so for each file with differences, $LOCAL will be a temporary file that's the same as the version of the file in the index, while the $REMOTE will be the version of the file in your working tree.

---------------------------------

there are 4 components to this (note that before this step, you would have already done a local-checkin.)

  • The local-checkin that your git tree has: LOCAL
  • The head of the remote repository (that is going to be merged): REMOTE
  • common ancestor to both LOCAL and REMOTE: BASE
  • The file that will be written as a result: MERGED.
https://stackoverflow.com/questions/5440610/git-and-difftool-problems-what-do-local-and-remote-point-to

diff.tool configuration variable) the configured command line will be invoked with the following variables available: $LOCAL is set to the name of the temporary file containing the contents of the diff pre-image and $REMOTE is set to the name of the temporary file containing the contents of the diff post-image. $MERGED is the name of the file which is being compared. $BASE is provided for compatibility with custom merge tool commands and has the same value as $MERGED.

https://git-scm.com/docs/git-difftool

How do I set up and use Meld as my git difftool?


  https://stackoverflow.com/a/34119867

git difftool displays the diff using a GUI diff program (i.e. Meld) instead of displaying the diff output in your terminal.

Although you can set the GUI program on the command line using -t / --tool=it makes more sense to configure it in your .gitconfig file. [Note: See the sections about escaping quotes and Windows paths at the bottom.]

# Add the following to your .gitconfig file.
[diff]
    tool = meld
[difftool]
    prompt = false
[difftool "meld"]
    cmd = meld "$LOCAL" "$REMOTE"

[Note: These settings will not alter the behaviour of git diff which will continue to function as usual.]

You use git difftool in exactly the same way as you use git diff. e.g.

git difftool  file_name
git difftool  file_name
git difftool   file_name

If properly configured a Meld window will open displaying the diff using a GUI interface.

The order of the Meld GUI window panes can be controlled by the order of $LOCAL and $REMOTE in cmd, that is to say which file is shown in the left pane and which in the right pane. If you want them the other way around simply swap them around like this:

    cmd = meld "$REMOTE" "$LOCAL"

Finally the prompt = false line simply stops git from prompting you as to whether you want to launch Meld or not, by default git will issue a prompt.


How do I set up and use Meld as my git mergetool?

git mergetool allows you to use a GUI merge program (i.e. Meld) to resolve the merge conflicts that have occurred during a merge.

Like difftool you can set the GUI program on the command line using -t / --tool= but, as before, it makes more sense to configure it in your .gitconfig file. [Note: See the sections about escaping quotes and Windows paths at the bottom.]

# 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"

You do NOT use git mergetool to perform an actual merge. Before using git mergetool you perform a merge in the usual way with git. e.g.

git checkout master
git merge branch_name

If there is a merge conflict git will display something like this:

$ 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.

At this point file_name will contain the partially merged file with the merge conflict information (that's the file with all the >>>>>>> and <<<<<<< entries in it).

Mergetool can now be used to resolve the merge conflicts. You start it very easily with:

git mergetool

If properly configured a Meld window will open displaying 3 files. Each file will be contained in a separate pane of its GUI interface.

In the example .gitconfig entry above, 2 lines are suggested as the [mergetool "meld"] cmd line. In fact there are all kinds of ways for advanced users to configure the cmd line, but that is beyond the scope of this answer.

This answer has 2 alternative cmd lines which, between them, will cater for most users, and will be a good starting point for advanced users who wish to take the tool to the next level of complexity.

Firstly here is what the parameters mean:

  • $LOCAL is the file in the current branch (e.g. master).
  • $REMOTE is the file in the branch being merged (e.g. branch_name).
  • $MERGED is the partially merged file with the merge conflict information in it.
  • $BASE is the shared commit ancestor of $LOCAL and $REMOTE, this is to say the file as it was when the branch containing $REMOTE was originally created.

I suggest you use either:

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

or:

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

The choice is whether to use $MERGED or $BASE in between $LOCAL and $REMOTE.

Either way Meld will display 3 panes with $LOCAL and $REMOTE in the left and right panes and either $MERGED or $BASE in the middle pane.

In BOTH cases the middle pane is the file that you should edit to resolve the merge conflicts. The difference is just in which starting edit position you'd prefer; $MERGED for the file which contains the partially merged file with the merge conflict information or $BASE for the shared commit ancestor of $LOCAL and $REMOTE. [Since both cmd lines can be useful I keep them both in my .gitconfig file. Most of the time I use the $MERGED line and the $BASE line is commented out, but the commenting out can be swapped over if I want to use the $BASE line instead.]

After editing the middle pane to resolve the merge conflicts, just save the file and close the Meld window. Git will do the update automatically and the file in the current branch (e.g. master) will now contain whatever you ended up with in the middle pane.

git will have made a backup of the partially merged file with the merge conflict information in it by appending .orig to the original filename. e.g. file_name.orig. After checking that you are happy with the merge and running any tests you may wish to do, the .orig file can be deleted.

At this point you can now do a commit to commit the changes.

NOTE: Do not worry that --output "$MERGED" is used in cmd regardless of whether $MERGEDor $BASE was used earlier in the cmd line. The --output option simply tells Meld what filename git wants the conflict resolution file to be saved in. Meld will make sure that your conflict edits are saved in that file regardless of whether you use $MERGED or $BASE as your starting edit point.

If, while you are editing the merge conflicts in Meld, you wish to abandon the use of Meld, then quit Meld without saving the merge resolution file in the middle pane. git will respond with the message file_name seems unchanged and then ask Was the merge successful? [y/n], if you answer n then the merge conflict resolution will be aborted and the file will remain unchanged. Note that if you have saved the file in Meld at any point then you will not receive the warning and prompt from git. [Of course you can just delete the file and replace it with the backup .orig file that git made for you.]

If you have more than 1 file with merge conflicts then git will open a new Meld window for each, one after another until they are all done. They won't all be opened at the same time, but when you finish editing the conflicts in one, and close Meld, git will then open the next one, and so on until all the merge conflicts have been resolved.

It would be sensible to create a dummy project to test the use of git mergetool before using it on a live project. Be sure to try a file with spaces in it, in case your OS requires you to escape the quotes in the cmd line, see below.


Escaping quote characters

Some operating systems may need to have the quotes in cmd escaped. Less experienced users should remember that config command lines should be tested with file names that include spaces, and if the cmd lines don't work with the file names that include spaces then try escaping the quotes. e.g.

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

In some cases more complex quote escaping may be needed. The 1st of the Windows path links below contains an example of triple-escaping each quote. It's a bore but sometimes necessary. e.g.

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

Windows paths

Windows users will probably need extra configuration added to the Meld cmd lines. They may need to use the full path to meldc, which is designed to be called on Windows from the command line, or they may need or want to use a wrapper. They should read the StackOverflow pages linked below which are about setting the correct Meld cmd line for Windows. As I am a Linux user I am unable to test the various Windows cmd lines and have no further information on the subject other than to recommend using my examples with the addition of a full path to Meld or meldc, or adding the Meld program folder to your path.

  • Git Diff and Meld on Windows
  • How to set Meld as git mergetool
  • Git mergetool with Meld on Windows

Ignoring trailing whitespace with Meld

Meld has a number of preferences that can be configured in the GUI.

In the preferences Text Filters tab there are several useful filters to ignore things like comments when performing a diff. Although there are filters to ignore All whitespace and Leading whitespace, there is no ignore Trailing whitespace filter (this has been suggested as an addition in the Meld mailing list but is not available in my version).

Ignoring trailing whitespace is often very useful, especially when collaborating, and can be manually added easily with a simple Python regular expression in the Meld preferences Text Filters tab.

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

I hope this helps everyone.

-----------------------------

其它参考:

https://gist.github.com/karenyyng/f19ff75c60f18b4b8149

你可能感兴趣的:(git)