rebase -i: call editor just once for a multi-squash

Sometimes you want to squash more than two commits.  Before this patch,
the editor was fired up for each squash command.  Now the editor is
started only with the last squash command.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Johannes Schindelin 2007-07-21 18:09:41 +01:00 committed by Junio C Hamano
parent e1abc69b72
commit 6368f3f8e7
2 changed files with 55 additions and 10 deletions

View File

@ -19,6 +19,8 @@ require_work_tree
DOTEST="$GIT_DIR/.dotest-merge" DOTEST="$GIT_DIR/.dotest-merge"
TODO="$DOTEST"/todo TODO="$DOTEST"/todo
DONE="$DOTEST"/done DONE="$DOTEST"/done
MSG="$DOTEST"/message
SQUASH_MSG="$DOTEST"/message-squash
REWRITTEN="$DOTEST"/rewritten REWRITTEN="$DOTEST"/rewritten
PRESERVE_MERGES= PRESERVE_MERGES=
STRATEGY= STRATEGY=
@ -158,6 +160,38 @@ pick_one_preserving_merges () {
esac esac
} }
nth_string () {
case "$1" in
*1[0-9]|*[04-9]) echo "$1"th;;
*1) echo "$1"st;;
*2) echo "$1"nd;;
*3) echo "$1"rd;;
esac
}
make_squash_message () {
if [ -f "$SQUASH_MSG" ]; then
COUNT=$(($(sed -n "s/^# This is [^0-9]*\([0-9]\+\).*/\1/p" \
< "$SQUASH_MSG" | tail -n 1)+1))
echo "# This is a combination of $COUNT commits."
sed -n "2,\$p" < "$SQUASH_MSG"
else
COUNT=2
echo "# This is a combination of two commits."
echo "# The first commit's message is:"
echo
git cat-file commit HEAD | sed -e '1,/^$/d'
echo
fi
echo "# This is the $(nth_string $COUNT) commit message:"
echo
git cat-file commit $1 | sed -e '1,/^$/d'
}
peek_next_command () {
sed -n "1s/ .*$//p" < "$TODO"
}
do_next () { do_next () {
test -f "$DOTEST"/message && rm "$DOTEST"/message test -f "$DOTEST"/message && rm "$DOTEST"/message
test -f "$DOTEST"/author-script && rm "$DOTEST"/author-script test -f "$DOTEST"/author-script && rm "$DOTEST"/author-script
@ -194,17 +228,19 @@ do_next () {
die "Cannot 'squash' without a previous commit" die "Cannot 'squash' without a previous commit"
mark_action_done mark_action_done
MSG="$DOTEST"/message make_squash_message $sha1 > "$MSG"
echo "# This is a combination of two commits." > "$MSG" case "$(peek_next_command)" in
echo "# The first commit's message is:" >> "$MSG" squash)
echo >> "$MSG" EDIT_COMMIT=
git cat-file commit HEAD | sed -e '1,/^$/d' >> "$MSG" cp "$MSG" "$SQUASH_MSG"
echo >> "$MSG" ;;
*)
EDIT_COMMIT=-e
test -f "$SQUASH_MSG" && rm "$SQUASH_MSG"
esac
failed=f failed=f
pick_one -n $sha1 || failed=t pick_one -n $sha1 || failed=t
echo "# And this is the 2nd commit message:" >> "$MSG"
echo >> "$MSG"
git cat-file commit $sha1 | sed -e '1,/^$/d' >> "$MSG"
git reset --soft HEAD^ git reset --soft HEAD^
author_script=$(get_author_ident_from_commit $sha1) author_script=$(get_author_ident_from_commit $sha1)
echo "$author_script" > "$DOTEST"/author-script echo "$author_script" > "$DOTEST"/author-script
@ -213,7 +249,7 @@ do_next () {
# This is like --amend, but with a different message # This is like --amend, but with a different message
eval "$author_script" eval "$author_script"
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
git commit -F "$MSG" -e git commit -F "$MSG" $EDIT_COMMIT
;; ;;
t) t)
cp "$MSG" "$GIT_DIR"/MERGE_MSG cp "$MSG" "$GIT_DIR"/MERGE_MSG

View File

@ -65,6 +65,7 @@ cat > fake-editor.sh << EOF
#!/bin/sh #!/bin/sh
test "\$1" = .git/COMMIT_EDITMSG && { test "\$1" = .git/COMMIT_EDITMSG && {
test -z "\$FAKE_COMMIT_MESSAGE" || echo "\$FAKE_COMMIT_MESSAGE" > "\$1" test -z "\$FAKE_COMMIT_MESSAGE" || echo "\$FAKE_COMMIT_MESSAGE" > "\$1"
test -z "\$FAKE_COMMIT_AMEND" || echo "\$FAKE_COMMIT_AMEND" >> "\$1"
exit exit
} }
test -z "\$FAKE_LINES" && exit test -z "\$FAKE_LINES" && exit
@ -212,4 +213,12 @@ test_expect_success 'verbose flag is heeded, even after --continue' '
grep "^ file1 | 2 +-$" output grep "^ file1 | 2 +-$" output
' '
test_expect_success 'multi-squash only fires up editor once' '
base=$(git rev-parse HEAD~4) &&
FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 squash 2 squash 3 squash 4" \
git rebase -i $base &&
test $base = $(git rev-parse HEAD^) &&
test 1 = $(git show | grep ONCE | wc -l)
'
test_done test_done