Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
rebase -i: Retain user-edited commit messages after squash/fixup conf…
Browse files Browse the repository at this point in the history
…licts

When a squash/fixup fails due to a conflict, the user is required to
edit the commit message.  Previously, if further squash/fixup commands
followed the conflicting squash/fixup, this user-edited message was
discarded and a new automatically-generated commit message was
suggested.

Change the handling of conflicts within squash/fixup command series:
Whenever the user is required to intervene, consider the resulting
commit to be a new basis for the following squash/fixups and use its
commit message in later suggested combined commit messages.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
mhagger authored and gitster committed Jan 14, 2010
1 parent 6c4c44c commit 6bdcd0d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 39 deletions.
66 changes: 27 additions & 39 deletions git-rebase--interactive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,21 @@ peek_next_command () {
sed -n -e "/^#/d" -e "/^$/d" -e "s/ .*//p" -e "q" < "$TODO"
}

# A squash/fixup has failed. Prepare the long version of the squash
# commit message, then die_with_patch. This code path requires the
# user to edit the combined commit message for all commits that have
# been squashed/fixedup so far. So also erase the old squash
# messages, effectively causing the combined commit to be used as the
# new basis for any further squash/fixups. Args: sha1 rest
die_failed_squash() {
mv "$SQUASH_MSG" "$MSG" || exit
rm -f "$FIXUP_MSG"
cp "$MSG" "$GIT_DIR"/MERGE_MSG || exit
warn
warn "Could not apply $1... $2"
die_with_patch $1 ""
}

do_next () {
rm -f "$MSG" "$AUTHOR_SCRIPT" "$AMEND" || exit
read command sha1 rest < "$TODO"
Expand Down Expand Up @@ -465,58 +480,31 @@ do_next () {

mark_action_done
update_squash_messages $squash_style $sha1
failed=f
author_script=$(get_author_ident_from_commit HEAD)
echo "$author_script" > "$AUTHOR_SCRIPT"
eval "$author_script"
output git reset --soft HEAD^
pick_one -n $sha1 || failed=t
pick_one -n $sha1 || die_failed_squash $sha1 "$rest"
case "$(peek_next_command)" in
squash|s|fixup|f)
# This is an intermediate commit; its message will only be
# used in case of trouble. So use the long version:
if test $failed = f
then
do_with_author output git commit --no-verify -F "$SQUASH_MSG" ||
failed=t
fi
if test $failed = t
then
cp "$SQUASH_MSG" "$MSG" || exit
# After any kind of hiccup, prevent committing without
# opening the commit message editor:
rm -f "$FIXUP_MSG"
cp "$MSG" "$GIT_DIR"/MERGE_MSG || exit
warn
warn "Could not apply $sha1... $rest"
die_with_patch $sha1 ""
fi
do_with_author output git commit --no-verify -F "$SQUASH_MSG" ||
die_failed_squash $sha1 "$rest"
;;
*)
# This is the final command of this squash/fixup group
if test $failed = f
if test -f "$FIXUP_MSG"
then
if test -f "$FIXUP_MSG"
then
do_with_author git commit --no-verify -F "$FIXUP_MSG" ||
failed=t
else
cp "$SQUASH_MSG" "$GIT_DIR"/SQUASH_MSG || exit
rm -f "$GIT_DIR"/MERGE_MSG
do_with_author git commit --no-verify -e ||
failed=t
fi
fi
rm -f "$FIXUP_MSG"
if test $failed = t
then
mv "$SQUASH_MSG" "$MSG" || exit
cp "$MSG" "$GIT_DIR"/MERGE_MSG || exit
warn
warn "Could not apply $sha1... $rest"
die_with_patch $sha1 ""
do_with_author git commit --no-verify -F "$FIXUP_MSG" ||
die_failed_squash $sha1 "$rest"
else
cp "$SQUASH_MSG" "$GIT_DIR"/SQUASH_MSG || exit
rm -f "$GIT_DIR"/MERGE_MSG
do_with_author git commit --no-verify -e ||
die_failed_squash $sha1 "$rest"
fi
rm -f "$SQUASH_MSG"
rm -f "$SQUASH_MSG" "$FIXUP_MSG"
;;
esac
;;
Expand Down
36 changes: 36 additions & 0 deletions t/t3404-rebase-interactive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,42 @@ test_expect_success 'multi-fixup does not fire up editor' '
git branch -D multi-fixup
'

test_expect_success 'commit message used after conflict' '
git checkout -b conflict-fixup conflict-branch &&
base=$(git rev-parse HEAD~4) &&
(
FAKE_LINES="1 fixup 3 fixup 4" &&
export FAKE_LINES &&
test_must_fail git rebase -i $base
) &&
echo three > conflict &&
git add conflict &&
FAKE_COMMIT_AMEND="ONCE" EXPECT_HEADER_COUNT=2 \
git rebase --continue &&
test $base = $(git rev-parse HEAD^) &&
test 1 = $(git show | grep ONCE | wc -l) &&
git checkout to-be-rebased &&
git branch -D conflict-fixup
'

test_expect_success 'commit message retained after conflict' '
git checkout -b conflict-squash conflict-branch &&
base=$(git rev-parse HEAD~4) &&
(
FAKE_LINES="1 fixup 3 squash 4" &&
export FAKE_LINES &&
test_must_fail git rebase -i $base
) &&
echo three > conflict &&
git add conflict &&
FAKE_COMMIT_AMEND="TWICE" EXPECT_HEADER_COUNT=2 \
git rebase --continue &&
test $base = $(git rev-parse HEAD^) &&
test 2 = $(git show | grep TWICE | wc -l) &&
git checkout to-be-rebased &&
git branch -D conflict-squash
'

cat > expect-squash-fixup << EOF
B
Expand Down

0 comments on commit 6bdcd0d

Please sign in to comment.