mirror of
https://github.com/git/git.git
synced 2024-10-30 05:47:53 +01:00
79f43447d2
Absent this fix, attempts to rebase an orphan branch using "rebase -m" fails with: $ git rebase -m ORPHAN_TARGET_BASE First, rewinding head to replay your work on top of it... fatal: Could not parse object 'ORPHAN_ROOT_SHA^' Unknown exit code (128) from command: git-merge-recursive ORPHAN_ROOT_SHA^ -- HEAD ORPHAN_ROOT_SHA To fix, this will only include the rebase root's parent as a base if it exists, so that in cases of rebasing an orphan branch, it is a simple two-way merge. Note the default rebase behavior does not fail: $ git rebase ORPHAN_TARGET_BASE First, rewinding head to replay your work on top of it... Applying: ORPHAN_ROOT_COMMIT_MSG Using index info to reconstruct a base tree... A few tests were expecting the old behaviour to forbid rebasing such a history with "rebase -m", which now need to expect them to succeed. Signed-off-by: Ben Woosley <ben.woosley@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
169 lines
3.8 KiB
Bash
169 lines
3.8 KiB
Bash
# This shell script fragment is sourced by git-rebase to implement
|
|
# its merge-based non-interactive mode that copes well with renamed
|
|
# files.
|
|
#
|
|
# Copyright (c) 2010 Junio C Hamano.
|
|
#
|
|
|
|
prec=4
|
|
|
|
read_state () {
|
|
onto_name=$(cat "$state_dir"/onto_name) &&
|
|
end=$(cat "$state_dir"/end) &&
|
|
msgnum=$(cat "$state_dir"/msgnum)
|
|
}
|
|
|
|
continue_merge () {
|
|
test -d "$state_dir" || die "$state_dir directory does not exist"
|
|
|
|
unmerged=$(git ls-files -u)
|
|
if test -n "$unmerged"
|
|
then
|
|
echo "You still have unmerged paths in your index"
|
|
echo "did you forget to use git add?"
|
|
die "$resolvemsg"
|
|
fi
|
|
|
|
cmt=$(cat "$state_dir/current")
|
|
if ! git diff-index --quiet --ignore-submodules HEAD --
|
|
then
|
|
if ! git commit ${gpg_sign_opt:+"$gpg_sign_opt"} --no-verify -C "$cmt"
|
|
then
|
|
echo "Commit failed, please do not call \"git commit\""
|
|
echo "directly, but instead do one of the following: "
|
|
die "$resolvemsg"
|
|
fi
|
|
if test -z "$GIT_QUIET"
|
|
then
|
|
printf "Committed: %0${prec}d " $msgnum
|
|
fi
|
|
echo "$cmt $(git rev-parse HEAD^0)" >> "$state_dir/rewritten"
|
|
else
|
|
if test -z "$GIT_QUIET"
|
|
then
|
|
printf "Already applied: %0${prec}d " $msgnum
|
|
fi
|
|
fi
|
|
test -z "$GIT_QUIET" &&
|
|
GIT_PAGER='' git log --format=%s -1 "$cmt"
|
|
|
|
# onto the next patch:
|
|
msgnum=$(($msgnum + 1))
|
|
echo "$msgnum" >"$state_dir/msgnum"
|
|
}
|
|
|
|
call_merge () {
|
|
msgnum="$1"
|
|
echo "$msgnum" >"$state_dir/msgnum"
|
|
cmt="$(cat "$state_dir/cmt.$msgnum")"
|
|
echo "$cmt" > "$state_dir/current"
|
|
hd=$(git rev-parse --verify HEAD)
|
|
cmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD)
|
|
eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
|
|
eval GITHEAD_$hd='$onto_name'
|
|
export GITHEAD_$cmt GITHEAD_$hd
|
|
if test -n "$GIT_QUIET"
|
|
then
|
|
GIT_MERGE_VERBOSITY=1 && export GIT_MERGE_VERBOSITY
|
|
fi
|
|
test -z "$strategy" && strategy=recursive
|
|
# If cmt doesn't have a parent, don't include it as a base
|
|
base=$(git rev-parse --verify --quiet $cmt^)
|
|
eval 'git-merge-$strategy' $strategy_opts $base ' -- "$hd" "$cmt"'
|
|
rv=$?
|
|
case "$rv" in
|
|
0)
|
|
unset GITHEAD_$cmt GITHEAD_$hd
|
|
return
|
|
;;
|
|
1)
|
|
git rerere $allow_rerere_autoupdate
|
|
die "$resolvemsg"
|
|
;;
|
|
2)
|
|
echo "Strategy: $strategy failed, try another" 1>&2
|
|
die "$resolvemsg"
|
|
;;
|
|
*)
|
|
die "Unknown exit code ($rv) from command:" \
|
|
"git-merge-$strategy $cmt^ -- HEAD $cmt"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
finish_rb_merge () {
|
|
move_to_original_branch
|
|
if test -s "$state_dir"/rewritten
|
|
then
|
|
git notes copy --for-rewrite=rebase <"$state_dir"/rewritten
|
|
hook="$(git rev-parse --git-path hooks/post-rewrite)"
|
|
test -x "$hook" && "$hook" rebase <"$state_dir"/rewritten
|
|
fi
|
|
say All done.
|
|
}
|
|
|
|
# The whole contents of this file is run by dot-sourcing it from
|
|
# inside a shell function. It used to be that "return"s we see
|
|
# below were not inside any function, and expected to return
|
|
# to the function that dot-sourced us.
|
|
#
|
|
# However, FreeBSD /bin/sh misbehaves on such a construct and
|
|
# continues to run the statements that follow such a "return".
|
|
# As a work-around, we introduce an extra layer of a function
|
|
# here, and immediately call it after defining it.
|
|
git_rebase__merge () {
|
|
|
|
case "$action" in
|
|
continue)
|
|
read_state
|
|
continue_merge
|
|
while test "$msgnum" -le "$end"
|
|
do
|
|
call_merge "$msgnum"
|
|
continue_merge
|
|
done
|
|
finish_rb_merge
|
|
return
|
|
;;
|
|
skip)
|
|
read_state
|
|
git rerere clear
|
|
msgnum=$(($msgnum + 1))
|
|
while test "$msgnum" -le "$end"
|
|
do
|
|
call_merge "$msgnum"
|
|
continue_merge
|
|
done
|
|
finish_rb_merge
|
|
return
|
|
;;
|
|
esac
|
|
|
|
mkdir -p "$state_dir"
|
|
echo "$onto_name" > "$state_dir/onto_name"
|
|
write_basic_state
|
|
|
|
msgnum=0
|
|
for cmt in $(git rev-list --reverse --no-merges "$revisions")
|
|
do
|
|
msgnum=$(($msgnum + 1))
|
|
echo "$cmt" > "$state_dir/cmt.$msgnum"
|
|
done
|
|
|
|
echo 1 >"$state_dir/msgnum"
|
|
echo $msgnum >"$state_dir/end"
|
|
|
|
end=$msgnum
|
|
msgnum=1
|
|
|
|
while test "$msgnum" -le "$end"
|
|
do
|
|
call_merge "$msgnum"
|
|
continue_merge
|
|
done
|
|
|
|
finish_rb_merge
|
|
|
|
}
|
|
# ... and then we call the whole thing.
|
|
git_rebase__merge
|