rebase: act on command line outside parsing loop
To later be able to use the command line processing in git-rebase.sh for both interactive and non-interactive rebases, move anything that is specific to non-interactive rebase outside of the parsing loop. Keep only parsing and validation of command line options in the loop. Signed-off-by: Martin von Zweigbergk <martin.von.zweigbergk@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
99de0640f2
commit
3426232248
@ -866,152 +866,158 @@ first and then run 'git rebase --continue' again."
|
|||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
shift
|
shift
|
||||||
test -z "$REBASE_ROOT" -a $# -ge 1 -a $# -le 2 ||
|
break
|
||||||
test ! -z "$REBASE_ROOT" -a $# -le 1 || usage
|
;;
|
||||||
test -d "$DOTEST" &&
|
esac
|
||||||
die "Interactive rebase already started"
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
git var GIT_COMMITTER_IDENT >/dev/null ||
|
test -z "$REBASE_ROOT" -a $# -ge 1 -a $# -le 2 ||
|
||||||
die "You need to set your committer info first"
|
test ! -z "$REBASE_ROOT" -a $# -le 1 || usage
|
||||||
|
test -d "$DOTEST" &&
|
||||||
|
die "Interactive rebase already started"
|
||||||
|
|
||||||
if test -z "$REBASE_ROOT"
|
git var GIT_COMMITTER_IDENT >/dev/null ||
|
||||||
then
|
die "You need to set your committer info first"
|
||||||
UPSTREAM_ARG="$1"
|
|
||||||
UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
|
|
||||||
test -z "$ONTO" && ONTO=$UPSTREAM
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
UPSTREAM=
|
|
||||||
UPSTREAM_ARG=--root
|
|
||||||
test -z "$ONTO" &&
|
|
||||||
die "You must specify --onto when using --root"
|
|
||||||
fi
|
|
||||||
run_pre_rebase_hook "$UPSTREAM_ARG" "$@"
|
|
||||||
|
|
||||||
comment_for_reflog start
|
if test -z "$REBASE_ROOT"
|
||||||
|
then
|
||||||
|
UPSTREAM_ARG="$1"
|
||||||
|
UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
|
||||||
|
test -z "$ONTO" && ONTO=$UPSTREAM
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
UPSTREAM=
|
||||||
|
UPSTREAM_ARG=--root
|
||||||
|
test -z "$ONTO" &&
|
||||||
|
die "You must specify --onto when using --root"
|
||||||
|
fi
|
||||||
|
run_pre_rebase_hook "$UPSTREAM_ARG" "$@"
|
||||||
|
|
||||||
require_clean_work_tree "rebase" "Please commit or stash them."
|
comment_for_reflog start
|
||||||
|
|
||||||
if test ! -z "$1"
|
require_clean_work_tree "rebase" "Please commit or stash them."
|
||||||
then
|
|
||||||
output git checkout "$1" -- ||
|
|
||||||
die "Could not checkout $1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
|
if test ! -z "$1"
|
||||||
mkdir "$DOTEST" || die "Could not create temporary $DOTEST"
|
then
|
||||||
|
output git checkout "$1" -- ||
|
||||||
|
die "Could not checkout $1"
|
||||||
|
fi
|
||||||
|
|
||||||
: > "$DOTEST"/interactive || die "Could not mark as interactive"
|
HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
|
||||||
git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||
|
mkdir "$DOTEST" || die "Could not create temporary $DOTEST"
|
||||||
echo "detached HEAD" > "$DOTEST"/head-name
|
|
||||||
|
|
||||||
echo $HEAD > "$DOTEST"/head
|
: > "$DOTEST"/interactive || die "Could not mark as interactive"
|
||||||
case "$REBASE_ROOT" in
|
git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||
|
||||||
'')
|
echo "detached HEAD" > "$DOTEST"/head-name
|
||||||
rm -f "$DOTEST"/rebase-root ;;
|
|
||||||
*)
|
|
||||||
: >"$DOTEST"/rebase-root ;;
|
|
||||||
esac
|
|
||||||
echo $ONTO > "$DOTEST"/onto
|
|
||||||
test -z "$STRATEGY" || echo "$STRATEGY" > "$DOTEST"/strategy
|
|
||||||
test t = "$VERBOSE" && : > "$DOTEST"/verbose
|
|
||||||
if test t = "$PRESERVE_MERGES"
|
|
||||||
then
|
|
||||||
if test -z "$REBASE_ROOT"
|
|
||||||
then
|
|
||||||
mkdir "$REWRITTEN" &&
|
|
||||||
for c in $(git merge-base --all $HEAD $UPSTREAM)
|
|
||||||
do
|
|
||||||
echo $ONTO > "$REWRITTEN"/$c ||
|
|
||||||
die "Could not init rewritten commits"
|
|
||||||
done
|
|
||||||
else
|
|
||||||
mkdir "$REWRITTEN" &&
|
|
||||||
echo $ONTO > "$REWRITTEN"/root ||
|
|
||||||
die "Could not init rewritten commits"
|
|
||||||
fi
|
|
||||||
# No cherry-pick because our first pass is to determine
|
|
||||||
# parents to rewrite and skipping dropped commits would
|
|
||||||
# prematurely end our probe
|
|
||||||
MERGES_OPTION=
|
|
||||||
first_after_upstream="$(git rev-list --reverse --first-parent $UPSTREAM..$HEAD | head -n 1)"
|
|
||||||
else
|
|
||||||
MERGES_OPTION="--no-merges --cherry-pick"
|
|
||||||
fi
|
|
||||||
|
|
||||||
SHORTHEAD=$(git rev-parse --short $HEAD)
|
echo $HEAD > "$DOTEST"/head
|
||||||
SHORTONTO=$(git rev-parse --short $ONTO)
|
case "$REBASE_ROOT" in
|
||||||
if test -z "$REBASE_ROOT"
|
'')
|
||||||
# this is now equivalent to ! -z "$UPSTREAM"
|
rm -f "$DOTEST"/rebase-root ;;
|
||||||
then
|
*)
|
||||||
SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM)
|
: >"$DOTEST"/rebase-root ;;
|
||||||
REVISIONS=$UPSTREAM...$HEAD
|
esac
|
||||||
SHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEAD
|
echo $ONTO > "$DOTEST"/onto
|
||||||
else
|
test -z "$STRATEGY" || echo "$STRATEGY" > "$DOTEST"/strategy
|
||||||
REVISIONS=$ONTO...$HEAD
|
test t = "$VERBOSE" && : > "$DOTEST"/verbose
|
||||||
SHORTREVISIONS=$SHORTHEAD
|
if test t = "$PRESERVE_MERGES"
|
||||||
fi
|
then
|
||||||
git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
|
if test -z "$REBASE_ROOT"
|
||||||
--abbrev=7 --reverse --left-right --topo-order \
|
then
|
||||||
$REVISIONS | \
|
mkdir "$REWRITTEN" &&
|
||||||
sed -n "s/^>//p" |
|
for c in $(git merge-base --all $HEAD $UPSTREAM)
|
||||||
while read -r shortsha1 rest
|
|
||||||
do
|
do
|
||||||
if test t != "$PRESERVE_MERGES"
|
echo $ONTO > "$REWRITTEN"/$c ||
|
||||||
then
|
die "Could not init rewritten commits"
|
||||||
printf '%s\n' "pick $shortsha1 $rest" >> "$TODO"
|
done
|
||||||
else
|
else
|
||||||
sha1=$(git rev-parse $shortsha1)
|
mkdir "$REWRITTEN" &&
|
||||||
if test -z "$REBASE_ROOT"
|
echo $ONTO > "$REWRITTEN"/root ||
|
||||||
|
die "Could not init rewritten commits"
|
||||||
|
fi
|
||||||
|
# No cherry-pick because our first pass is to determine
|
||||||
|
# parents to rewrite and skipping dropped commits would
|
||||||
|
# prematurely end our probe
|
||||||
|
MERGES_OPTION=
|
||||||
|
first_after_upstream="$(git rev-list --reverse --first-parent $UPSTREAM..$HEAD | head -n 1)"
|
||||||
|
else
|
||||||
|
MERGES_OPTION="--no-merges --cherry-pick"
|
||||||
|
fi
|
||||||
|
|
||||||
|
SHORTHEAD=$(git rev-parse --short $HEAD)
|
||||||
|
SHORTONTO=$(git rev-parse --short $ONTO)
|
||||||
|
if test -z "$REBASE_ROOT"
|
||||||
|
# this is now equivalent to ! -z "$UPSTREAM"
|
||||||
|
then
|
||||||
|
SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM)
|
||||||
|
REVISIONS=$UPSTREAM...$HEAD
|
||||||
|
SHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEAD
|
||||||
|
else
|
||||||
|
REVISIONS=$ONTO...$HEAD
|
||||||
|
SHORTREVISIONS=$SHORTHEAD
|
||||||
|
fi
|
||||||
|
git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
|
||||||
|
--abbrev=7 --reverse --left-right --topo-order \
|
||||||
|
$REVISIONS | \
|
||||||
|
sed -n "s/^>//p" |
|
||||||
|
while read -r shortsha1 rest
|
||||||
|
do
|
||||||
|
if test t != "$PRESERVE_MERGES"
|
||||||
|
then
|
||||||
|
printf '%s\n' "pick $shortsha1 $rest" >> "$TODO"
|
||||||
|
else
|
||||||
|
sha1=$(git rev-parse $shortsha1)
|
||||||
|
if test -z "$REBASE_ROOT"
|
||||||
|
then
|
||||||
|
preserve=t
|
||||||
|
for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)
|
||||||
|
do
|
||||||
|
if test -f "$REWRITTEN"/$p -a \( $p != $ONTO -o $sha1 = $first_after_upstream \)
|
||||||
then
|
then
|
||||||
preserve=t
|
|
||||||
for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)
|
|
||||||
do
|
|
||||||
if test -f "$REWRITTEN"/$p -a \( $p != $ONTO -o $sha1 = $first_after_upstream \)
|
|
||||||
then
|
|
||||||
preserve=f
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
preserve=f
|
preserve=f
|
||||||
fi
|
fi
|
||||||
if test f = "$preserve"
|
|
||||||
then
|
|
||||||
touch "$REWRITTEN"/$sha1
|
|
||||||
printf '%s\n' "pick $shortsha1 $rest" >> "$TODO"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Watch for commits that been dropped by --cherry-pick
|
|
||||||
if test t = "$PRESERVE_MERGES"
|
|
||||||
then
|
|
||||||
mkdir "$DROPPED"
|
|
||||||
# Save all non-cherry-picked changes
|
|
||||||
git rev-list $REVISIONS --left-right --cherry-pick | \
|
|
||||||
sed -n "s/^>//p" > "$DOTEST"/not-cherry-picks
|
|
||||||
# Now all commits and note which ones are missing in
|
|
||||||
# not-cherry-picks and hence being dropped
|
|
||||||
git rev-list $REVISIONS |
|
|
||||||
while read rev
|
|
||||||
do
|
|
||||||
if test -f "$REWRITTEN"/$rev -a "$(sane_grep "$rev" "$DOTEST"/not-cherry-picks)" = ""
|
|
||||||
then
|
|
||||||
# Use -f2 because if rev-list is telling us this commit is
|
|
||||||
# not worthwhile, we don't want to track its multiple heads,
|
|
||||||
# just the history of its first-parent for others that will
|
|
||||||
# be rebasing on top of it
|
|
||||||
git rev-list --parents -1 $rev | cut -d' ' -s -f2 > "$DROPPED"/$rev
|
|
||||||
short=$(git rev-list -1 --abbrev-commit --abbrev=7 $rev)
|
|
||||||
sane_grep -v "^[a-z][a-z]* $short" <"$TODO" > "${TODO}2" ; mv "${TODO}2" "$TODO"
|
|
||||||
rm "$REWRITTEN"/$rev
|
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
else
|
||||||
|
preserve=f
|
||||||
fi
|
fi
|
||||||
|
if test f = "$preserve"
|
||||||
|
then
|
||||||
|
touch "$REWRITTEN"/$sha1
|
||||||
|
printf '%s\n' "pick $shortsha1 $rest" >> "$TODO"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
test -s "$TODO" || echo noop >> "$TODO"
|
# Watch for commits that been dropped by --cherry-pick
|
||||||
test -n "$AUTOSQUASH" && rearrange_squash "$TODO"
|
if test t = "$PRESERVE_MERGES"
|
||||||
cat >> "$TODO" << EOF
|
then
|
||||||
|
mkdir "$DROPPED"
|
||||||
|
# Save all non-cherry-picked changes
|
||||||
|
git rev-list $REVISIONS --left-right --cherry-pick | \
|
||||||
|
sed -n "s/^>//p" > "$DOTEST"/not-cherry-picks
|
||||||
|
# Now all commits and note which ones are missing in
|
||||||
|
# not-cherry-picks and hence being dropped
|
||||||
|
git rev-list $REVISIONS |
|
||||||
|
while read rev
|
||||||
|
do
|
||||||
|
if test -f "$REWRITTEN"/$rev -a "$(sane_grep "$rev" "$DOTEST"/not-cherry-picks)" = ""
|
||||||
|
then
|
||||||
|
# Use -f2 because if rev-list is telling us this commit is
|
||||||
|
# not worthwhile, we don't want to track its multiple heads,
|
||||||
|
# just the history of its first-parent for others that will
|
||||||
|
# be rebasing on top of it
|
||||||
|
git rev-list --parents -1 $rev | cut -d' ' -s -f2 > "$DROPPED"/$rev
|
||||||
|
short=$(git rev-list -1 --abbrev-commit --abbrev=7 $rev)
|
||||||
|
sane_grep -v "^[a-z][a-z]* $short" <"$TODO" > "${TODO}2" ; mv "${TODO}2" "$TODO"
|
||||||
|
rm "$REWRITTEN"/$rev
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
test -s "$TODO" || echo noop >> "$TODO"
|
||||||
|
test -n "$AUTOSQUASH" && rearrange_squash "$TODO"
|
||||||
|
cat >> "$TODO" << EOF
|
||||||
|
|
||||||
# Rebase $SHORTREVISIONS onto $SHORTONTO
|
# Rebase $SHORTREVISIONS onto $SHORTONTO
|
||||||
#
|
#
|
||||||
@ -1028,22 +1034,18 @@ first and then run 'git rebase --continue' again."
|
|||||||
#
|
#
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
has_action "$TODO" ||
|
has_action "$TODO" ||
|
||||||
die_abort "Nothing to do"
|
die_abort "Nothing to do"
|
||||||
|
|
||||||
cp "$TODO" "$TODO".backup
|
cp "$TODO" "$TODO".backup
|
||||||
git_editor "$TODO" ||
|
git_editor "$TODO" ||
|
||||||
die_abort "Could not execute editor"
|
die_abort "Could not execute editor"
|
||||||
|
|
||||||
has_action "$TODO" ||
|
has_action "$TODO" ||
|
||||||
die_abort "Nothing to do"
|
die_abort "Nothing to do"
|
||||||
|
|
||||||
test -d "$REWRITTEN" || test -n "$NEVER_FF" || skip_unnecessary_picks
|
test -d "$REWRITTEN" || test -n "$NEVER_FF" || skip_unnecessary_picks
|
||||||
|
|
||||||
output git checkout $ONTO || die_abort "could not detach HEAD"
|
output git checkout $ONTO || die_abort "could not detach HEAD"
|
||||||
git update-ref ORIG_HEAD $HEAD
|
git update-ref ORIG_HEAD $HEAD
|
||||||
do_rest
|
do_rest
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
126
git-rebase.sh
126
git-rebase.sh
@ -62,6 +62,8 @@ in_progress=
|
|||||||
type=
|
type=
|
||||||
# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge}
|
# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge}
|
||||||
state_dir=
|
state_dir=
|
||||||
|
# One of {'', continue, skip, abort}, as parsed from command line
|
||||||
|
action=
|
||||||
|
|
||||||
read_state () {
|
read_state () {
|
||||||
if test "$type" = merge
|
if test "$type" = merge
|
||||||
@ -236,66 +238,10 @@ do
|
|||||||
--verify)
|
--verify)
|
||||||
OK_TO_SKIP_PRE_REBASE=
|
OK_TO_SKIP_PRE_REBASE=
|
||||||
;;
|
;;
|
||||||
--continue)
|
--continue|--skip|--abort)
|
||||||
test -z "$in_progress" && die "No rebase in progress?"
|
action=${1##--}
|
||||||
|
shift
|
||||||
git update-index --ignore-submodules --refresh &&
|
break
|
||||||
git diff-files --quiet --ignore-submodules || {
|
|
||||||
echo "You must edit all merge conflicts and then"
|
|
||||||
echo "mark them as resolved using git add"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
read_state
|
|
||||||
if test -d "$merge_dir"
|
|
||||||
then
|
|
||||||
continue_merge
|
|
||||||
while test "$msgnum" -le "$end"
|
|
||||||
do
|
|
||||||
call_merge "$msgnum"
|
|
||||||
continue_merge
|
|
||||||
done
|
|
||||||
finish_rb_merge
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
git am --resolved --3way --resolvemsg="$RESOLVEMSG" &&
|
|
||||||
move_to_original_branch
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
--skip)
|
|
||||||
test -z "$in_progress" && die "No rebase in progress?"
|
|
||||||
|
|
||||||
git reset --hard HEAD || exit $?
|
|
||||||
read_state
|
|
||||||
if test -d "$merge_dir"
|
|
||||||
then
|
|
||||||
git rerere clear
|
|
||||||
msgnum=$(($msgnum + 1))
|
|
||||||
while test "$msgnum" -le "$end"
|
|
||||||
do
|
|
||||||
call_merge "$msgnum"
|
|
||||||
continue_merge
|
|
||||||
done
|
|
||||||
finish_rb_merge
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
|
|
||||||
move_to_original_branch
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
--abort)
|
|
||||||
test -z "$in_progress" && die "No rebase in progress?"
|
|
||||||
|
|
||||||
git rerere clear
|
|
||||||
read_state
|
|
||||||
case "$head_name" in
|
|
||||||
refs/*)
|
|
||||||
git symbolic-ref HEAD $head_name ||
|
|
||||||
die "Could not move back to $head_name"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
git reset --hard $orig_head
|
|
||||||
rm -r "$state_dir"
|
|
||||||
exit
|
|
||||||
;;
|
;;
|
||||||
--onto)
|
--onto)
|
||||||
test 2 -le "$#" || usage
|
test 2 -le "$#" || usage
|
||||||
@ -391,6 +337,66 @@ do
|
|||||||
done
|
done
|
||||||
test $# -gt 2 && usage
|
test $# -gt 2 && usage
|
||||||
|
|
||||||
|
test -n "$action" && test -z "$in_progress" && die "No rebase in progress?"
|
||||||
|
|
||||||
|
case "$action" in
|
||||||
|
continue)
|
||||||
|
git update-index --ignore-submodules --refresh &&
|
||||||
|
git diff-files --quiet --ignore-submodules || {
|
||||||
|
echo "You must edit all merge conflicts and then"
|
||||||
|
echo "mark them as resolved using git add"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
read_state
|
||||||
|
if test -d "$merge_dir"
|
||||||
|
then
|
||||||
|
continue_merge
|
||||||
|
while test "$msgnum" -le "$end"
|
||||||
|
do
|
||||||
|
call_merge "$msgnum"
|
||||||
|
continue_merge
|
||||||
|
done
|
||||||
|
finish_rb_merge
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
git am --resolved --3way --resolvemsg="$RESOLVEMSG" &&
|
||||||
|
move_to_original_branch
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
skip)
|
||||||
|
git reset --hard HEAD || exit $?
|
||||||
|
read_state
|
||||||
|
if test -d "$merge_dir"
|
||||||
|
then
|
||||||
|
git rerere clear
|
||||||
|
msgnum=$(($msgnum + 1))
|
||||||
|
while test "$msgnum" -le "$end"
|
||||||
|
do
|
||||||
|
call_merge "$msgnum"
|
||||||
|
continue_merge
|
||||||
|
done
|
||||||
|
finish_rb_merge
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
|
||||||
|
move_to_original_branch
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
abort)
|
||||||
|
git rerere clear
|
||||||
|
read_state
|
||||||
|
case "$head_name" in
|
||||||
|
refs/*)
|
||||||
|
git symbolic-ref HEAD $head_name ||
|
||||||
|
die "Could not move back to $head_name"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
git reset --hard $orig_head
|
||||||
|
rm -r "$state_dir"
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# Make sure no rebase is in progress
|
# Make sure no rebase is in progress
|
||||||
if test -n "$in_progress"
|
if test -n "$in_progress"
|
||||||
then
|
then
|
||||||
|
Loading…
Reference in New Issue
Block a user