summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2010-01-20 14:41:48 -0800
committerLibravatar Junio C Hamano <gitster@pobox.com>2010-01-20 14:41:48 -0800
commitcc6b41cc7d38c1b2de9809c0995087a2378d27ec (patch)
treea0192c7abe36de838db16737fdf7972007d8d776
parentMerge branch 'il/push-set-upstream' (diff)
parentrebase-i: Ignore comments and blank lines in peek_next_command (diff)
downloadtgif-cc6b41cc7d38c1b2de9809c0995087a2378d27ec.tar.xz
Merge branch 'mh/rebase-fixup' (early part)
* 'mh/rebase-fixup' (early part): rebase-i: Ignore comments and blank lines in peek_next_command lib-rebase: Allow comments and blank lines to be added to the rebase script lib-rebase: Provide clearer debugging info about what the editor did Add a command "fixup" to rebase --interactive t3404: Use test_commit to set up test repository
-rw-r--r--Documentation/git-rebase.txt13
-rwxr-xr-xgit-rebase--interactive.sh45
-rw-r--r--t/lib-rebase.sh27
-rwxr-xr-xt/t3404-rebase-interactive.sh120
4 files changed, 137 insertions, 68 deletions
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index ca5e1e8653..9b648ece6e 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 1560e84bd5..d0b59c96c4 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"
@@ -787,6 +811,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 62f452c8ea..0db8250c58 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -5,12 +5,20 @@
# - override the commit message with $FAKE_COMMIT_MESSAGE,
# - amend the commit message with $FAKE_COMMIT_AMEND
# - check that non-commit messages have a certain line count with $EXPECT_COUNT
-# - rewrite a rebase -i script with $FAKE_LINES in the form
+# - rewrite a rebase -i script as directed by $FAKE_LINES.
+# $FAKE_LINES consists of a sequence of words separated by spaces.
+# The following word combinations are possible:
#
-# "[<lineno1>] [<lineno2>]..."
+# "<lineno>" -- add a "pick" line with the SHA1 taken from the
+# specified line.
#
-# If a line number is prefixed with "squash", "edit", or "reword", the
-# respective line's command will be replaced with the specified one.
+# "<cmd> <lineno>" -- add a line with the specified command
+# ("squash", "fixup", "edit", or "reword") and the SHA1 taken
+# from the specified line.
+#
+# "#" -- Add a comment line.
+#
+# ">" -- Add a blank line.
set_fake_editor () {
echo "#!$SHELL_PATH" >fake-editor.sh
@@ -28,19 +36,24 @@ test -z "$EXPECT_COUNT" ||
test -z "$FAKE_LINES" && exit
grep -v '^#' < "$1" > "$1".tmp
rm -f "$1"
+echo 'rebase -i script before editing:'
cat "$1".tmp
action=pick
for line in $FAKE_LINES; do
case $line in
- squash|edit|reword)
+ squash|fixup|edit|reword)
action="$line";;
+ "#")
+ echo '# comment' >> "$1";;
+ ">")
+ echo >> "$1";;
*)
- echo sed -n "${line}s/^pick/$action/p"
- sed -n "${line}p" < "$1".tmp
sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
action=pick;;
esac
done
+echo 'rebase -i script after editing:'
+cat "$1"
EOF
test_set_editor "$(pwd)/fake-editor.sh"
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 3a37793c0d..d9382e41d3 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -16,53 +16,26 @@ set_fake_editor
# set up two branches like this:
#
-# A - B - C - D - E
+# A - B - C - D - E (master)
# \
-# F - G - H
+# F - G - H (branch1)
# \
-# I
+# I (branch2)
#
-# where B, D and G touch the same file.
+# where A, B, D and G touch the same file.
test_expect_success 'setup' '
- : > file1 &&
- git add file1 &&
- test_tick &&
- git commit -m A &&
- git tag A &&
- echo 1 > file1 &&
- test_tick &&
- git commit -m B file1 &&
- : > file2 &&
- git add file2 &&
- test_tick &&
- git commit -m C &&
- echo 2 > file1 &&
- test_tick &&
- git commit -m D file1 &&
- : > file3 &&
- git add file3 &&
- test_tick &&
- git commit -m E &&
+ test_commit A file1 &&
+ test_commit B file1 &&
+ test_commit C file2 &&
+ test_commit D file1 &&
+ test_commit E file3 &&
git checkout -b branch1 A &&
- : > file4 &&
- git add file4 &&
- test_tick &&
- git commit -m F &&
- git tag F &&
- echo 3 > file1 &&
- test_tick &&
- git commit -m G file1 &&
- : > file5 &&
- git add file5 &&
- test_tick &&
- git commit -m H &&
+ test_commit F file4 &&
+ test_commit G file1 &&
+ test_commit H file5 &&
git checkout -b branch2 F &&
- : > file6 &&
- git add file6 &&
- test_tick &&
- git commit -m I &&
- git tag I
+ test_commit I file6
'
test_expect_success 'no changes are a nop' '
@@ -111,19 +84,20 @@ test_expect_success 'exchange two commits' '
cat > expect << EOF
diff --git a/file1 b/file1
-index e69de29..00750ed 100644
+index f70f10e..fd79235 100644
--- a/file1
+++ b/file1
-@@ -0,0 +1 @@
-+3
+@@ -1 +1 @@
+-A
++G
EOF
cat > expect2 << EOF
<<<<<<< HEAD
-2
+D
=======
-3
->>>>>>> b7ca976... G
+G
+>>>>>>> 91201e5... G
EOF
test_expect_success 'stop on conflicting pick' '
@@ -261,6 +235,60 @@ 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 ignores comments' '
+ git checkout -b skip-comments E &&
+ base=$(git rev-parse HEAD~4) &&
+ FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="# 1 # squash 2 # squash 3 # squash 4 #" \
+ EXPECT_HEADER_COUNT=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 skip-comments
+'
+
+test_expect_success 'squash ignores blank lines' '
+ git checkout -b skip-blank-lines E &&
+ base=$(git rev-parse HEAD~4) &&
+ FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="> 1 > squash 2 > squash 3 > squash 4 >" \
+ EXPECT_HEADER_COUNT=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 skip-blank-lines
+'
+
test_expect_success 'squash works as expected' '
for n in one two three four
do