Skip to content

Commit

Permalink
git.el: Added a command to amend a commit.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alexandre Julliard authored and Junio C Hamano committed Feb 8, 2008
1 parent 3f3d564 commit 76127b3
Showing 1 changed file with 73 additions and 1 deletion.
74 changes: 73 additions & 1 deletion contrib/emacs/git.el
Original file line number Diff line number Diff line change
Expand Up @@ -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."))
Expand Down Expand Up @@ -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."
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down

0 comments on commit 76127b3

Please sign in to comment.