2012-03-11 50 views
31

(问题改编自How do I combine the two variants of a conflict in emacs' emerge?冲突解决使用Emacs Ediff:我如何可以采取两个版本的变化

我有合并冲突标记的文件。它看起来类似于这样:

<<<<<<< HEAD 
      522ADC9C14B2FD9D00F56BAD /* close_test_button.png in Resources */, 
      522ADC9D14B2FD9D00F56BAD /* [email protected] in Resources */, 
      522ADCA014B2FDB100F56BAD /* test_failed.png in Resources */, 
      522ADCA114B2FDB100F56BAD /* [email protected] in Resources */, 
======= 
      EC1633C014B2F3E3004B52E7 /* arrow.png in Resources */, 
      EC1633C114B2F3E3004B52E7 /* [email protected] in Resources */, 
      EC1633C214B2F3E3004B52E7 /* groups.png in Resources */, 
      EC1633C314B2F3E3004B52E7 /* [email protected] in Resources */, 
>>>>>>> beta_2.8 

我用M-X VC-解决,冲突开始Ediff。我可以打我的键盘上一个b选择变种一个,但我怎么结合这两个变种,一个接一个?

+3

我很想这么长时间,谢谢你的推动。 – 2012-03-23 21:38:04

回答

8

您可以切换到缓冲区“C”并编辑它。新闻+如果您已经选择A或B来恢复差异。

如果你想要按下某个键自动删除差异标记,我只能说这看起来像一个可怕的想法。

手动合并应留给用户。去除每个diff区域来自哪里的线索对我来说并不合适。

您可以自定义标记是空白行与此:

M-:

(setq ediff-combination-pattern '("" A "" B "" Ancestor)) 
+9

重点不在于删除差异标记,而是要求两个差异都包含在最终结果中 - 并强制人们手动执行此操作是PITA。差异通常只是显示两个人将事物添加到列表中的位置。很明显,用户可以选择它并打破他们的代码,但是他们也可以通过按A或B来做到这一点...... – 2012-03-23 22:04:12

+0

也可以像“meld”一样“复制”或“复制”。 。 – mgalgs 2014-10-01 18:20:15

+0

同意Trey。由于用户想要执行某项操作,因此推送了一个短键。根据你的理由,他们应该删除xa和xb的快捷键......大多数其他体面的工具都具有这种能力,即先拿A然后B或B然后A ......它是我离开edfiff的唯一原因.. it由于这个短暂的到来似乎吸引了合并。 – UpAndAdam 2016-03-04 02:20:57

3

VC-解决,冲突 doc字符串说,这是一个别名smerge-ediff

如果按照我的预期工作,那么你的缓冲区应该处于smerge minor模式,并且应该有一个smerge菜单。该菜单包含您需要的一切。

+4

具体有'C-c^a' \t smerge-keep-all;请参阅_smerge-mode_help ... – 2014-02-21 13:13:06

+0

实际上与'ediff'功能(它不使用'smerge-mode' - 或者至少现在没有,如果它曾经这样做过)没有任何关系,但肯定是一个有用的答案if你*使用'smerge-mode'。 – phils 2016-12-14 22:20:03

4

是的,我完全想要这样做!使用以下代码块,您可以通过键入d - 这将从合并缓冲区中的缓冲区A和缓冲区B(按此顺序)获取代码。

这段代码唯一真正的困难是ediff在一个地方使用宏,并且编译后的函数版本需要用新宏重新评估。无论如何,请尝试编码。使用Emacs 23.2进行测试。

(require 'ediff-init)   ;ensure the macro is defined, so we can override it 

(defmacro ediff-char-to-buftype (arg) 
    `(cond ((memq ,arg '(?a ?A)) 'A) 
    ((memq ,arg '(?b ?B)) 'B) 
    ((memq ,arg '(?c ?C)) 'C) 
    ((memq ,arg '(?d ?D)) 'D) 
    )) 

(require 'ediff) 

;; Literally copied from ediff-util 
;; need to re-evaluate because it uses the macro defined above 
;; and the compiled version needs to be re-compiled with the new definition 
;; why a macro???? 
(defun ediff-diff-to-diff (arg &optional keys) 
    "Copy buffer-X'th difference region to buffer Y \(X,Y are A, B, or C\). 
If numerical prefix argument, copy the difference specified in the arg. 
Otherwise, copy the difference given by `ediff-current-difference'. 
This command assumes it is bound to a 2-character key sequence, `ab', `ba', 
`ac', etc., which is used to determine the types of buffers to be used for 
copying difference regions. The first character in the sequence specifies 
the source buffer and the second specifies the target. 

If the second optional argument, a 2-character string, is given, use it to 
determine the source and the target buffers instead of the command keys." 
    (interactive "P") 
    (ediff-barf-if-not-control-buffer) 
    (or keys (setq keys (this-command-keys))) 
    (if (eq arg '-) (setq arg -1)) ; translate neg arg to -1 
    (if (numberp arg) (ediff-jump-to-difference arg)) 

    (let* ((key1 (aref keys 0)) 
    (key2 (aref keys 1)) 
    (char1 (ediff-event-key key1)) 
    (char2 (ediff-event-key key2)) 
    ediff-verbose-p) 
(ediff-copy-diff ediff-current-difference 
     (ediff-char-to-buftype char1) 
     (ediff-char-to-buftype char2)) 
;; recenter with rehighlighting, but no messages 
(ediff-recenter))) 

(defun ediff-copy-D-to-C (arg) 
    "Copy ARGth difference region from both buffers A and B to C. 
ARG is a prefix argument. If nil, copy the current difference region." 
    (interactive "P") 
    (ediff-diff-to-diff arg "dc")) 

(defun ediff-copy-diff (n from-buf-type to-buf-type 
       &optional batch-invocation reg-to-copy) 
    (let* ((to-buf (ediff-get-buffer to-buf-type)) 
    ;;(from-buf (if (not reg-to-copy) (ediff-get-buffer from-buf-type))) 
    (ctrl-buf ediff-control-buffer) 
    (saved-p t) 
    (three-way ediff-3way-job) 
    messg 
    ediff-verbose-p 
    reg-to-delete reg-to-delete-beg reg-to-delete-end) 

(setq reg-to-delete-beg 
     (ediff-get-diff-posn to-buf-type 'beg n ctrl-buf)) 
(setq reg-to-delete-end 
     (ediff-get-diff-posn to-buf-type 'end n ctrl-buf)) 

(if (eq from-buf-type 'D) 
    ;; want to copy *both* A and B 
    (if reg-to-copy 
    (setq from-buf-type nil) 
     (setq reg-to-copy (concat (ediff-get-region-contents n 'A ctrl-buf) 
       (ediff-get-region-contents n 'B ctrl-buf)))) 
    ;; regular code 
    (if reg-to-copy 
     (setq from-buf-type nil) 
    (setq reg-to-copy (ediff-get-region-contents n from-buf-type ctrl-buf)))) 

(setq reg-to-delete (ediff-get-region-contents 
      n to-buf-type ctrl-buf 
      reg-to-delete-beg reg-to-delete-end)) 

(if (string= reg-to-delete reg-to-copy) 
    (setq saved-p nil) ; don't copy identical buffers 
    ;; seems ok to copy 
    (if (or batch-invocation (ediff-test-save-region n to-buf-type)) 
     (condition-case conds 
     (progn 
     (ediff-with-current-buffer to-buf 
      ;; to prevent flags from interfering if buffer is writable 
      (let ((inhibit-read-only (null buffer-read-only))) 

     (goto-char reg-to-delete-end) 
     (insert reg-to-copy) 

     (if (> reg-to-delete-end reg-to-delete-beg) 
      (kill-region reg-to-delete-beg reg-to-delete-end)) 
     )) 
     (or batch-invocation 
     (setq 
     messg 
     (ediff-save-diff-region n to-buf-type reg-to-delete)))) 
    (error (message "ediff-copy-diff: %s %s" 
      (car conds) 
      (mapconcat 'prin1-to-string (cdr conds) " ")) 
      (beep 1) 
      (sit-for 2) ; let the user see the error msg 
      (setq saved-p nil) 
      ))) 
) 

;; adjust state of difference in case 3-way and diff was copied ok 
(if (and saved-p three-way) 
    (ediff-set-state-of-diff-in-all-buffers n ctrl-buf)) 

(if batch-invocation 
    (ediff-clear-fine-differences n) 
    ;; If diff3 job, we should recompute fine diffs so we clear them 
    ;; before reinserting flags (and thus before ediff-recenter). 
    (if (and saved-p three-way) 
     (ediff-clear-fine-differences n)) 

    (ediff-refresh-mode-lines) 

    ;; For diff2 jobs, don't recompute fine diffs, since we know there 
    ;; aren't any. So we clear diffs after ediff-recenter. 
    (if (and saved-p (not three-way)) 
     (ediff-clear-fine-differences n)) 
    ;; Make sure that the message about saving and how to restore is seen 
    ;; by the user 
    (message "%s" messg)) 
)) 

;; add keybinding in a hook b/c the keymap isn't defined until the hook is run 
(add-hook 'ediff-keymap-setup-hook 'add-d-to-ediff-mode-map) 

(defun add-d-to-ediff-mode-map() 
    (define-key ediff-mode-map "d" 'ediff-copy-D-to-C)) 
+0

看到我的答案 - 以更简单的方式实现Trey的想法。 – killdash9 2015-05-01 03:45:00

22

这和Trey Jackson的有用答案是一样的,它更简单。按d将复制A和B到缓冲区C.

(defun ediff-copy-both-to-C() 
    (interactive) 
    (ediff-copy-diff ediff-current-difference nil 'C nil 
        (concat 
        (ediff-get-region-contents ediff-current-difference 'A ediff-control-buffer) 
        (ediff-get-region-contents ediff-current-difference 'B ediff-control-buffer)))) 
(defun add-d-to-ediff-mode-map() (define-key ediff-mode-map "d" 'ediff-copy-both-to-C)) 
(add-hook 'ediff-keymap-setup-hook 'add-d-to-ediff-mode-map) 
+1

这太好了。为了完整性,还可以在快速帮助菜单中添加一行关于它的内容? – chengiz 2015-09-30 14:25:56

+4

这太棒了。结合'〜'交换缓冲区的顺序,你可以得到A然后B *或* B然后A,这有时也派上用场。 – 2016-08-19 07:51:07

+1

键绑定'd'与跳转到diff有冲突。我将它绑定到'B'(大写)。 – Joe 2016-10-07 18:07:35