Skip to content

Commit 0205e72

Browse files
mhaggergitster
authored andcommitted
Add a command "fixup" to rebase --interactive
The command is like "squash", except that it discards the commit message of the corresponding commit. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 163f392 commit 0205e72

File tree

4 files changed

+77
-18
lines changed

4 files changed

+77
-18
lines changed

Documentation/git-rebase.txt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,12 @@ If you just want to edit the commit message for a commit, replace the
382382
command "pick" with the command "reword".
383383

384384
If you want to fold two or more commits into one, replace the command
385-
"pick" with "squash" for the second and subsequent commit. If the
386-
commits had different authors, it will attribute the squashed commit to
387-
the author of the first commit.
385+
"pick" for the second and subsequent commits with "squash" or "fixup".
386+
If the commits had different authors, the folded commit will be
387+
attributed to the author of the first commit. The suggested commit
388+
message for the folded commit is the concatenation of the commit
389+
messages of the first commit and of those with the "squash" command,
390+
but omits the commit messages of commits with the "fixup" command.
388391

389392
'git-rebase' will stop when "pick" has been replaced with "edit" or
390393
when a command fails due to merge errors. When you are done editing
@@ -512,8 +515,8 @@ Easy case: The changes are literally the same.::
512515
Hard case: The changes are not the same.::
513516

514517
This happens if the 'subsystem' rebase had conflicts, or used
515-
`\--interactive` to omit, edit, or squash commits; or if the
516-
upstream used one of `commit \--amend`, `reset`, or
518+
`\--interactive` to omit, edit, squash, or fixup commits; or
519+
if the upstream used one of `commit \--amend`, `reset`, or
517520
`filter-branch`.
518521

519522

git-rebase--interactive.sh

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,10 @@ nth_string () {
302302

303303
make_squash_message () {
304304
if test -f "$SQUASH_MSG"; then
305-
COUNT=$(($(sed -n "s/^# This is [^0-9]*\([1-9][0-9]*\).*/\1/p" \
305+
# We want to be careful about matching only the commit
306+
# message comment lines generated by this function.
307+
# "[snrt][tdh]" matches the nth_string endings.
308+
COUNT=$(($(sed -n "s/^# Th[^0-9]*\([1-9][0-9]*\)[snrt][tdh] commit message.*:/\1/p" \
306309
< "$SQUASH_MSG" | sed -ne '$p')+1))
307310
echo "# This is a combination of $COUNT commits."
308311
sed -e 1d -e '2,/^./{
@@ -315,10 +318,23 @@ make_squash_message () {
315318
echo
316319
git cat-file commit HEAD | sed -e '1,/^$/d'
317320
fi
318-
echo
319-
echo "# This is the $(nth_string $COUNT) commit message:"
320-
echo
321-
git cat-file commit $1 | sed -e '1,/^$/d'
321+
case $1 in
322+
squash)
323+
echo
324+
echo "# This is the $(nth_string $COUNT) commit message:"
325+
echo
326+
git cat-file commit $2 | sed -e '1,/^$/d'
327+
;;
328+
fixup)
329+
echo
330+
echo "# The $(nth_string $COUNT) commit message will be skipped:"
331+
echo
332+
# Comment the lines of the commit message out using
333+
# "# " rather than "# " to make them less likely to
334+
# confuse the sed regexp above.
335+
git cat-file commit $2 | sed -e '1,/^$/d' -e 's/^/# /'
336+
;;
337+
esac
322338
}
323339

324340
peek_next_command () {
@@ -367,20 +383,28 @@ do_next () {
367383
warn
368384
exit 0
369385
;;
370-
squash|s)
371-
comment_for_reflog squash
386+
squash|s|fixup|f)
387+
case "$command" in
388+
squash|s)
389+
squash_style=squash
390+
;;
391+
fixup|f)
392+
squash_style=fixup
393+
;;
394+
esac
395+
comment_for_reflog $squash_style
372396

373397
test -f "$DONE" && has_action "$DONE" ||
374-
die "Cannot 'squash' without a previous commit"
398+
die "Cannot '$squash_style' without a previous commit"
375399

376400
mark_action_done
377-
make_squash_message $sha1 > "$MSG"
401+
make_squash_message $squash_style $sha1 > "$MSG"
378402
failed=f
379403
author_script=$(get_author_ident_from_commit HEAD)
380404
output git reset --soft HEAD^
381405
pick_one -n $sha1 || failed=t
382406
case "$(peek_next_command)" in
383-
squash|s)
407+
squash|s|fixup|f)
384408
USE_OUTPUT=output
385409
MSG_OPT=-F
386410
EDIT_OR_FILE="$MSG"
@@ -768,6 +792,7 @@ first and then run 'git rebase --continue' again."
768792
# r, reword = use commit, but edit the commit message
769793
# e, edit = use commit, but stop for amending
770794
# s, squash = use commit, but meld into previous commit
795+
# f, fixup = like "squash", but discard this commit's log message
771796
#
772797
# If you remove a line here THAT COMMIT WILL BE LOST.
773798
# However, if you remove everything, the rebase will be aborted.

t/lib-rebase.sh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
#
1010
# "[<lineno1>] [<lineno2>]..."
1111
#
12-
# If a line number is prefixed with "squash", "edit", or "reword", the
13-
# respective line's command will be replaced with the specified one.
12+
# If a line number is prefixed with "squash", "fixup", "edit", or
13+
# "reword", the respective line's command will be replaced with the
14+
# specified one.
1415

1516
set_fake_editor () {
1617
echo "#!$SHELL_PATH" >fake-editor.sh
@@ -32,7 +33,7 @@ cat "$1".tmp
3233
action=pick
3334
for line in $FAKE_LINES; do
3435
case $line in
35-
squash|edit|reword)
36+
squash|fixup|edit|reword)
3637
action="$line";;
3738
*)
3839
echo sed -n "${line}s/^pick/$action/p"

t/t3404-rebase-interactive.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,36 @@ test_expect_success 'multi-squash only fires up editor once' '
235235
test 1 = $(git show | grep ONCE | wc -l)
236236
'
237237

238+
test_expect_success 'multi-fixup only fires up editor once' '
239+
git checkout -b multi-fixup E &&
240+
base=$(git rev-parse HEAD~4) &&
241+
FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 fixup 3 fixup 4" \
242+
git rebase -i $base &&
243+
test $base = $(git rev-parse HEAD^) &&
244+
test 1 = $(git show | grep ONCE | wc -l) &&
245+
git checkout to-be-rebased &&
246+
git branch -D multi-fixup
247+
'
248+
249+
cat > expect-squash-fixup << EOF
250+
B
251+
252+
D
253+
254+
ONCE
255+
EOF
256+
257+
test_expect_success 'squash and fixup generate correct log messages' '
258+
git checkout -b squash-fixup E &&
259+
base=$(git rev-parse HEAD~4) &&
260+
FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 squash 3 fixup 4" \
261+
git rebase -i $base &&
262+
git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fixup &&
263+
test_cmp expect-squash-fixup actual-squash-fixup &&
264+
git checkout to-be-rebased &&
265+
git branch -D squash-fixup
266+
'
267+
238268
test_expect_success 'squash works as expected' '
239269
for n in one two three four
240270
do

0 commit comments

Comments
 (0)