git.el: Added a command to amend a commit.
It reverts the commit and sets up the status and edit log buffer to allow making changes and recommitting it. Bound to C-c C-a. Signed-off-by: Alexandre Julliard <julliard@winehq.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
3f3d564aa7
commit
76127b3a0d
@ -740,6 +740,27 @@ Return the list of files that haven't been handled."
|
||||
(git-refresh-files)
|
||||
(git-refresh-ewoc-hf git-status)))
|
||||
|
||||
(defun git-mark-files (status files)
|
||||
"Mark all the specified FILES, and unmark the others."
|
||||
(setq files (sort files #'string-lessp))
|
||||
(let ((file (and files (pop files)))
|
||||
(node (ewoc-nth status 0)))
|
||||
(while node
|
||||
(let ((info (ewoc-data node)))
|
||||
(if (and file (string-equal (git-fileinfo->name info) file))
|
||||
(progn
|
||||
(unless (git-fileinfo->marked info)
|
||||
(setf (git-fileinfo->marked info) t)
|
||||
(setf (git-fileinfo->needs-refresh info) t))
|
||||
(setq file (pop files))
|
||||
(setq node (ewoc-next status node)))
|
||||
(when (git-fileinfo->marked info)
|
||||
(setf (git-fileinfo->marked info) nil)
|
||||
(setf (git-fileinfo->needs-refresh info) t))
|
||||
(if (and file (string-lessp file (git-fileinfo->name info)))
|
||||
(setq file (pop files))
|
||||
(setq node (ewoc-next status node))))))))
|
||||
|
||||
(defun git-marked-files ()
|
||||
"Return a list of all marked files, or if none a list containing just the file at cursor position."
|
||||
(unless git-status (error "Not in git-status buffer."))
|
||||
@ -1218,7 +1239,8 @@ Return the list of files that haven't been handled."
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "\n+\\'" nil t)
|
||||
(replace-match "\n" t t))
|
||||
(when sign-off (git-append-sign-off committer-name committer-email)))))
|
||||
(when sign-off (git-append-sign-off committer-name committer-email)))
|
||||
buffer))
|
||||
|
||||
(defun git-commit-file ()
|
||||
"Commit the marked file(s), asking for a commit message."
|
||||
@ -1251,6 +1273,52 @@ Return the list of files that haven't been handled."
|
||||
(setq buffer-file-coding-system coding-system)
|
||||
(re-search-forward (regexp-quote (concat git-log-msg-separator "\n")) nil t))))
|
||||
|
||||
(defun git-setup-commit-buffer (commit)
|
||||
"Setup the commit buffer with the contents of COMMIT."
|
||||
(let (author-name author-email subject date msg)
|
||||
(with-temp-buffer
|
||||
(let ((coding-system (git-get-logoutput-coding-system)))
|
||||
(git-call-process-env t nil "log" "-1" commit)
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "^Author: *\\(.*\\) <\\(.*\\)>$" nil t)
|
||||
(setq author-name (match-string 1))
|
||||
(setq author-email (match-string 2)))
|
||||
(when (re-search-forward "^Date: *\\(.*\\)$" nil t)
|
||||
(setq date (match-string 1)))
|
||||
(while (re-search-forward "^ \\(.*\\)$" nil t)
|
||||
(push (match-string 1) msg))
|
||||
(setq msg (nreverse msg))
|
||||
(setq subject (pop msg))
|
||||
(while (and msg (zerop (length (car msg))) (pop msg)))))
|
||||
(git-setup-log-buffer (get-buffer-create "*git-commit*")
|
||||
author-name author-email subject date
|
||||
(mapconcat #'identity msg "\n"))))
|
||||
|
||||
(defun git-get-commit-files (commit)
|
||||
"Retrieve the list of files modified by COMMIT."
|
||||
(let (files)
|
||||
(with-temp-buffer
|
||||
(git-call-process-env t nil "diff-tree" "-r" "-z" "--name-only" "--no-commit-id" commit)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\\([^\0]*\\)\0" nil t 1)
|
||||
(push (match-string 1) files)))
|
||||
files))
|
||||
|
||||
(defun git-amend-commit ()
|
||||
"Undo the last commit on HEAD, and set things up to commit an
|
||||
amended version of it."
|
||||
(interactive)
|
||||
(unless git-status (error "Not in git-status buffer."))
|
||||
(when (git-empty-db-p) (error "No commit to amend."))
|
||||
(let* ((commit (git-rev-parse "HEAD"))
|
||||
(files (git-get-commit-files commit)))
|
||||
(git-call-process-env nil nil "reset" "--soft" "HEAD^")
|
||||
(git-update-status-files (copy-sequence files) 'uptodate)
|
||||
(git-mark-files git-status files)
|
||||
(git-refresh-files)
|
||||
(git-setup-commit-buffer commit)
|
||||
(git-commit-file)))
|
||||
|
||||
(defun git-find-file ()
|
||||
"Visit the current file in its own buffer."
|
||||
(interactive)
|
||||
@ -1329,6 +1397,7 @@ Return the list of files that haven't been handled."
|
||||
|
||||
(unless git-status-mode-map
|
||||
(let ((map (make-keymap))
|
||||
(commit-map (make-sparse-keymap))
|
||||
(diff-map (make-sparse-keymap))
|
||||
(toggle-map (make-sparse-keymap)))
|
||||
(suppress-keymap map)
|
||||
@ -1337,6 +1406,7 @@ Return the list of files that haven't been handled."
|
||||
(define-key map " " 'git-next-file)
|
||||
(define-key map "a" 'git-add-file)
|
||||
(define-key map "c" 'git-commit-file)
|
||||
(define-key map "\C-c" commit-map)
|
||||
(define-key map "d" diff-map)
|
||||
(define-key map "=" 'git-diff-file)
|
||||
(define-key map "f" 'git-find-file)
|
||||
@ -1362,6 +1432,8 @@ Return the list of files that haven't been handled."
|
||||
(define-key map "x" 'git-remove-handled)
|
||||
(define-key map "\C-?" 'git-unmark-file-up)
|
||||
(define-key map "\M-\C-?" 'git-unmark-all)
|
||||
; the commit submap
|
||||
(define-key commit-map "\C-a" 'git-amend-commit)
|
||||
; the diff submap
|
||||
(define-key diff-map "b" 'git-diff-file-base)
|
||||
(define-key diff-map "c" 'git-diff-file-combined)
|
||||
|
Loading…
Reference in New Issue
Block a user