branch: elpa/magit
commit 9674c4755a9871568c780beb53bde9ad472db067
Author: Jonas Bernoulli <[email protected]>
Commit: Jonas Bernoulli <[email protected]>
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 4a9d4cd625a..31ed501d3f3 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 3e36f80cb71..ef1e9fd663a 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 984d810b646..64a46d3e32d 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)