当前位置:  开发笔记 > 编程语言 > 正文

使用ediff作为git mergetool

如何解决《使用ediff作为gitmergetool》经验,为你挑选了4个好方法。

我希望能够使用ediff与"git mergetool".

我找到了一些改变源代码的补丁,我不想这样做.相反,我想在我的.gitconfig中添加ediff支持.

我知道git已经内置了对emerge的支持,但我更喜欢ediff.

我试图将这些行添加到我的.gitconfig:

[mergetool "ediff"]
    cmd = emacs --eval "(ediff-merge-files-with-ancestor \"$LOCAL\" \"$REMOTE\" \"$BASE\" nil \"$MERGED\")"

但是当我尝试使用"git mergetool --tool = ediff"运行时,我得到了这个:

eval: 1: Syntax error: "(" unexpected

我究竟做错了什么?



1> tarsius..:

我用了一个更复杂的命令.据我记得,我从这个帖子http://kerneltrap.org/mailarchive/git/2007/6/28/250230得到它(可能和你指的一样).

[mergetool.ediff]
    cmd = emacs --eval \"\
(progn\
  (defun ediff-write-merge-buffer ()\
    (let ((file ediff-merge-store-file))\
      (set-buffer ediff-buffer-C)\
      (write-region (point-min) (point-max) file)\
      (message \\\"Merge buffer saved in: %s\\\" file)\
      (set-buffer-modified-p nil)\
      (sit-for 1)))\
  (setq ediff-quit-hook 'kill-emacs\
        ediff-quit-merge-hook 'ediff-write-merge-buffer)\
  (ediff-merge-files-with-ancestor \\\"$LOCAL\\\" \\\"$REMOTE\\\"\
                                   \\\"$BASE\\\" nil \\\"$MERGED\\\"))\"

请注意,我已将其拆分为多行,以提高可读性并转义新行,\因此git config将其视为单行.

我通常使用emacsclient来编辑例如提交消息.遗憾的是,上面的mergetool配置不使用emacsclient,当我试图让它与emacsclient一起工作时,我遇到了各种问题,包括emacsclient立即返回的事实.

但是你刚才提醒我这个问题,所以我可能会尽快解决这个问题.但是,如果其他人已经找到了一个当然很棒的解决方案;-)


如果你想知道如何使用emacsclient,我很想知道.
好吧,我现在维持*Magit :-)但我恐怕不得不说它的Ediff支持并不是那么好.我将在下一次发布后继续研究.

2> u-punkt..:

我使用以下脚本作为mergetool工作得很好.

#!/bin/bash

# test args
if [ ! ${#} -ge 3 ]; then
    echo 1>&2 "Usage: ${0} LOCAL REMOTE MERGED BASE"
    echo 1>&2 "       (LOCAL, REMOTE, MERGED, BASE can be provided by \`git mergetool'.)"
    exit 1
fi

# tools
_EMACSCLIENT=/usr/local/bin/emacsclient
_BASENAME=/bin/basename
_CP=/bin/cp
_EGREP=/bin/egrep
_MKTEMP=/bin/mktemp

# args
_LOCAL=${1}
_REMOTE=${2}
_MERGED=${3}
if [ -r ${4} ] ; then
    _BASE=${4}
    _EDIFF=ediff-merge-files-with-ancestor
    _EVAL="${_EDIFF} \"${_LOCAL}\" \"${_REMOTE}\" \"${_BASE}\" nil \"${_MERGED}\""
else
    _EDIFF=ediff-merge-files
    _EVAL="${_EDIFF} \"${_LOCAL}\" \"${_REMOTE}\" nil \"${_MERGED}\""
fi

# console vs. X
if [ "${TERM}" = "linux" ]; then
    unset DISPLAY
    _EMACSCLIENTOPTS="-t"
else
    _EMACSCLIENTOPTS="-c"
fi

# run emacsclient
${_EMACSCLIENT} ${_EMACSCLIENTOPTS} -a "" -e "(${_EVAL})" 2>&1

# check modified file
if [ ! $(egrep -c '^(<<<<<<<|=======|>>>>>>>|####### Ancestor)' ${_MERGED}) = 0 ]; then
    _MERGEDSAVE=$(${_MKTEMP} --tmpdir `${_BASENAME} ${_MERGED}`.XXXXXXXXXX)
    ${_CP} ${_MERGED} ${_MERGEDSAVE}
    echo 1>&2 "Oops! Conflict markers detected in $_MERGED."
    echo 1>&2 "Saved your changes to ${_MERGEDSAVE}"
    echo 1>&2 "Exiting with code 1."
    exit 1
fi

exit 0

要将它与`git mergetool'一起使用,请在git config中添加以下内容:

[merge]
        tool = ediff

[mergetool "ediff"]
        cmd = /path/to/ediff-merge-script $LOCAL $REMOTE $MERGED $BASE
        trustExitCode = true

此外,您应该检查(在脚本中)使用的工具的路径以及穷人的控制台检测是否适合您.

脚本本身启动一个emacs客户端(或emacs后面跟一个emacs客户端-a ""),并且ediff-merge-files-with-ancestor或者ediff-merge-files如果没有基本版本(例如合并两个独立创建相同路径/文件的分支时).

emacs客户端完成后,检查合并文件是否有冲突标记.如果找到这些文件,您的工作将被保存到临时文件中,脚本将以代码1退出,git将恢复合并文件的预合并工具内容.

当没有冲突标记存在时,脚本以代码0退出,git将合并视为成功.

重要提示:设置合并工具选项trustExitCodetrue以及为冲突标记编辑后检查,如果你开始将无法正常工作emacsclient--no-wait选项.



3> 小智..:

这是我的设置,它运行得相当好,至少使用Emacs 23.3.我使用的技巧是在钩子中使用(递归编辑),这样emacsclient就不会退出,直到建议的ediff-quit钩子调用(exit-recursive-edit).

我使用了一个建议的ediff-quit来确保退出 - 递归 - 编辑是最后完成的事情.

还有钩子来保存当前帧和窗口状态并在之后恢复它,钩子使当前帧填满屏幕.您可能希望修改它,但我发现合并全屏是最好的方法.

我没有解决中止ediff并使emacsclient返回非零退出的问题.

放入你的gitconfig:

[mergetool "ediff"]
       cmd = emacsclient --eval \"(git-mergetool-emacsclient-ediff \\\"$LOCAL\\\" \\\"$REMOTE\\\" \\\"$BASE\\\" \\\"$MERGED\\\")\"
       trustExitCode = true
[mergetool]
    prompt = false
[merge]
    tool = ediff

放入你的.emacs或同等的:

;;
;; Setup for ediff.
;;
(require 'ediff)

(defvar ediff-after-quit-hooks nil
  "* Hooks to run after ediff or emerge is quit.")

(defadvice ediff-quit (after edit-after-quit-hooks activate)
  (run-hooks 'ediff-after-quit-hooks))

(setq git-mergetool-emacsclient-ediff-active nil)

(defun local-ediff-frame-maximize ()
  (let* ((bounds (display-usable-bounds))
     (x (nth 0 bounds))
     (y (nth 1 bounds))
     (width (/ (nth 2 bounds) (frame-char-width)))
     (height (/ (nth 3 bounds) (frame-char-height))))
    (set-frame-width (selected-frame) width)
    (set-frame-height (selected-frame) height)
    (set-frame-position (selected-frame) x y)))

(setq ediff-window-setup-function 'ediff-setup-windows-plain)
(setq ediff-split-window-function 'split-window-horizontally)

(defun local-ediff-before-setup-hook ()
  (setq local-ediff-saved-frame-configuration (current-frame-configuration))
  (setq local-ediff-saved-window-configuration (current-window-configuration))
  (local-ediff-frame-maximize)
  (if git-mergetool-emacsclient-ediff-active
      (raise-frame)))

(defun local-ediff-quit-hook ()
  (set-frame-configuration local-ediff-saved-frame-configuration)
  (set-window-configuration local-ediff-saved-window-configuration))

(defun local-ediff-suspend-hook ()
  (set-frame-configuration local-ediff-saved-frame-configuration)
  (set-window-configuration local-ediff-saved-window-configuration))

(add-hook 'ediff-before-setup-hook 'local-ediff-before-setup-hook)
(add-hook 'ediff-quit-hook 'local-ediff-quit-hook 'append)
(add-hook 'ediff-suspend-hook 'local-ediff-suspend-hook 'append)

;; Useful for ediff merge from emacsclient.
(defun git-mergetool-emacsclient-ediff (local remote base merged)
  (setq git-mergetool-emacsclient-ediff-active t)
  (if (file-readable-p base)
      (ediff-merge-files-with-ancestor local remote base nil merged)
    (ediff-merge-files local remote nil merged))
  (recursive-edit))

(defun git-mergetool-emacsclient-ediff-after-quit-hook ()
  (exit-recursive-edit))

(add-hook 'ediff-after-quit-hooks 'git-mergetool-emacsclient-ediff-after-quit-hook 'append)



4> pajato0..:

除了我在上面的评论中发现的git vs bzr问题之外,我能够确认你需要逃避这些问题.

 cmd = emacs --eval "\\(ediff-merge-files-with-ancestor \"$LOCAL\" \"$REMOTE\" \"$BASE\" nil \"$MERGED\"\\)"

请注意双反斜杠字符.我有点明白,他们需要(而不是单一的)来完成sh/bash引用和emacs启动引用机制.我会留给那些更好地掌握Emacs和shell引用来解释血腥细节的人.

-pmr

推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有