branch: elpa/magit commit 9674c4755a9871568c780beb53bde9ad472db067 Author: Jonas Bernoulli <jo...@bernoul.li> Commit: Jonas Bernoulli <jo...@bernoul.li>
git-rebase-{alter,squish}: New commands --- docs/magit.org | 31 +++++++++++++++-- docs/magit.texi | 33 +++++++++++++++++-- lisp/git-rebase.el | 97 ++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 127 insertions(+), 34 deletions(-) diff --git a/docs/magit.org b/docs/magit.org index 4a9d4cd625..31ed501d3f 100644 --- a/docs/magit.org +++ b/docs/magit.org @@ -6112,12 +6112,37 @@ the following suffix commands. - Key: s (git-rebase-squash) :: - Meld commit on current line into previous commit, and edit message. + This command folds the commit on the current line into the previous + commit, giving the user a change to manually merge the two messages. + +- Key: S (git-rebase-squish) :: + + This command folds the commit on the current line into the previous + commit, discarding the message of the previous commit but giving the + user a change to edit the final message, based on the message of the + current commit. + + This action's indicator, shown in the list of commits, is ~fixup -c~ + (with a lower-case c). - Key: f (git-rebase-fixup) :: - Meld commit on current line into previous commit, discarding the - current commit's message. + This command folds the commit on the current line into the previous + commit, using only the message of the previous commit as-is and + discarding the message of the current commit. + +- Key: F (git-rebase-alter) :: + + This command folds the commit on the current into the previous + commit, discarding the message of the previous commit and instead + using the message of the current commit as-is. + + This is like ~git-rebase-alter~, except that it uses the other + message. This is also like ~git-rebase-squish~, except that it lets + the user edit the message. + + This action's indicator, shown in the list of commits, is ~fixup -C~ + (with a upper-case C). - Key: k (git-rebase-kill-line) :: diff --git a/docs/magit.texi b/docs/magit.texi index 3e36f80cb7..ef1e9fd663 100644 --- a/docs/magit.texi +++ b/docs/magit.texi @@ -7220,13 +7220,40 @@ Stop at the commit on the current line. @item @kbd{s} (@code{git-rebase-squash}) @kindex s @findex git-rebase-squash -Meld commit on current line into previous commit, and edit message. +This command folds the commit on the current line into the previous +commit, giving the user a change to manually merge the two messages. + +@item @kbd{S} (@code{git-rebase-squish}) +@kindex S +@findex git-rebase-squish +This command folds the commit on the current line into the previous +commit, discarding the message of the previous commit but giving the +user a change to edit the final message, based on the message of the +current commit. + +This action's indicator, shown in the list of commits, is @code{fixup -c} +(with a lower-case c). @item @kbd{f} (@code{git-rebase-fixup}) @kindex f @findex git-rebase-fixup -Meld commit on current line into previous commit, discarding the -current commit's message. +This command folds the commit on the current line into the previous +commit, using only the message of the previous commit as-is and +discarding the message of the current commit. + +@item @kbd{F} (@code{git-rebase-alter}) +@kindex F +@findex git-rebase-alter +This command folds the commit on the current into the previous +commit, discarding the message of the previous commit and instead +using the message of the current commit as-is. + +This is like @code{git-rebase-alter}, except that it uses the other +message. This is also like @code{git-rebase-squish}, except that it lets +the user edit the message. + +This action's indicator, shown in the list of commits, is @code{fixup -C} +(with a upper-case C). @item @kbd{k} (@code{git-rebase-kill-line}) @kindex k diff --git a/lisp/git-rebase.el b/lisp/git-rebase.el index 984d810b64..64a46d3e32 100644 --- a/lisp/git-rebase.el +++ b/lisp/git-rebase.el @@ -162,11 +162,14 @@ "M M" #'git-rebase-merge "M t" #'git-rebase-merge-toggle-editmsg "m" #'git-rebase-edit + "s" #'git-rebase-squash + "S" #'git-rebase-squish "f" #'git-rebase-fixup + "F" #'git-rebase-alter + "A" #'git-rebase-alter "q" #'undefined "r" #'git-rebase-reword "w" #'git-rebase-reword - "s" #'git-rebase-squash "t" #'git-rebase-reset "u" #'git-rebase-update-ref "x" #'git-rebase-exec @@ -178,6 +181,7 @@ "M-<up>" #'git-rebase-move-line-up "M-<down>" #'git-rebase-move-line-down "<remap> <undo>" #'git-rebase-undo) +(put 'git-rebase-alter :advertised-binding (kbd "F")) (put 'git-rebase-reword :advertised-binding (kbd "r")) (put 'git-rebase-move-line-up :advertised-binding (kbd "M-p")) (put 'git-rebase-kill-line :advertised-binding (kbd "k")) @@ -216,6 +220,17 @@ (git-rebase-insert . "insert a line for an arbitrary commit") (git-rebase-noop . "add noop action at point"))) +(defvar git-rebase-fixup-descriptions + '((git-rebase-squish + . "fixup -c <commit> = use commit, but meld into previous commit,\n#\ + dropping previous commit's message, and open the editor") + (git-rebase-fixup + . "fixup <commit> = use commit, but meld into previous commit,\n#\ + dropping <commit>'s message") + (git-rebase-alter + . "fixup -C <commit> = use commit, but meld into previous commit,\n#\ + dropping previous commit's message"))) + ;;; Commands (defun git-rebase-pick () @@ -243,17 +258,33 @@ If the region is active, act on all lines touched by the region." (git-rebase-set-action "edit")) (defun git-rebase-squash () - "Meld commit on current line into previous commit, edit message. + "Fold commit on current line into previous commit, edit combined message. If the region is active, act on all lines touched by the region." (interactive) (git-rebase-set-action "squash")) +(defun git-rebase-squish () + "Fold current into previous commit, discard previous message and edit current. +This is like `git-rebase-squash', except that the other message is kept. +The action indicatore shown in the list commits is \"fixup -c\". If the +region is active, act on all lines touched by the region." + (interactive) + (git-rebase-set-action "fixup -c")) + (defun git-rebase-fixup () - "Meld commit on current line into previous commit, discard its message. + "Fold commit on current line into previous commit, discard current message. If the region is active, act on all lines touched by the region." (interactive) (git-rebase-set-action "fixup")) +(defun git-rebase-alter () + "Meld current into previous commit, discard previous message and use current. +This is like `git-rebase-fixup', except that the other message is kept. +The action indicatore shown in the list commits is \"fixup -C\". If the +region is active, act on all lines touched by the region." + (interactive) + (git-rebase-set-action "fixup -C")) + (defvar-local git-rebase-comment-re nil) (defvar git-rebase-short-options @@ -291,12 +322,14 @@ If the region is active, act on all lines touched by the region." (defvar git-rebase-line-regexps `((commit . ,(concat - (regexp-opt '("e" "edit" - "d" "drop" - "f" "fixup" - "p" "pick" - "r" "reword" - "s" "squash") + (regexp-opt '("d" "drop" + "e" "edit" + "f" "fixup" + "f -C" "fixup -C" + "f -c" "fixup -c" + "p" "pick" + "r" "reword" + "s" "squash") "\\(?1:") " \\(?3:[^ \n]+\\) ?\\(?4:.*\\)")) (exec . "\\(?1:x\\|exec\\) \\(?3:.*\\)") @@ -815,24 +848,23 @@ except for the \"pick\" command." (concat git-rebase-comment-re "\\s-+p, pick") nil t)) (goto-char (line-beginning-position)) - (pcase-dolist (`(,cmd . ,desc) git-rebase-command-descriptions) - (insert (format (propertize "%s %s %s\n" - 'font-lock-face 'font-lock-comment-face) - comment-start - (string-pad - (substitute-command-keys (format "\\[%s]" cmd)) 8) - desc))) - (while (re-search-forward - (concat git-rebase-comment-re "\\(?:" - "\\( \\.? *\\)\\|" - "\\( +\\)\\([^\n,],\\) \\([^\n ]+\\) \\)") - nil t) - (if (match-string 1) - (replace-match (make-string 10 ?\s) t t nil 1) - (let ((cmd (intern (concat "git-rebase-" (match-string 4))))) - (if (not (fboundp cmd)) - (delete-region (line-beginning-position) - (1+ (line-end-position))) + (git-rebase--insert-descriptions git-rebase-command-descriptions) + (let ((cmd nil) + (line (concat git-rebase-comment-re "\\(?:\\( \\.? *\\)\\|" + "\\( +\\)\\([^\n,],\\) \\([^\n ]+\\) \\)"))) + (while (re-search-forward line nil t) + (if (match-string 1) + (if (assq cmd git-rebase-fixup-descriptions) + (delete-line) + (replace-match (make-string 10 ?\s) t t nil 1)) + (setq cmd (intern (concat "git-rebase-" (match-string 4)))) + (cond + ((not (fboundp cmd)) + (delete-line)) + ((eq cmd 'git-rebase-fixup) + (delete-line) + (git-rebase--insert-descriptions git-rebase-fixup-descriptions)) + (t (add-text-properties (line-beginning-position) (1+ (line-end-position)) '(font-lock-face font-lock-comment-face)) @@ -842,7 +874,16 @@ except for the \"pick\" command." (save-match-data (substitute-command-keys (format "\\[%s]" cmd))) 8) - t t nil 3))))))))) + t t nil 3)))))))))) + +(defun git-rebase--insert-descriptions (alist) + (pcase-dolist (`(,cmd . ,desc) alist) + (insert (format (propertize "%s %s %s\n" + 'font-lock-face 'font-lock-comment-face) + comment-start + (string-pad + (substitute-command-keys (format "\\[%s]" cmd)) 8) + desc)))) (add-hook 'git-rebase-mode-hook #'git-rebase-mode-show-keybindings t)