tool推荐 - 使用ediff作为git mergetool




merge tool推荐 (8)

我希望能够使用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

我究竟做错了什么?


Viper3369代码中的elisp代码( 使用ediff作为git mergetool )使用了一个不存在的函数“display-usable-bounds”。 由于钩子比完全必要的更多,所以简单地删除对“display-useful-bounds”的所有引用就足以使它对我有用。 干得好! ;)

(编辑:我想我应该发布修改后的emacs-lisp代码:

;;
;; 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)


(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)

对于使用Subversion的交互式合并工具而不是git,请参阅this帖子以获取设置此内容的一些说明。


我用了一个更复杂的命令。 据我记得,我从这个帖子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立即返回的事实。

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


有一种方法可以将ediff-merge-files-with-ancestor函数与emacsclient一起使用。

最简单的一个(对于GNU / Linux用户)是在emacsclient调用之后从管道执行shell读取。 附加到ediff-quit-hook的钩子(它必须在ediff-cleanup-mess之后运行,否则ediff会话没有正确终止)将通过shell命令在管道中射出一个字符。

更精致的将使用信号量。

这里到了Unix高级用户。

然后到达Emacs Guru(Stefan Monnier)并告诉你可以打电话

emacsclient --eval'(progn(ediff-merge-files-wit .......)(递归编辑))'

添加后

(抛出'出口)

在ediff-quit-hook结束的某个地方。 没有命名管道,没有信号量,只有Emacs LISP。 简单,优雅,不需要奇怪的测试,以避免在不使用时使用管道或信号量。

谢谢Stefan!


谢谢,它也适用于xemacs,但是pmr 的回复中的引用似乎不起作用,而我认为所有其他回复中的引用都很好:

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

我把上面的代码放在~/.gitconfig


这对我来说是一个有价值的发现。 我有一个小的补充,因为我使用emacs桌面保存模式:

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

并添加了“(当”下面的条款,因为我更喜欢多帧ediff:

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

(when (or (not desktop-save-mode) (member "--no-desktop" command-line-args))
      (defvar ediff-after-quit-hooks nil
       ... (rest of TauPan's code here) ...
)


这是我的设置,它运行得相当好,至少使用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)




merge