Merge branch 'tr/rebase-root'
* tr/rebase-root: rebase: update documentation for --root rebase -i: learn to rebase root commit rebase: learn to rebase root commit rebase -i: execute hook only after argument checking
This commit is contained in:
commit
90abc19b5a
@ -8,10 +8,11 @@ git-rebase - Forward-port local commits to the updated upstream head
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
|
'git rebase' [-i | --interactive] [options] [--onto <newbase>]
|
||||||
[-s <strategy> | --strategy=<strategy>] [--no-verify]
|
<upstream> [<branch>]
|
||||||
[-C<n>] [ --whitespace=<option>] [-p | --preserve-merges]
|
'git rebase' [-i | --interactive] [options] --onto <newbase>
|
||||||
[--onto <newbase>] <upstream> [<branch>]
|
--root [<branch>]
|
||||||
|
|
||||||
'git rebase' --continue | --skip | --abort
|
'git rebase' --continue | --skip | --abort
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -22,7 +23,8 @@ it remains on the current branch.
|
|||||||
|
|
||||||
All changes made by commits in the current branch but that are not
|
All changes made by commits in the current branch but that are not
|
||||||
in <upstream> are saved to a temporary area. This is the same set
|
in <upstream> are saved to a temporary area. This is the same set
|
||||||
of commits that would be shown by `git log <upstream>..HEAD`.
|
of commits that would be shown by `git log <upstream>..HEAD` (or
|
||||||
|
`git log HEAD`, if --root is specified).
|
||||||
|
|
||||||
The current branch is reset to <upstream>, or <newbase> if the
|
The current branch is reset to <upstream>, or <newbase> if the
|
||||||
--onto option was supplied. This has the exact same effect as
|
--onto option was supplied. This has the exact same effect as
|
||||||
@ -255,6 +257,15 @@ OPTIONS
|
|||||||
--preserve-merges::
|
--preserve-merges::
|
||||||
Instead of ignoring merges, try to recreate them.
|
Instead of ignoring merges, try to recreate them.
|
||||||
|
|
||||||
|
--root::
|
||||||
|
Rebase all commits reachable from <branch>, instead of
|
||||||
|
limiting them with an <upstream>. This allows you to rebase
|
||||||
|
the root commit(s) on a branch. Must be used with --onto, and
|
||||||
|
will skip changes already contained in <newbase> (instead of
|
||||||
|
<upstream>). When used together with --preserve-merges, 'all'
|
||||||
|
root commits will be rewritten to have <newbase> as parent
|
||||||
|
instead.
|
||||||
|
|
||||||
include::merge-strategies.txt[]
|
include::merge-strategies.txt[]
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
|
@ -27,6 +27,7 @@ continue continue rebasing process
|
|||||||
abort abort rebasing process and restore original branch
|
abort abort rebasing process and restore original branch
|
||||||
skip skip current patch and continue rebasing process
|
skip skip current patch and continue rebasing process
|
||||||
no-verify override pre-rebase hook from stopping the operation
|
no-verify override pre-rebase hook from stopping the operation
|
||||||
|
root rebase all reachable commmits up to the root(s)
|
||||||
"
|
"
|
||||||
|
|
||||||
. git-sh-setup
|
. git-sh-setup
|
||||||
@ -44,6 +45,7 @@ STRATEGY=
|
|||||||
ONTO=
|
ONTO=
|
||||||
VERBOSE=
|
VERBOSE=
|
||||||
OK_TO_SKIP_PRE_REBASE=
|
OK_TO_SKIP_PRE_REBASE=
|
||||||
|
REBASE_ROOT=
|
||||||
|
|
||||||
GIT_CHERRY_PICK_HELP=" After resolving the conflicts,
|
GIT_CHERRY_PICK_HELP=" After resolving the conflicts,
|
||||||
mark the corrected paths with 'git add <paths>', and
|
mark the corrected paths with 'git add <paths>', and
|
||||||
@ -154,6 +156,11 @@ pick_one () {
|
|||||||
output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
|
output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
|
||||||
test -d "$REWRITTEN" &&
|
test -d "$REWRITTEN" &&
|
||||||
pick_one_preserving_merges "$@" && return
|
pick_one_preserving_merges "$@" && return
|
||||||
|
if test ! -z "$REBASE_ROOT"
|
||||||
|
then
|
||||||
|
output git cherry-pick "$@"
|
||||||
|
return
|
||||||
|
fi
|
||||||
parent_sha1=$(git rev-parse --verify $sha1^) ||
|
parent_sha1=$(git rev-parse --verify $sha1^) ||
|
||||||
die "Could not get the parent of $sha1"
|
die "Could not get the parent of $sha1"
|
||||||
current_sha1=$(git rev-parse --verify HEAD)
|
current_sha1=$(git rev-parse --verify HEAD)
|
||||||
@ -197,7 +204,11 @@ pick_one_preserving_merges () {
|
|||||||
|
|
||||||
# rewrite parents; if none were rewritten, we can fast-forward.
|
# rewrite parents; if none were rewritten, we can fast-forward.
|
||||||
new_parents=
|
new_parents=
|
||||||
pend=" $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)"
|
pend=" $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)"
|
||||||
|
if test "$pend" = " "
|
||||||
|
then
|
||||||
|
pend=" root"
|
||||||
|
fi
|
||||||
while [ "$pend" != "" ]
|
while [ "$pend" != "" ]
|
||||||
do
|
do
|
||||||
p=$(expr "$pend" : ' \([^ ]*\)')
|
p=$(expr "$pend" : ' \([^ ]*\)')
|
||||||
@ -227,7 +238,9 @@ pick_one_preserving_merges () {
|
|||||||
if test -f "$DROPPED"/$p
|
if test -f "$DROPPED"/$p
|
||||||
then
|
then
|
||||||
fast_forward=f
|
fast_forward=f
|
||||||
pend=" $(cat "$DROPPED"/$p)$pend"
|
replacement="$(cat "$DROPPED"/$p)"
|
||||||
|
test -z "$replacement" && replacement=root
|
||||||
|
pend=" $replacement$pend"
|
||||||
else
|
else
|
||||||
new_parents="$new_parents $p"
|
new_parents="$new_parents $p"
|
||||||
fi
|
fi
|
||||||
@ -443,6 +456,7 @@ get_saved_options () {
|
|||||||
test -d "$REWRITTEN" && PRESERVE_MERGES=t
|
test -d "$REWRITTEN" && PRESERVE_MERGES=t
|
||||||
test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
|
test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
|
||||||
test -f "$DOTEST"/verbose && VERBOSE=t
|
test -f "$DOTEST"/verbose && VERBOSE=t
|
||||||
|
test ! -s "$DOTEST"/upstream && REBASE_ROOT=t
|
||||||
}
|
}
|
||||||
|
|
||||||
while test $# != 0
|
while test $# != 0
|
||||||
@ -547,6 +561,9 @@ first and then run 'git rebase --continue' again."
|
|||||||
-i)
|
-i)
|
||||||
# yeah, we know
|
# yeah, we know
|
||||||
;;
|
;;
|
||||||
|
--root)
|
||||||
|
REBASE_ROOT=t
|
||||||
|
;;
|
||||||
--onto)
|
--onto)
|
||||||
shift
|
shift
|
||||||
ONTO=$(git rev-parse --verify "$1") ||
|
ONTO=$(git rev-parse --verify "$1") ||
|
||||||
@ -554,27 +571,36 @@ first and then run 'git rebase --continue' again."
|
|||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
shift
|
shift
|
||||||
run_pre_rebase_hook ${1+"$@"}
|
test ! -z "$REBASE_ROOT" -o $# -eq 1 -o $# -eq 2 || usage
|
||||||
test $# -eq 1 -o $# -eq 2 || usage
|
|
||||||
test -d "$DOTEST" &&
|
test -d "$DOTEST" &&
|
||||||
die "Interactive rebase already started"
|
die "Interactive rebase already started"
|
||||||
|
|
||||||
git var GIT_COMMITTER_IDENT >/dev/null ||
|
git var GIT_COMMITTER_IDENT >/dev/null ||
|
||||||
die "You need to set your committer info first"
|
die "You need to set your committer info first"
|
||||||
|
|
||||||
|
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_ARG=--root
|
||||||
|
test -z "$ONTO" &&
|
||||||
|
die "You must specify --onto when using --root"
|
||||||
|
fi
|
||||||
|
run_pre_rebase_hook "$UPSTREAM_ARG" "$@"
|
||||||
|
|
||||||
comment_for_reflog start
|
comment_for_reflog start
|
||||||
|
|
||||||
require_clean_work_tree
|
require_clean_work_tree
|
||||||
|
|
||||||
UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
|
if test ! -z "$1"
|
||||||
test -z "$ONTO" && ONTO=$UPSTREAM
|
|
||||||
|
|
||||||
if test ! -z "$2"
|
|
||||||
then
|
then
|
||||||
output git show-ref --verify --quiet "refs/heads/$2" ||
|
output git show-ref --verify --quiet "refs/heads/$1" ||
|
||||||
die "Invalid branchname: $2"
|
die "Invalid branchname: $1"
|
||||||
output git checkout "$2" ||
|
output git checkout "$1" ||
|
||||||
die "Could not checkout $2"
|
die "Could not checkout $1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
|
HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
|
||||||
@ -598,12 +624,19 @@ first and then run 'git rebase --continue' again."
|
|||||||
# This ensures that commits on merged, but otherwise
|
# This ensures that commits on merged, but otherwise
|
||||||
# unrelated side branches are left alone. (Think "X"
|
# unrelated side branches are left alone. (Think "X"
|
||||||
# in the man page's example.)
|
# in the man page's example.)
|
||||||
mkdir "$REWRITTEN" &&
|
if test -z "$REBASE_ROOT"
|
||||||
for c in $(git merge-base --all $HEAD $UPSTREAM)
|
then
|
||||||
do
|
mkdir "$REWRITTEN" &&
|
||||||
echo $ONTO > "$REWRITTEN"/$c ||
|
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"
|
die "Could not init rewritten commits"
|
||||||
done
|
fi
|
||||||
# No cherry-pick because our first pass is to determine
|
# No cherry-pick because our first pass is to determine
|
||||||
# parents to rewrite and skipping dropped commits would
|
# parents to rewrite and skipping dropped commits would
|
||||||
# prematurely end our probe
|
# prematurely end our probe
|
||||||
@ -613,12 +646,21 @@ first and then run 'git rebase --continue' again."
|
|||||||
MERGES_OPTION="--no-merges --cherry-pick"
|
MERGES_OPTION="--no-merges --cherry-pick"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM)
|
|
||||||
SHORTHEAD=$(git rev-parse --short $HEAD)
|
SHORTHEAD=$(git rev-parse --short $HEAD)
|
||||||
SHORTONTO=$(git rev-parse --short $ONTO)
|
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 \
|
git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
|
||||||
--abbrev=7 --reverse --left-right --topo-order \
|
--abbrev=7 --reverse --left-right --topo-order \
|
||||||
$UPSTREAM...$HEAD | \
|
$REVISIONS | \
|
||||||
sed -n "s/^>//p" | while read shortsha1 rest
|
sed -n "s/^>//p" | while read shortsha1 rest
|
||||||
do
|
do
|
||||||
if test t != "$PRESERVE_MERGES"
|
if test t != "$PRESERVE_MERGES"
|
||||||
@ -626,14 +668,19 @@ first and then run 'git rebase --continue' again."
|
|||||||
echo "pick $shortsha1 $rest" >> "$TODO"
|
echo "pick $shortsha1 $rest" >> "$TODO"
|
||||||
else
|
else
|
||||||
sha1=$(git rev-parse $shortsha1)
|
sha1=$(git rev-parse $shortsha1)
|
||||||
preserve=t
|
if test -z "$REBASE_ROOT"
|
||||||
for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
|
then
|
||||||
do
|
preserve=t
|
||||||
if test -f "$REWRITTEN"/$p -a \( $p != $UPSTREAM -o $sha1 = $first_after_upstream \)
|
for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)
|
||||||
then
|
do
|
||||||
preserve=f
|
if test -f "$REWRITTEN"/$p -a \( $p != $UPSTREAM -o $sha1 = $first_after_upstream \)
|
||||||
fi
|
then
|
||||||
done
|
preserve=f
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
preserve=f
|
||||||
|
fi
|
||||||
if test f = "$preserve"
|
if test f = "$preserve"
|
||||||
then
|
then
|
||||||
touch "$REWRITTEN"/$sha1
|
touch "$REWRITTEN"/$sha1
|
||||||
@ -647,11 +694,11 @@ first and then run 'git rebase --continue' again."
|
|||||||
then
|
then
|
||||||
mkdir "$DROPPED"
|
mkdir "$DROPPED"
|
||||||
# Save all non-cherry-picked changes
|
# Save all non-cherry-picked changes
|
||||||
git rev-list $UPSTREAM...$HEAD --left-right --cherry-pick | \
|
git rev-list $REVISIONS --left-right --cherry-pick | \
|
||||||
sed -n "s/^>//p" > "$DOTEST"/not-cherry-picks
|
sed -n "s/^>//p" > "$DOTEST"/not-cherry-picks
|
||||||
# Now all commits and note which ones are missing in
|
# Now all commits and note which ones are missing in
|
||||||
# not-cherry-picks and hence being dropped
|
# not-cherry-picks and hence being dropped
|
||||||
git rev-list $UPSTREAM..$HEAD |
|
git rev-list $REVISIONS |
|
||||||
while read rev
|
while read rev
|
||||||
do
|
do
|
||||||
if test -f "$REWRITTEN"/$rev -a "$(grep "$rev" "$DOTEST"/not-cherry-picks)" = ""
|
if test -f "$REWRITTEN"/$rev -a "$(grep "$rev" "$DOTEST"/not-cherry-picks)" = ""
|
||||||
@ -660,17 +707,18 @@ first and then run 'git rebase --continue' again."
|
|||||||
# not worthwhile, we don't want to track its multiple heads,
|
# not worthwhile, we don't want to track its multiple heads,
|
||||||
# just the history of its first-parent for others that will
|
# just the history of its first-parent for others that will
|
||||||
# be rebasing on top of it
|
# be rebasing on top of it
|
||||||
git rev-list --parents -1 $rev | cut -d' ' -f2 > "$DROPPED"/$rev
|
git rev-list --parents -1 $rev | cut -d' ' -s -f2 > "$DROPPED"/$rev
|
||||||
short=$(git rev-list -1 --abbrev-commit --abbrev=7 $rev)
|
short=$(git rev-list -1 --abbrev-commit --abbrev=7 $rev)
|
||||||
grep -v "^[a-z][a-z]* $short" <"$TODO" > "${TODO}2" ; mv "${TODO}2" "$TODO"
|
grep -v "^[a-z][a-z]* $short" <"$TODO" > "${TODO}2" ; mv "${TODO}2" "$TODO"
|
||||||
rm "$REWRITTEN"/$rev
|
rm "$REWRITTEN"/$rev
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test -s "$TODO" || echo noop >> "$TODO"
|
test -s "$TODO" || echo noop >> "$TODO"
|
||||||
cat >> "$TODO" << EOF
|
cat >> "$TODO" << EOF
|
||||||
|
|
||||||
# Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
|
# Rebase $SHORTREVISIONS onto $SHORTONTO
|
||||||
#
|
#
|
||||||
# Commands:
|
# Commands:
|
||||||
# p, pick = use commit
|
# p, pick = use commit
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
# Copyright (c) 2005 Junio C Hamano.
|
# Copyright (c) 2005 Junio C Hamano.
|
||||||
#
|
#
|
||||||
|
|
||||||
USAGE='[--interactive | -i] [-v] [--onto <newbase>] <upstream> [<branch>]'
|
USAGE='[--interactive | -i] [-v] [--onto <newbase>] [<upstream>|--root] [<branch>]'
|
||||||
LONG_USAGE='git-rebase replaces <branch> with a new branch of the
|
LONG_USAGE='git-rebase replaces <branch> with a new branch of the
|
||||||
same name. When the --onto option is provided the new branch starts
|
same name. When the --onto option is provided the new branch starts
|
||||||
out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
|
out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
|
||||||
@ -47,6 +47,7 @@ dotest="$GIT_DIR"/rebase-merge
|
|||||||
prec=4
|
prec=4
|
||||||
verbose=
|
verbose=
|
||||||
git_am_opt=
|
git_am_opt=
|
||||||
|
rebase_root=
|
||||||
|
|
||||||
continue_merge () {
|
continue_merge () {
|
||||||
test -n "$prev_head" || die "prev_head must be defined"
|
test -n "$prev_head" || die "prev_head must be defined"
|
||||||
@ -297,6 +298,9 @@ do
|
|||||||
-C*)
|
-C*)
|
||||||
git_am_opt="$git_am_opt $1"
|
git_am_opt="$git_am_opt $1"
|
||||||
;;
|
;;
|
||||||
|
--root)
|
||||||
|
rebase_root=t
|
||||||
|
;;
|
||||||
-*)
|
-*)
|
||||||
usage
|
usage
|
||||||
;;
|
;;
|
||||||
@ -344,17 +348,29 @@ case "$diff" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# The upstream head must be given. Make sure it is valid.
|
if test -z "$rebase_root"
|
||||||
upstream_name="$1"
|
then
|
||||||
upstream=`git rev-parse --verify "${upstream_name}^0"` ||
|
# The upstream head must be given. Make sure it is valid.
|
||||||
die "invalid upstream $upstream_name"
|
upstream_name="$1"
|
||||||
|
shift
|
||||||
|
upstream=`git rev-parse --verify "${upstream_name}^0"` ||
|
||||||
|
die "invalid upstream $upstream_name"
|
||||||
|
unset root_flag
|
||||||
|
upstream_arg="$upstream_name"
|
||||||
|
else
|
||||||
|
test -z "$newbase" && die "--root must be used with --onto"
|
||||||
|
unset upstream_name
|
||||||
|
unset upstream
|
||||||
|
root_flag="--root"
|
||||||
|
upstream_arg="$root_flag"
|
||||||
|
fi
|
||||||
|
|
||||||
# Make sure the branch to rebase onto is valid.
|
# Make sure the branch to rebase onto is valid.
|
||||||
onto_name=${newbase-"$upstream_name"}
|
onto_name=${newbase-"$upstream_name"}
|
||||||
onto=$(git rev-parse --verify "${onto_name}^0") || exit
|
onto=$(git rev-parse --verify "${onto_name}^0") || exit
|
||||||
|
|
||||||
# If a hook exists, give it a chance to interrupt
|
# If a hook exists, give it a chance to interrupt
|
||||||
run_pre_rebase_hook ${1+"$@"}
|
run_pre_rebase_hook "$upstream_arg" "$@"
|
||||||
|
|
||||||
# If the branch to rebase is given, that is the branch we will rebase
|
# If the branch to rebase is given, that is the branch we will rebase
|
||||||
# $branch_name -- branch being rebased, or HEAD (already detached)
|
# $branch_name -- branch being rebased, or HEAD (already detached)
|
||||||
@ -362,16 +378,16 @@ run_pre_rebase_hook ${1+"$@"}
|
|||||||
# $head_name -- refs/heads/<that-branch> or "detached HEAD"
|
# $head_name -- refs/heads/<that-branch> or "detached HEAD"
|
||||||
switch_to=
|
switch_to=
|
||||||
case "$#" in
|
case "$#" in
|
||||||
2)
|
1)
|
||||||
# Is it "rebase other $branchname" or "rebase other $commit"?
|
# Is it "rebase other $branchname" or "rebase other $commit"?
|
||||||
branch_name="$2"
|
branch_name="$1"
|
||||||
switch_to="$2"
|
switch_to="$1"
|
||||||
|
|
||||||
if git show-ref --verify --quiet -- "refs/heads/$2" &&
|
if git show-ref --verify --quiet -- "refs/heads/$1" &&
|
||||||
branch=$(git rev-parse -q --verify "refs/heads/$2")
|
branch=$(git rev-parse -q --verify "refs/heads/$1")
|
||||||
then
|
then
|
||||||
head_name="refs/heads/$2"
|
head_name="refs/heads/$1"
|
||||||
elif branch=$(git rev-parse -q --verify "$2")
|
elif branch=$(git rev-parse -q --verify "$1")
|
||||||
then
|
then
|
||||||
head_name="detached HEAD"
|
head_name="detached HEAD"
|
||||||
else
|
else
|
||||||
@ -393,7 +409,8 @@ case "$#" in
|
|||||||
esac
|
esac
|
||||||
orig_head=$branch
|
orig_head=$branch
|
||||||
|
|
||||||
# Now we are rebasing commits $upstream..$branch on top of $onto
|
# Now we are rebasing commits $upstream..$branch (or with --root,
|
||||||
|
# everything leading up to $branch) on top of $onto
|
||||||
|
|
||||||
# Check if we are already based on $onto with linear history,
|
# Check if we are already based on $onto with linear history,
|
||||||
# but this should be done only when upstream and onto are the same.
|
# but this should be done only when upstream and onto are the same.
|
||||||
@ -429,10 +446,17 @@ then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test -n "$rebase_root"
|
||||||
|
then
|
||||||
|
revisions="$onto..$orig_head"
|
||||||
|
else
|
||||||
|
revisions="$upstream..$orig_head"
|
||||||
|
fi
|
||||||
|
|
||||||
if test -z "$do_merge"
|
if test -z "$do_merge"
|
||||||
then
|
then
|
||||||
git format-patch -k --stdout --full-index --ignore-if-in-upstream \
|
git format-patch -k --stdout --full-index --ignore-if-in-upstream \
|
||||||
"$upstream..$orig_head" |
|
$root_flag "$revisions" |
|
||||||
git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" &&
|
git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" &&
|
||||||
move_to_original_branch
|
move_to_original_branch
|
||||||
ret=$?
|
ret=$?
|
||||||
@ -455,7 +479,7 @@ echo "$orig_head" > "$dotest/orig-head"
|
|||||||
echo "$head_name" > "$dotest/head-name"
|
echo "$head_name" > "$dotest/head-name"
|
||||||
|
|
||||||
msgnum=0
|
msgnum=0
|
||||||
for cmt in `git rev-list --reverse --no-merges "$upstream..$orig_head"`
|
for cmt in `git rev-list --reverse --no-merges "$revisions"`
|
||||||
do
|
do
|
||||||
msgnum=$(($msgnum + 1))
|
msgnum=$(($msgnum + 1))
|
||||||
echo "$cmt" > "$dotest/cmt.$msgnum"
|
echo "$cmt" > "$dotest/cmt.$msgnum"
|
||||||
|
187
t/t3412-rebase-root.sh
Executable file
187
t/t3412-rebase-root.sh
Executable file
@ -0,0 +1,187 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='git rebase --root
|
||||||
|
|
||||||
|
Tests if git rebase --root --onto <newparent> can rebase the root commit.
|
||||||
|
'
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
test_expect_success 'prepare repository' '
|
||||||
|
echo 1 > A &&
|
||||||
|
git add A &&
|
||||||
|
git commit -m 1 &&
|
||||||
|
echo 2 > A &&
|
||||||
|
git add A &&
|
||||||
|
git commit -m 2 &&
|
||||||
|
git symbolic-ref HEAD refs/heads/other &&
|
||||||
|
rm .git/index &&
|
||||||
|
echo 3 > B &&
|
||||||
|
git add B &&
|
||||||
|
git commit -m 3 &&
|
||||||
|
echo 1 > A &&
|
||||||
|
git add A &&
|
||||||
|
git commit -m 1b &&
|
||||||
|
echo 4 > B &&
|
||||||
|
git add B &&
|
||||||
|
git commit -m 4
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'rebase --root expects --onto' '
|
||||||
|
test_must_fail git rebase --root
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup pre-rebase hook' '
|
||||||
|
mkdir -p .git/hooks &&
|
||||||
|
cat >.git/hooks/pre-rebase <<EOF &&
|
||||||
|
#!$SHELL_PATH
|
||||||
|
echo "\$1,\$2" >.git/PRE-REBASE-INPUT
|
||||||
|
EOF
|
||||||
|
chmod +x .git/hooks/pre-rebase
|
||||||
|
'
|
||||||
|
cat > expect <<EOF
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'rebase --root --onto <newbase>' '
|
||||||
|
git checkout -b work &&
|
||||||
|
git rebase --root --onto master &&
|
||||||
|
git log --pretty=tformat:"%s" > rebased &&
|
||||||
|
test_cmp expect rebased
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'pre-rebase got correct input (1)' '
|
||||||
|
test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'rebase --root --onto <newbase> <branch>' '
|
||||||
|
git branch work2 other &&
|
||||||
|
git rebase --root --onto master work2 &&
|
||||||
|
git log --pretty=tformat:"%s" > rebased2 &&
|
||||||
|
test_cmp expect rebased2
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'pre-rebase got correct input (2)' '
|
||||||
|
test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work2
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'rebase -i --root --onto <newbase>' '
|
||||||
|
git checkout -b work3 other &&
|
||||||
|
GIT_EDITOR=: git rebase -i --root --onto master &&
|
||||||
|
git log --pretty=tformat:"%s" > rebased3 &&
|
||||||
|
test_cmp expect rebased3
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'pre-rebase got correct input (3)' '
|
||||||
|
test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'rebase -i --root --onto <newbase> <branch>' '
|
||||||
|
git branch work4 other &&
|
||||||
|
GIT_EDITOR=: git rebase -i --root --onto master work4 &&
|
||||||
|
git log --pretty=tformat:"%s" > rebased4 &&
|
||||||
|
test_cmp expect rebased4
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'pre-rebase got correct input (4)' '
|
||||||
|
test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work4
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'rebase -i -p with linear history' '
|
||||||
|
git checkout -b work5 other &&
|
||||||
|
GIT_EDITOR=: git rebase -i -p --root --onto master &&
|
||||||
|
git log --pretty=tformat:"%s" > rebased5 &&
|
||||||
|
test_cmp expect rebased5
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'pre-rebase got correct input (5)' '
|
||||||
|
test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'set up merge history' '
|
||||||
|
git checkout other^ &&
|
||||||
|
git checkout -b side &&
|
||||||
|
echo 5 > C &&
|
||||||
|
git add C &&
|
||||||
|
git commit -m 5 &&
|
||||||
|
git checkout other &&
|
||||||
|
git merge side
|
||||||
|
'
|
||||||
|
|
||||||
|
sed 's/#/ /g' > expect-side <<'EOF'
|
||||||
|
* Merge branch 'side' into other
|
||||||
|
|\##
|
||||||
|
| * 5
|
||||||
|
* | 4
|
||||||
|
|/##
|
||||||
|
* 3
|
||||||
|
* 2
|
||||||
|
* 1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'rebase -i -p with merge' '
|
||||||
|
git checkout -b work6 other &&
|
||||||
|
GIT_EDITOR=: git rebase -i -p --root --onto master &&
|
||||||
|
git log --graph --topo-order --pretty=tformat:"%s" > rebased6 &&
|
||||||
|
test_cmp expect-side rebased6
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'set up second root and merge' '
|
||||||
|
git symbolic-ref HEAD refs/heads/third &&
|
||||||
|
rm .git/index &&
|
||||||
|
rm A B C &&
|
||||||
|
echo 6 > D &&
|
||||||
|
git add D &&
|
||||||
|
git commit -m 6 &&
|
||||||
|
git checkout other &&
|
||||||
|
git merge third
|
||||||
|
'
|
||||||
|
|
||||||
|
sed 's/#/ /g' > expect-third <<'EOF'
|
||||||
|
* Merge branch 'third' into other
|
||||||
|
|\##
|
||||||
|
| * 6
|
||||||
|
* | Merge branch 'side' into other
|
||||||
|
|\ \##
|
||||||
|
| * | 5
|
||||||
|
* | | 4
|
||||||
|
|/ /##
|
||||||
|
* | 3
|
||||||
|
|/##
|
||||||
|
* 2
|
||||||
|
* 1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'rebase -i -p with two roots' '
|
||||||
|
git checkout -b work7 other &&
|
||||||
|
GIT_EDITOR=: git rebase -i -p --root --onto master &&
|
||||||
|
git log --graph --topo-order --pretty=tformat:"%s" > rebased7 &&
|
||||||
|
test_cmp expect-third rebased7
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup pre-rebase hook that fails' '
|
||||||
|
mkdir -p .git/hooks &&
|
||||||
|
cat >.git/hooks/pre-rebase <<EOF &&
|
||||||
|
#!$SHELL_PATH
|
||||||
|
false
|
||||||
|
EOF
|
||||||
|
chmod +x .git/hooks/pre-rebase
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'pre-rebase hook stops rebase' '
|
||||||
|
git checkout -b stops1 other &&
|
||||||
|
GIT_EDITOR=: test_must_fail git rebase --root --onto master &&
|
||||||
|
test "z$(git symbolic-ref HEAD)" = zrefs/heads/stops1
|
||||||
|
test 0 = $(git rev-list other...stops1 | wc -l)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'pre-rebase hook stops rebase -i' '
|
||||||
|
git checkout -b stops2 other &&
|
||||||
|
GIT_EDITOR=: test_must_fail git rebase --root --onto master &&
|
||||||
|
test "z$(git symbolic-ref HEAD)" = zrefs/heads/stops2
|
||||||
|
test 0 = $(git rev-list other...stops2 | wc -l)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in New Issue
Block a user