rebase -i: handle --continue more like non-interactive rebase

Non-interactive rebase requires the working tree to be clean, but
applies what is in the index without requiring the user to do it
herself.  Imitate that, but (since we are interactive, after all)
fire up an editor with the commit message.

It also fixes a subtle bug: a forgotten "continue" was removed, which
led to an infinite loop when continuing without remaining patches.

Both issues noticed by Frank Lichtenheld.

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-08 03:01:29 +01:00 committed by Junio C Hamano
parent 797e99a278
commit 18640d991b
2 changed files with 32 additions and 10 deletions

View File

@ -59,6 +59,10 @@ make_patch () {
} }
die_with_patch () { die_with_patch () {
test -f "$DOTEST"/message ||
git cat-file commit $sha1 | sed "1,/^$/d" > "$DOTEST"/message
test -f "$DOTEST"/author-script ||
get_author_ident_from_commit $sha1 > "$DOTEST"/author-script
make_patch "$1" make_patch "$1"
die "$2" die "$2"
} }
@ -140,10 +144,7 @@ pick_one_preserving_merges () {
if ! git merge $STRATEGY -m "$msg" $new_parents if ! git merge $STRATEGY -m "$msg" $new_parents
then then
echo "$msg" > "$GIT_DIR"/MERGE_MSG echo "$msg" > "$GIT_DIR"/MERGE_MSG
warn Error redoing merge $sha1 die Error redoing merge $sha1
warn
warn After fixup, please use
die "$author_script git commit"
fi fi
;; ;;
*) *)
@ -154,11 +155,12 @@ pick_one_preserving_merges () {
} }
do_next () { do_next () {
test -f "$DOTEST"/message && rm "$DOTEST"/message
test -f "$DOTEST"/author-script && rm "$DOTEST"/author-script
read command sha1 rest < "$TODO" read command sha1 rest < "$TODO"
case "$command" in case "$command" in
\#|'') \#|'')
mark_action_done mark_action_done
continue
;; ;;
pick) pick)
comment_for_reflog pick comment_for_reflog pick
@ -201,6 +203,7 @@ do_next () {
git cat-file commit $sha1 | sed -e '1,/^$/d' >> "$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
case $failed in case $failed in
f) f)
# This is like --amend, but with a different message # This is like --amend, but with a different message
@ -212,10 +215,6 @@ do_next () {
cp "$MSG" "$GIT_DIR"/MERGE_MSG cp "$MSG" "$GIT_DIR"/MERGE_MSG
warn warn
warn "Could not apply $sha1... $rest" warn "Could not apply $sha1... $rest"
warn "After you fixed that, commit the result with"
warn
warn " $(echo $author_script | tr '\012' ' ') \\"
warn " git commit -F \"$GIT_DIR\"/MERGE_MSG -e"
die_with_patch $sha1 "" die_with_patch $sha1 ""
esac esac
;; ;;
@ -265,6 +264,15 @@ do
test -d "$DOTEST" || die "No interactive rebase running" test -d "$DOTEST" || die "No interactive rebase running"
# commit if necessary
git rev-parse --verify HEAD > /dev/null &&
git update-index --refresh &&
git diff-files --quiet &&
! git diff-index --cached --quiet HEAD &&
. "$DOTEST"/author-script &&
export GIT_AUTHOR_NAME GIT_AUTHOR_NAME GIT_AUTHOR_DATE &&
git commit -F "$DOTEST"/message -e
require_clean_work_tree require_clean_work_tree
do_rest do_rest
;; ;;

View File

@ -63,7 +63,10 @@ test_expect_success 'setup' '
cat > fake-editor.sh << EOF cat > fake-editor.sh << EOF
#!/bin/sh #!/bin/sh
test "\$1" = .git/COMMIT_EDITMSG && exit test "\$1" = .git/COMMIT_EDITMSG && {
test -z "\$FAKE_COMMIT_MESSAGE" || echo "\$FAKE_COMMIT_MESSAGE" > "\$1"
exit
}
test -z "\$FAKE_LINES" && exit test -z "\$FAKE_LINES" && exit
grep -v "^#" < "\$1" > "\$1".tmp grep -v "^#" < "\$1" > "\$1".tmp
rm "\$1" rm "\$1"
@ -181,6 +184,7 @@ test_expect_success 'preserve merges with -p' '
echo C > file1 && echo C > file1 &&
test_tick && test_tick &&
git commit -m K file1 && git commit -m K file1 &&
test_tick &&
git rebase -i -p --onto branch1 master && git rebase -i -p --onto branch1 master &&
test $(git rev-parse HEAD^^2) = $(git rev-parse to-be-preserved) && test $(git rev-parse HEAD^^2) = $(git rev-parse to-be-preserved) &&
test $(git rev-parse HEAD~3) = $(git rev-parse branch1) && test $(git rev-parse HEAD~3) = $(git rev-parse branch1) &&
@ -188,4 +192,14 @@ test_expect_success 'preserve merges with -p' '
test $(git show HEAD~2:file1) = B test $(git show HEAD~2:file1) = B
' '
test_expect_success '--continue tries to commit' '
test_tick &&
! git rebase -i --onto new-branch1 HEAD^ &&
echo resolved > file1 &&
git add file1 &&
FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue &&
test $(git rev-parse HEAD^) = $(git rev-parse new-branch1) &&
git show HEAD | grep chouette
'
test_done test_done