@matheusbsbs / matheus-bagliano / commits / 76127b3a0d
Fork 0

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>

Alexandre Julliard committed Feb 7, 2008 at 13:50 UTC 76127b3a0d7cf359b12be80971f023b6ee07f7f9
1 file changed +73 -1
contrib/emacs/git.el
+73 -1
@@ -740,6 +740,27 @@ Return the list of files that haven't been handled."
740 (git-refresh-files)
741 (git-refresh-ewoc-hf git-status)))
742
743 +(defun git-mark-files (status files)
744 + "Mark all the specified FILES, and unmark the others."
745 + (setq files (sort files #'string-lessp))
746 + (let ((file (and files (pop files)))
747 + (node (ewoc-nth status 0)))
748 + (while node
749 + (let ((info (ewoc-data node)))
750 + (if (and file (string-equal (git-fileinfo->name info) file))
751 + (progn
752 + (unless (git-fileinfo->marked info)
753 + (setf (git-fileinfo->marked info) t)
754 + (setf (git-fileinfo->needs-refresh info) t))
755 + (setq file (pop files))
756 + (setq node (ewoc-next status node)))
757 + (when (git-fileinfo->marked info)
758 + (setf (git-fileinfo->marked info) nil)
759 + (setf (git-fileinfo->needs-refresh info) t))
760 + (if (and file (string-lessp file (git-fileinfo->name info)))
761 + (setq file (pop files))
762 + (setq node (ewoc-next status node))))))))
763 +
764 (defun git-marked-files ()
765 "Return a list of all marked files, or if none a list containing just the file at cursor position."
766 (unless git-status (error "Not in git-status buffer."))
@@ -1218,7 +1239,8 @@ Return the list of files that haven't been handled."
1239 (goto-char (point-min))
1240 (when (re-search-forward "\n+\\'" nil t)
1241 (replace-match "\n" t t))
1221 - (when sign-off (git-append-sign-off committer-name committer-email)))))
1242 + (when sign-off (git-append-sign-off committer-name committer-email)))
1243 + buffer))
1244
1245 (defun git-commit-file ()
1246 "Commit the marked file(s), asking for a commit message."
@@ -1251,6 +1273,52 @@ Return the list of files that haven't been handled."
1273 (setq buffer-file-coding-system coding-system)
1274 (re-search-forward (regexp-quote (concat git-log-msg-separator "\n")) nil t))))
1275
1276 +(defun git-setup-commit-buffer (commit)
1277 + "Setup the commit buffer with the contents of COMMIT."
1278 + (let (author-name author-email subject date msg)
1279 + (with-temp-buffer
1280 + (let ((coding-system (git-get-logoutput-coding-system)))
1281 + (git-call-process-env t nil "log" "-1" commit)
1282 + (goto-char (point-min))
1283 + (when (re-search-forward "^Author: *\\(.*\\) <\\(.*\\)>$" nil t)
1284 + (setq author-name (match-string 1))
1285 + (setq author-email (match-string 2)))
1286 + (when (re-search-forward "^Date: *\\(.*\\)$" nil t)
1287 + (setq date (match-string 1)))
1288 + (while (re-search-forward "^ \\(.*\\)$" nil t)
1289 + (push (match-string 1) msg))
1290 + (setq msg (nreverse msg))
1291 + (setq subject (pop msg))
1292 + (while (and msg (zerop (length (car msg))) (pop msg)))))
1293 + (git-setup-log-buffer (get-buffer-create "*git-commit*")
1294 + author-name author-email subject date
1295 + (mapconcat #'identity msg "\n"))))
1296 +
1297 +(defun git-get-commit-files (commit)
1298 + "Retrieve the list of files modified by COMMIT."
1299 + (let (files)
1300 + (with-temp-buffer
1301 + (git-call-process-env t nil "diff-tree" "-r" "-z" "--name-only" "--no-commit-id" commit)
1302 + (goto-char (point-min))
1303 + (while (re-search-forward "\\([^\0]*\\)\0" nil t 1)
1304 + (push (match-string 1) files)))
1305 + files))
1306 +
1307 +(defun git-amend-commit ()
1308 + "Undo the last commit on HEAD, and set things up to commit an
1309 +amended version of it."
1310 + (interactive)
1311 + (unless git-status (error "Not in git-status buffer."))
1312 + (when (git-empty-db-p) (error "No commit to amend."))
1313 + (let* ((commit (git-rev-parse "HEAD"))
1314 + (files (git-get-commit-files commit)))
1315 + (git-call-process-env nil nil "reset" "--soft" "HEAD^")
1316 + (git-update-status-files (copy-sequence files) 'uptodate)
1317 + (git-mark-files git-status files)
1318 + (git-refresh-files)
1319 + (git-setup-commit-buffer commit)
1320 + (git-commit-file)))
1321 +
1322 (defun git-find-file ()
1323 "Visit the current file in its own buffer."
1324 (interactive)
@@ -1329,6 +1397,7 @@ Return the list of files that haven't been handled."
1397
1398 (unless git-status-mode-map
1399 (let ((map (make-keymap))
1400 + (commit-map (make-sparse-keymap))
1401 (diff-map (make-sparse-keymap))
1402 (toggle-map (make-sparse-keymap)))
1403 (suppress-keymap map)
@@ -1337,6 +1406,7 @@ Return the list of files that haven't been handled."
1406 (define-key map " " 'git-next-file)
1407 (define-key map "a" 'git-add-file)
1408 (define-key map "c" 'git-commit-file)
1409 + (define-key map "\C-c" commit-map)
1410 (define-key map "d" diff-map)
1411 (define-key map "=" 'git-diff-file)
1412 (define-key map "f" 'git-find-file)
@@ -1362,6 +1432,8 @@ Return the list of files that haven't been handled."
1432 (define-key map "x" 'git-remove-handled)
1433 (define-key map "\C-?" 'git-unmark-file-up)
1434 (define-key map "\M-\C-?" 'git-unmark-all)
1435 + ; the commit submap
1436 + (define-key commit-map "\C-a" 'git-amend-commit)
1437 ; the diff submap
1438 (define-key diff-map "b" 'git-diff-file-base)
1439 (define-key diff-map "c" 'git-diff-file-combined)