From 0205e72f088322a70a77643a7cd2d8b23ee07e14 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Mon, 7 Dec 2009 10:20:59 +0100 Subject: 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 Acked-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/git-rebase.txt | 13 ++++++++----- git-rebase--interactive.sh | 45 +++++++++++++++++++++++++++++++++---------- t/lib-rebase.sh | 7 ++++--- t/t3404-rebase-interactive.sh | 30 +++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 18 deletions(-) diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index ca5e1e865..9b648ece6 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -382,9 +382,12 @@ If you just want to edit the commit message for a commit, replace the command "pick" with the command "reword". If you want to fold two or more commits into one, replace the command -"pick" with "squash" for the second and subsequent commit. If the -commits had different authors, it will attribute the squashed commit to -the author of the first commit. +"pick" for the second and subsequent commits with "squash" or "fixup". +If the commits had different authors, the folded commit will be +attributed to the author of the first commit. The suggested commit +message for the folded commit is the concatenation of the commit +messages of the first commit and of those with the "squash" command, +but omits the commit messages of commits with the "fixup" command. 'git-rebase' will stop when "pick" has been replaced with "edit" or 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.:: Hard case: The changes are not the same.:: This happens if the 'subsystem' rebase had conflicts, or used - `\--interactive` to omit, edit, or squash commits; or if the - upstream used one of `commit \--amend`, `reset`, or + `\--interactive` to omit, edit, squash, or fixup commits; or + if the upstream used one of `commit \--amend`, `reset`, or `filter-branch`. diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 0bd3bf78b..30de96ee1 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -302,7 +302,10 @@ nth_string () { make_squash_message () { if test -f "$SQUASH_MSG"; then - COUNT=$(($(sed -n "s/^# This is [^0-9]*\([1-9][0-9]*\).*/\1/p" \ + # We want to be careful about matching only the commit + # message comment lines generated by this function. + # "[snrt][tdh]" matches the nth_string endings. + COUNT=$(($(sed -n "s/^# Th[^0-9]*\([1-9][0-9]*\)[snrt][tdh] commit message.*:/\1/p" \ < "$SQUASH_MSG" | sed -ne '$p')+1)) echo "# This is a combination of $COUNT commits." sed -e 1d -e '2,/^./{ @@ -315,10 +318,23 @@ make_squash_message () { echo git cat-file commit HEAD | sed -e '1,/^$/d' fi - echo - echo "# This is the $(nth_string $COUNT) commit message:" - echo - git cat-file commit $1 | sed -e '1,/^$/d' + case $1 in + squash) + echo + echo "# This is the $(nth_string $COUNT) commit message:" + echo + git cat-file commit $2 | sed -e '1,/^$/d' + ;; + fixup) + echo + echo "# The $(nth_string $COUNT) commit message will be skipped:" + echo + # Comment the lines of the commit message out using + # "# " rather than "# " to make them less likely to + # confuse the sed regexp above. + git cat-file commit $2 | sed -e '1,/^$/d' -e 's/^/# /' + ;; + esac } peek_next_command () { @@ -367,20 +383,28 @@ do_next () { warn exit 0 ;; - squash|s) - comment_for_reflog squash + squash|s|fixup|f) + case "$command" in + squash|s) + squash_style=squash + ;; + fixup|f) + squash_style=fixup + ;; + esac + comment_for_reflog $squash_style test -f "$DONE" && has_action "$DONE" || - die "Cannot 'squash' without a previous commit" + die "Cannot '$squash_style' without a previous commit" mark_action_done - make_squash_message $sha1 > "$MSG" + make_squash_message $squash_style $sha1 > "$MSG" failed=f author_script=$(get_author_ident_from_commit HEAD) output git reset --soft HEAD^ pick_one -n $sha1 || failed=t case "$(peek_next_command)" in - squash|s) + squash|s|fixup|f) USE_OUTPUT=output MSG_OPT=-F EDIT_OR_FILE="$MSG" @@ -768,6 +792,7 @@ first and then run 'git rebase --continue' again." # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit +# f, fixup = like "squash", but discard this commit's log message # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index 62f452c8e..f4dda02b5 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -9,8 +9,9 @@ # # "[] []..." # -# If a line number is prefixed with "squash", "edit", or "reword", the -# respective line's command will be replaced with the specified one. +# If a line number is prefixed with "squash", "fixup", "edit", or +# "reword", the respective line's command will be replaced with the +# specified one. set_fake_editor () { echo "#!$SHELL_PATH" >fake-editor.sh @@ -32,7 +33,7 @@ cat "$1".tmp action=pick for line in $FAKE_LINES; do case $line in - squash|edit|reword) + squash|fixup|edit|reword) action="$line";; *) echo sed -n "${line}s/^pick/$action/p" diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 778daf419..ea2611513 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -235,6 +235,36 @@ test_expect_success 'multi-squash only fires up editor once' ' test 1 = $(git show | grep ONCE | wc -l) ' +test_expect_success 'multi-fixup only fires up editor once' ' + git checkout -b multi-fixup E && + base=$(git rev-parse HEAD~4) && + FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 fixup 3 fixup 4" \ + git rebase -i $base && + test $base = $(git rev-parse HEAD^) && + test 1 = $(git show | grep ONCE | wc -l) && + git checkout to-be-rebased && + git branch -D multi-fixup +' + +cat > expect-squash-fixup << EOF +B + +D + +ONCE +EOF + +test_expect_success 'squash and fixup generate correct log messages' ' + git checkout -b squash-fixup E && + base=$(git rev-parse HEAD~4) && + FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 squash 3 fixup 4" \ + git rebase -i $base && + git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fixup && + test_cmp expect-squash-fixup actual-squash-fixup && + git checkout to-be-rebased && + git branch -D squash-fixup +' + test_expect_success 'squash works as expected' ' for n in one two three four do -- cgit v1.2.1