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"
TODO="$DOTEST"/todo
DONE="$DOTEST"/done
MSG="$DOTEST"/message
SQUASH_MSG="$DOTEST"/message-squash
REWRITTEN="$DOTEST"/rewritten
PRESERVE_MERGES=
STRATEGY=
@ -158,6 +160,38 @@ pick_one_preserving_merges () {
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 () {
test -f "$DOTEST"/message && rm "$DOTEST"/message
test -f "$DOTEST"/author-script && rm "$DOTEST"/author-script
@ -194,17 +228,19 @@ do_next () {
die "Cannot 'squash' without a previous commit"
mark_action_done
MSG="$DOTEST"/message
echo "# This is a combination of two commits." > "$MSG"
echo "# The first commit's message is:" >> "$MSG"
echo >> "$MSG"
git cat-file commit HEAD | sed -e '1,/^$/d' >> "$MSG"
echo >> "$MSG"
make_squash_message $sha1 > "$MSG"
case "$(peek_next_command)" in
squash)
EDIT_COMMIT=
cp "$MSG" "$SQUASH_MSG"
;;
*)
EDIT_COMMIT=-e
test -f "$SQUASH_MSG" && rm "$SQUASH_MSG"
esac
failed=f
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^
author_script=$(get_author_ident_from_commit $sha1)
echo "$author_script" > "$DOTEST"/author-script
@ -213,7 +249,7 @@ do_next () {
# This is like --amend, but with a different message
eval "$author_script"
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
git commit -F "$MSG" -e
git commit -F "$MSG" $EDIT_COMMIT
;;
t)
cp "$MSG" "$GIT_DIR"/MERGE_MSG

View file

@ -65,6 +65,7 @@ cat > fake-editor.sh << EOF
#!/bin/sh
test "\$1" = .git/COMMIT_EDITMSG && {
test -z "\$FAKE_COMMIT_MESSAGE" || echo "\$FAKE_COMMIT_MESSAGE" > "\$1"
test -z "\$FAKE_COMMIT_AMEND" || echo "\$FAKE_COMMIT_AMEND" >> "\$1"
exit
}
test -z "\$FAKE_LINES" && exit
@ -212,4 +213,12 @@ test_expect_success 'verbose flag is heeded, even after --continue' '
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