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 checkingmaint
						commit
						90abc19b5a
					
				| 
						 | 
				
			
			@ -8,10 +8,11 @@ git-rebase - Forward-port local commits to the updated upstream head
 | 
			
		|||
SYNOPSIS
 | 
			
		||||
--------
 | 
			
		||||
[verse]
 | 
			
		||||
'git rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
 | 
			
		||||
	[-s <strategy> | --strategy=<strategy>] [--no-verify]
 | 
			
		||||
	[-C<n>] [ --whitespace=<option>] [-p | --preserve-merges]
 | 
			
		||||
	[--onto <newbase>] <upstream> [<branch>]
 | 
			
		||||
'git rebase' [-i | --interactive] [options] [--onto <newbase>]
 | 
			
		||||
	<upstream> [<branch>]
 | 
			
		||||
'git rebase' [-i | --interactive] [options] --onto <newbase>
 | 
			
		||||
	--root [<branch>]
 | 
			
		||||
 | 
			
		||||
'git rebase' --continue | --skip | --abort
 | 
			
		||||
 | 
			
		||||
DESCRIPTION
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +23,8 @@ it remains on the current branch.
 | 
			
		|||
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
--onto option was supplied.  This has the exact same effect as
 | 
			
		||||
| 
						 | 
				
			
			@ -255,6 +257,15 @@ OPTIONS
 | 
			
		|||
--preserve-merges::
 | 
			
		||||
	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[]
 | 
			
		||||
 | 
			
		||||
NOTES
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ continue           continue rebasing process
 | 
			
		|||
abort              abort rebasing process and restore original branch
 | 
			
		||||
skip               skip current patch and continue rebasing process
 | 
			
		||||
no-verify          override pre-rebase hook from stopping the operation
 | 
			
		||||
root               rebase all reachable commmits up to the root(s)
 | 
			
		||||
"
 | 
			
		||||
 | 
			
		||||
. git-sh-setup
 | 
			
		||||
| 
						 | 
				
			
			@ -44,6 +45,7 @@ STRATEGY=
 | 
			
		|||
ONTO=
 | 
			
		||||
VERBOSE=
 | 
			
		||||
OK_TO_SKIP_PRE_REBASE=
 | 
			
		||||
REBASE_ROOT=
 | 
			
		||||
 | 
			
		||||
GIT_CHERRY_PICK_HELP="  After resolving the conflicts,
 | 
			
		||||
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"
 | 
			
		||||
	test -d "$REWRITTEN" &&
 | 
			
		||||
		pick_one_preserving_merges "$@" && return
 | 
			
		||||
	if test ! -z "$REBASE_ROOT"
 | 
			
		||||
	then
 | 
			
		||||
		output git cherry-pick "$@"
 | 
			
		||||
		return
 | 
			
		||||
	fi
 | 
			
		||||
	parent_sha1=$(git rev-parse --verify $sha1^) ||
 | 
			
		||||
		die "Could not get the parent of $sha1"
 | 
			
		||||
	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.
 | 
			
		||||
	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" != "" ]
 | 
			
		||||
	do
 | 
			
		||||
		p=$(expr "$pend" : ' \([^ ]*\)')
 | 
			
		||||
| 
						 | 
				
			
			@ -227,7 +238,9 @@ pick_one_preserving_merges () {
 | 
			
		|||
			if test -f "$DROPPED"/$p
 | 
			
		||||
			then
 | 
			
		||||
				fast_forward=f
 | 
			
		||||
				pend=" $(cat "$DROPPED"/$p)$pend"
 | 
			
		||||
				replacement="$(cat "$DROPPED"/$p)"
 | 
			
		||||
				test -z "$replacement" && replacement=root
 | 
			
		||||
				pend=" $replacement$pend"
 | 
			
		||||
			else
 | 
			
		||||
				new_parents="$new_parents $p"
 | 
			
		||||
			fi
 | 
			
		||||
| 
						 | 
				
			
			@ -443,6 +456,7 @@ get_saved_options () {
 | 
			
		|||
	test -d "$REWRITTEN" && PRESERVE_MERGES=t
 | 
			
		||||
	test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
 | 
			
		||||
	test -f "$DOTEST"/verbose && VERBOSE=t
 | 
			
		||||
	test ! -s "$DOTEST"/upstream && REBASE_ROOT=t
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
while test $# != 0
 | 
			
		||||
| 
						 | 
				
			
			@ -547,6 +561,9 @@ first and then run 'git rebase --continue' again."
 | 
			
		|||
	-i)
 | 
			
		||||
		# yeah, we know
 | 
			
		||||
		;;
 | 
			
		||||
	--root)
 | 
			
		||||
		REBASE_ROOT=t
 | 
			
		||||
		;;
 | 
			
		||||
	--onto)
 | 
			
		||||
		shift
 | 
			
		||||
		ONTO=$(git rev-parse --verify "$1") ||
 | 
			
		||||
| 
						 | 
				
			
			@ -554,27 +571,36 @@ first and then run 'git rebase --continue' again."
 | 
			
		|||
		;;
 | 
			
		||||
	--)
 | 
			
		||||
		shift
 | 
			
		||||
		run_pre_rebase_hook ${1+"$@"}
 | 
			
		||||
		test $# -eq 1 -o $# -eq 2 || usage
 | 
			
		||||
		test ! -z "$REBASE_ROOT" -o $# -eq 1 -o $# -eq 2 || usage
 | 
			
		||||
		test -d "$DOTEST" &&
 | 
			
		||||
			die "Interactive rebase already started"
 | 
			
		||||
 | 
			
		||||
		git var GIT_COMMITTER_IDENT >/dev/null ||
 | 
			
		||||
			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
 | 
			
		||||
 | 
			
		||||
		require_clean_work_tree
 | 
			
		||||
 | 
			
		||||
		UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
 | 
			
		||||
		test -z "$ONTO" && ONTO=$UPSTREAM
 | 
			
		||||
 | 
			
		||||
		if test ! -z "$2"
 | 
			
		||||
		if test ! -z "$1"
 | 
			
		||||
		then
 | 
			
		||||
			output git show-ref --verify --quiet "refs/heads/$2" ||
 | 
			
		||||
				die "Invalid branchname: $2"
 | 
			
		||||
			output git checkout "$2" ||
 | 
			
		||||
				die "Could not checkout $2"
 | 
			
		||||
			output git show-ref --verify --quiet "refs/heads/$1" ||
 | 
			
		||||
				die "Invalid branchname: $1"
 | 
			
		||||
			output git checkout "$1" ||
 | 
			
		||||
				die "Could not checkout $1"
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		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
 | 
			
		||||
			# unrelated side branches are left alone. (Think "X"
 | 
			
		||||
			# in the man page's example.)
 | 
			
		||||
			mkdir "$REWRITTEN" &&
 | 
			
		||||
			for c in $(git merge-base --all $HEAD $UPSTREAM)
 | 
			
		||||
			do
 | 
			
		||||
				echo $ONTO > "$REWRITTEN"/$c ||
 | 
			
		||||
			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"
 | 
			
		||||
			done
 | 
			
		||||
			fi
 | 
			
		||||
			# No cherry-pick because our first pass is to determine
 | 
			
		||||
			# parents to rewrite and skipping dropped commits would
 | 
			
		||||
			# prematurely end our probe
 | 
			
		||||
| 
						 | 
				
			
			@ -613,12 +646,21 @@ first and then run 'git rebase --continue' again."
 | 
			
		|||
			MERGES_OPTION="--no-merges --cherry-pick"
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM)
 | 
			
		||||
		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 \
 | 
			
		||||
			$UPSTREAM...$HEAD | \
 | 
			
		||||
			$REVISIONS | \
 | 
			
		||||
			sed -n "s/^>//p" | while read shortsha1 rest
 | 
			
		||||
		do
 | 
			
		||||
			if test t != "$PRESERVE_MERGES"
 | 
			
		||||
| 
						 | 
				
			
			@ -626,14 +668,19 @@ first and then run 'git rebase --continue' again."
 | 
			
		|||
				echo "pick $shortsha1 $rest" >> "$TODO"
 | 
			
		||||
			else
 | 
			
		||||
				sha1=$(git rev-parse $shortsha1)
 | 
			
		||||
				preserve=t
 | 
			
		||||
				for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
 | 
			
		||||
				do
 | 
			
		||||
					if test -f "$REWRITTEN"/$p -a \( $p != $UPSTREAM -o $sha1 = $first_after_upstream \)
 | 
			
		||||
					then
 | 
			
		||||
						preserve=f
 | 
			
		||||
					fi
 | 
			
		||||
				done
 | 
			
		||||
				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 != $UPSTREAM -o $sha1 = $first_after_upstream \)
 | 
			
		||||
						then
 | 
			
		||||
							preserve=f
 | 
			
		||||
						fi
 | 
			
		||||
					done
 | 
			
		||||
				else
 | 
			
		||||
					preserve=f
 | 
			
		||||
				fi
 | 
			
		||||
				if test f = "$preserve"
 | 
			
		||||
				then
 | 
			
		||||
					touch "$REWRITTEN"/$sha1
 | 
			
		||||
| 
						 | 
				
			
			@ -647,11 +694,11 @@ first and then run 'git rebase --continue' again."
 | 
			
		|||
		then
 | 
			
		||||
			mkdir "$DROPPED"
 | 
			
		||||
			# 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
 | 
			
		||||
			# Now all commits and note which ones are missing in
 | 
			
		||||
			# not-cherry-picks and hence being dropped
 | 
			
		||||
			git rev-list $UPSTREAM..$HEAD |
 | 
			
		||||
			git rev-list $REVISIONS |
 | 
			
		||||
			while read rev
 | 
			
		||||
			do
 | 
			
		||||
				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,
 | 
			
		||||
					# 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' ' -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)
 | 
			
		||||
					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"
 | 
			
		||||
		cat >> "$TODO" << EOF
 | 
			
		||||
 | 
			
		||||
# Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
 | 
			
		||||
# Rebase $SHORTREVISIONS onto $SHORTONTO
 | 
			
		||||
#
 | 
			
		||||
# Commands:
 | 
			
		||||
#  p, pick = use commit
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
# 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
 | 
			
		||||
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>
 | 
			
		||||
| 
						 | 
				
			
			@ -47,6 +47,7 @@ dotest="$GIT_DIR"/rebase-merge
 | 
			
		|||
prec=4
 | 
			
		||||
verbose=
 | 
			
		||||
git_am_opt=
 | 
			
		||||
rebase_root=
 | 
			
		||||
 | 
			
		||||
continue_merge () {
 | 
			
		||||
	test -n "$prev_head" || die "prev_head must be defined"
 | 
			
		||||
| 
						 | 
				
			
			@ -297,6 +298,9 @@ do
 | 
			
		|||
	-C*)
 | 
			
		||||
		git_am_opt="$git_am_opt $1"
 | 
			
		||||
		;;
 | 
			
		||||
	--root)
 | 
			
		||||
		rebase_root=t
 | 
			
		||||
		;;
 | 
			
		||||
	-*)
 | 
			
		||||
		usage
 | 
			
		||||
		;;
 | 
			
		||||
| 
						 | 
				
			
			@ -344,17 +348,29 @@ case "$diff" in
 | 
			
		|||
	;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
# The upstream head must be given.  Make sure it is valid.
 | 
			
		||||
upstream_name="$1"
 | 
			
		||||
upstream=`git rev-parse --verify "${upstream_name}^0"` ||
 | 
			
		||||
    die "invalid upstream $upstream_name"
 | 
			
		||||
if test -z "$rebase_root"
 | 
			
		||||
then
 | 
			
		||||
	# The upstream head must be given.  Make sure it is valid.
 | 
			
		||||
	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.
 | 
			
		||||
onto_name=${newbase-"$upstream_name"}
 | 
			
		||||
onto=$(git rev-parse --verify "${onto_name}^0") || exit
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
# $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"
 | 
			
		||||
switch_to=
 | 
			
		||||
case "$#" in
 | 
			
		||||
2)
 | 
			
		||||
1)
 | 
			
		||||
	# Is it "rebase other $branchname" or "rebase other $commit"?
 | 
			
		||||
	branch_name="$2"
 | 
			
		||||
	switch_to="$2"
 | 
			
		||||
	branch_name="$1"
 | 
			
		||||
	switch_to="$1"
 | 
			
		||||
 | 
			
		||||
	if git show-ref --verify --quiet -- "refs/heads/$2" &&
 | 
			
		||||
	   branch=$(git rev-parse -q --verify "refs/heads/$2")
 | 
			
		||||
	if git show-ref --verify --quiet -- "refs/heads/$1" &&
 | 
			
		||||
	   branch=$(git rev-parse -q --verify "refs/heads/$1")
 | 
			
		||||
	then
 | 
			
		||||
		head_name="refs/heads/$2"
 | 
			
		||||
	elif branch=$(git rev-parse -q --verify "$2")
 | 
			
		||||
		head_name="refs/heads/$1"
 | 
			
		||||
	elif branch=$(git rev-parse -q --verify "$1")
 | 
			
		||||
	then
 | 
			
		||||
		head_name="detached HEAD"
 | 
			
		||||
	else
 | 
			
		||||
| 
						 | 
				
			
			@ -393,7 +409,8 @@ case "$#" in
 | 
			
		|||
esac
 | 
			
		||||
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,
 | 
			
		||||
# but this should be done only when upstream and onto are the same.
 | 
			
		||||
| 
						 | 
				
			
			@ -429,10 +446,17 @@ then
 | 
			
		|||
	exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -n "$rebase_root"
 | 
			
		||||
then
 | 
			
		||||
	revisions="$onto..$orig_head"
 | 
			
		||||
else
 | 
			
		||||
	revisions="$upstream..$orig_head"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -z "$do_merge"
 | 
			
		||||
then
 | 
			
		||||
	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" &&
 | 
			
		||||
	move_to_original_branch
 | 
			
		||||
	ret=$?
 | 
			
		||||
| 
						 | 
				
			
			@ -455,7 +479,7 @@ echo "$orig_head" > "$dotest/orig-head"
 | 
			
		|||
echo "$head_name" > "$dotest/head-name"
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
	msgnum=$(($msgnum + 1))
 | 
			
		||||
	echo "$cmt" > "$dotest/cmt.$msgnum"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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