Use ediff interactive merge to help conflict resolution.

Idea from smerge code, adapted to git, new key binding on "e"
This commit is contained in:
Rémi Vanicat 2009-02-25 14:55:52 +01:00
parent 5cd62fa9ac
commit 1eac6b70c6
2 changed files with 73 additions and 17 deletions

View file

@ -1104,6 +1104,7 @@ Many Magit faces inherit from this one by default."
(define-key map (kbd "B") 'magit-create-branch) (define-key map (kbd "B") 'magit-create-branch)
(define-key map (kbd "m") 'magit-manual-merge) (define-key map (kbd "m") 'magit-manual-merge)
(define-key map (kbd "M") 'magit-automatic-merge) (define-key map (kbd "M") 'magit-automatic-merge)
(define-key map (kbd "e") 'magit-interactive-resolve-item)
(define-key map (kbd "N r") 'magit-svn-rebase) (define-key map (kbd "N r") 'magit-svn-rebase)
(define-key map (kbd "N c") 'magit-svn-dcommit) (define-key map (kbd "N c") 'magit-svn-dcommit)
(define-key map (kbd "R") 'magit-rebase-step) (define-key map (kbd "R") 'magit-rebase-step)
@ -1167,6 +1168,7 @@ Many Magit faces inherit from this one by default."
["Create branch" magit-create-branch t] ["Create branch" magit-create-branch t]
["Merge" magit-automatic-merge t] ["Merge" magit-automatic-merge t]
["Merge (no commit)" magit-manual-merge t] ["Merge (no commit)" magit-manual-merge t]
["Interactive resolve" magit-interactive-resolve-item t]
["Rebase" magit-rebase-step t] ["Rebase" magit-rebase-step t]
("Git SVN" ("Git SVN"
["Rebase" magit-svn-rebase (magit-svn-enabled)] ["Rebase" magit-svn-rebase (magit-svn-enabled)]
@ -2865,4 +2867,58 @@ Prefix arg means justify as well."
(erase-buffer) (erase-buffer)
(shell-command (concat magit-git-executable " branch -va") t t))) (shell-command (concat magit-git-executable " branch -va") t t)))
(defvar magit-ediff-file)
(defvar magit-ediff-windows)
(defun magit-interactive-resolve (file)
(let ((merge-status (magit-git-string "ls-files -u -- %s" file))
(base-buffer (generate-new-buffer (concat file ".base")))
(our-buffer (generate-new-buffer (concat file ".ours")))
(their-buffer (generate-new-buffer (concat file ".theirs")))
(windows (current-window-configuration)))
(if (null merge-status)
(error "Cannot resolge %s" file))
(with-current-buffer base-buffer
(if (string-match "^[0-9]+ [0-9a-f]+ 1" merge-status)
(insert (magit-git-string "cat-file blob :1:%s" file))))
(with-current-buffer our-buffer
(if (string-match "^[0-9]+ [0-9a-f]+ 2" merge-status)
(insert (magit-git-string "cat-file blob :2:%s" file))))
(with-current-buffer their-buffer
(if (string-match "^[0-9]+ [0-9a-f]+ 3" merge-status)
(insert (magit-git-string "cat-file blob :3:%s" file))))
;; We have now created the 3 buffer with ours, theirs and the ancestor files
(with-current-buffer (ediff-merge-buffers-with-ancestor our-buffer their-buffer base-buffer)
(make-local-variable 'magit-ediff-file)
(setq magit-ediff-file file)
(make-local-variable 'magit-ediff-windows)
(setq magit-ediff-windows windows)
(make-local-variable 'ediff-quit-hook)
(add-hook 'ediff-quit-hook
(lambda ()
(let ((buffer-A ediff-buffer-A)
(buffer-B ediff-buffer-B)
(buffer-C ediff-buffer-C)
(buffer-Ancestor ediff-ancestor-buffer)
(file magit-ediff-file)
(windows magit-ediff-windows))
(ediff-cleanup-mess)
(find-file file)
(erase-buffer)
(insert-buffer-substring buffer-C)
(kill-buffer buffer-A)
(kill-buffer buffer-B)
(kill-buffer buffer-C)
(when (bufferp buffer-Ancestor) (kill-buffer buffer-Ancestor))
(set-window-configuration windows)
(message "Conflict resolution finished; you may save the buffer")))))))
(defun magit-interactive-resolve-item ()
(interactive)
(magit-section-action (item info "resolv")
((diff)
(magit-interactive-resolve (cadr info)))))
(provide 'magit) (provide 'magit)

View file

@ -452,10 +452,10 @@ one parent). If you want to abort a manual merge, just do a hard
reset to HEAD with @kbd{X}. reset to HEAD with @kbd{X}.
Merges can fail if the two branches you merge want to introduce Merges can fail if the two branches you merge want to introduce
conflicting changes. In that case, the automatic merge stops before conflicting changes. In that case, the automatic merge stops before the
the commit, essentially falling back to a manual merge. You need to commit, essentially falling back to a manual merge. You need to resolve
resolve the conflicts and stage the resolved files, for example with the conflicts for example with @kbd{e} and stage the resolved files, for
@kbd{S}. example with @kbd{S}.
You can not stage individual hunks one by one as you resolve them, you You can not stage individual hunks one by one as you resolve them, you
can only stage whole files once all conflicts in them have been can only stage whole files once all conflicts in them have been