Skip to content

Commit 2147f84

Browse files
arachsysgitster
authored andcommitted
rebase -i: handle fixup of root commit correctly
There is a bug with git rebase -i --root when a fixup or squash line is applied to the new root. We attempt to amend the commit onto which they apply with git reset --soft HEAD^ followed by a normal commit. Unlike a real commit --amend, this sequence will fail against a root commit as it has no parent. Fix rebase -i to use commit --amend for fixup and squash instead, and add a test for the case of a fixup of the root commit. Signed-off-by: Chris Webb <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 994fd91 commit 2147f84

File tree

2 files changed

+21
-12
lines changed

2 files changed

+21
-12
lines changed

git-rebase--interactive.sh

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -495,25 +495,28 @@ do_next () {
495495
author_script_content=$(get_author_ident_from_commit HEAD)
496496
echo "$author_script_content" > "$author_script"
497497
eval "$author_script_content"
498-
output git reset --soft HEAD^
499-
pick_one -n $sha1 || die_failed_squash $sha1 "$rest"
498+
if ! pick_one -n $sha1
499+
then
500+
git rev-parse --verify HEAD >"$amend"
501+
die_failed_squash $sha1 "$rest"
502+
fi
500503
case "$(peek_next_command)" in
501504
squash|s|fixup|f)
502505
# This is an intermediate commit; its message will only be
503506
# used in case of trouble. So use the long version:
504-
do_with_author output git commit --no-verify -F "$squash_msg" ||
507+
do_with_author output git commit --amend --no-verify -F "$squash_msg" ||
505508
die_failed_squash $sha1 "$rest"
506509
;;
507510
*)
508511
# This is the final command of this squash/fixup group
509512
if test -f "$fixup_msg"
510513
then
511-
do_with_author git commit --no-verify -F "$fixup_msg" ||
514+
do_with_author git commit --amend --no-verify -F "$fixup_msg" ||
512515
die_failed_squash $sha1 "$rest"
513516
else
514517
cp "$squash_msg" "$GIT_DIR"/SQUASH_MSG || exit
515518
rm -f "$GIT_DIR"/MERGE_MSG
516-
do_with_author git commit --no-verify -e ||
519+
do_with_author git commit --amend --no-verify -F "$GIT_DIR"/SQUASH_MSG -e ||
517520
die_failed_squash $sha1 "$rest"
518521
fi
519522
rm -f "$squash_msg" "$fixup_msg"
@@ -729,21 +732,19 @@ In both case, once you're done, continue with:
729732
fi
730733
. "$author_script" ||
731734
die "Error trying to find the author identity to amend commit"
732-
current_head=
733735
if test -f "$amend"
734736
then
735737
current_head=$(git rev-parse --verify HEAD)
736738
test "$current_head" = $(cat "$amend") ||
737739
die "\
738740
You have uncommitted changes in your working tree. Please, commit them
739741
first and then run 'git rebase --continue' again."
740-
git reset --soft HEAD^ ||
741-
die "Cannot rewind the HEAD"
742+
do_with_author git commit --amend --no-verify -F "$msg" -e ||
743+
die "Could not commit staged changes."
744+
else
745+
do_with_author git commit --no-verify -F "$msg" -e ||
746+
die "Could not commit staged changes."
742747
fi
743-
do_with_author git commit --no-verify -F "$msg" -e || {
744-
test -n "$current_head" && git reset --soft $current_head
745-
die "Could not commit staged changes."
746-
}
747748
fi
748749

749750
record_in_rewritten "$(cat "$state_dir"/stopped-sha)"

t/t3404-rebase-interactive.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,4 +786,12 @@ test_expect_success 'rebase -i --root temporary sentinel commit' '
786786
git rebase --abort
787787
'
788788

789+
test_expect_success 'rebase -i --root fixup root commit' '
790+
git checkout B &&
791+
FAKE_LINES="1 fixup 2" git rebase -i --root &&
792+
test A = $(git cat-file commit HEAD | sed -ne \$p) &&
793+
test B = $(git show HEAD:file1) &&
794+
test 0 = $(git cat-file commit HEAD | grep -c ^parent\ )
795+
'
796+
789797
test_done

0 commit comments

Comments
 (0)