diff --git a/git-rebase.sh b/git-rebase.sh
index b121f4537ccb173d9f289734f1fe2e89b28d7562..cbb0ea90ed410d5af68ce814b7fd93a90829f3ee 100755 (executable)
--- a/git-rebase.sh
+++ b/git-rebase.sh
# Copyright (c) 2005 Junio C Hamano.
#
# Copyright (c) 2005 Junio C Hamano.
#
-USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--onto <newbase>] [<upstream>|--root] [<branch>] [--quiet | -q]'
+USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--no-ff] [--onto <newbase>] (<upstream>|--root) [<branch>] [--quiet | -q]'
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>
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>
require_work_tree
cd_to_toplevel
require_work_tree
cd_to_toplevel
+LF='
+'
OK_TO_SKIP_PRE_REBASE=
RESOLVEMSG="
When you have resolved this problem run \"git rebase --continue\".
OK_TO_SKIP_PRE_REBASE=
RESOLVEMSG="
When you have resolved this problem run \"git rebase --continue\".
"
unset newbase
strategy=recursive
"
unset newbase
strategy=recursive
+strategy_opts=
do_merge=
dotest="$GIT_DIR"/rebase-merge
prec=4
verbose=
do_merge=
dotest="$GIT_DIR"/rebase-merge
prec=4
verbose=
-diffstat=$(git config --bool rebase.stat)
+diffstat=
+test "$(git config --bool rebase.stat)" = true && diffstat=t
git_am_opt=
rebase_root=
force_rebase=
git_am_opt=
rebase_root=
force_rebase=
+allow_rerere_autoupdate=
continue_merge () {
test -n "$prev_head" || die "prev_head must be defined"
continue_merge () {
test -n "$prev_head" || die "prev_head must be defined"
then
printf "Committed: %0${prec}d " $msgnum
fi
then
printf "Committed: %0${prec}d " $msgnum
fi
+ echo "$cmt $(git rev-parse HEAD^0)" >> "$dotest/rewritten"
else
if test -z "$GIT_QUIET"
then
printf "Already applied: %0${prec}d " $msgnum
fi
fi
else
if test -z "$GIT_QUIET"
then
printf "Already applied: %0${prec}d " $msgnum
fi
fi
- if test -z "$GIT_QUIET"
- then
- git rev-list --pretty=oneline -1 "$cmt" | sed -e 's/^[^ ]* //'
- fi
+ test -z "$GIT_QUIET" &&
+ GIT_PAGER='' git log --format=%s -1 "$cmt"
prev_head=`git rev-parse HEAD^0`
# save the resulting commit so we can read-tree on it later
prev_head=`git rev-parse HEAD^0`
# save the resulting commit so we can read-tree on it later
export GITHEAD_$cmt GITHEAD_$hd
if test -n "$GIT_QUIET"
then
export GITHEAD_$cmt GITHEAD_$hd
if test -n "$GIT_QUIET"
then
- export GIT_MERGE_VERBOSITY=1
+ GIT_MERGE_VERBOSITY=1 && export GIT_MERGE_VERBOSITY
fi
fi
- git-merge-$strategy "$cmt^" -- "$hd" "$cmt"
+ eval 'git-merge-$strategy' $strategy_opts '"$cmt^" -- "$hd" "$cmt"'
rv=$?
case "$rv" in
0)
rv=$?
case "$rv" in
0)
return
;;
1)
return
;;
1)
- git rerere
+ git rerere $allow_rerere_autoupdate
die "$RESOLVEMSG"
;;
2)
die "$RESOLVEMSG"
;;
2)
finish_rb_merge () {
move_to_original_branch
finish_rb_merge () {
move_to_original_branch
+ git notes copy --for-rewrite=rebase < "$dotest"/rewritten
+ if test -x "$GIT_DIR"/hooks/post-rewrite &&
+ test -s "$dotest"/rewritten; then
+ "$GIT_DIR"/hooks/post-rewrite rebase < "$dotest"/rewritten
+ fi
rm -r "$dotest"
say All done.
}
rm -r "$dotest"
say All done.
}
is_interactive "$@" && exec git-rebase--interactive "$@"
is_interactive "$@" && exec git-rebase--interactive "$@"
-if test $# -eq 0
-then
- test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply || usage
- test -d "$dotest" -o -f "$GIT_DIR"/rebase-apply/rebasing &&
- die 'A rebase is in progress, try --continue, --skip or --abort.'
- die "No arguments given and $GIT_DIR/rebase-apply already exists."
-fi
-
while test $# != 0
do
case "$1" in
--no-verify)
OK_TO_SKIP_PRE_REBASE=yes
;;
while test $# != 0
do
case "$1" in
--no-verify)
OK_TO_SKIP_PRE_REBASE=yes
;;
+ --verify)
+ OK_TO_SKIP_PRE_REBASE=
+ ;;
--continue)
test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply ||
die "No rebase in progress?"
--continue)
test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply ||
die "No rebase in progress?"
+ 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"
git diff-files --quiet --ignore-submodules || {
echo "You must edit all merge conflicts and then"
echo "mark them as resolved using git add"
die "No rebase in progress?"
git rerere clear
die "No rebase in progress?"
git rerere clear
- if test -d "$dotest"
- then
- GIT_QUIET=$(cat "$dotest/quiet")
- move_to_original_branch
- else
- dotest="$GIT_DIR"/rebase-apply
- GIT_QUIET=$(cat "$dotest/quiet")
- move_to_original_branch
- fi
+
+ test -d "$dotest" || dotest="$GIT_DIR"/rebase-apply
+
+ head_name="$(cat "$dotest"/head-name)" &&
+ case "$head_name" in
+ refs/*)
+ git symbolic-ref HEAD $head_name ||
+ die "Could not move back to $head_name"
+ ;;
+ esac
git reset --hard $(cat "$dotest/orig-head")
rm -r "$dotest"
exit
git reset --hard $(cat "$dotest/orig-head")
rm -r "$dotest"
exit
-M|-m|--m|--me|--mer|--merg|--merge)
do_merge=t
;;
-M|-m|--m|--me|--mer|--merg|--merge)
do_merge=t
;;
+ -X*|--strategy-option*)
+ case "$#,$1" in
+ 1,-X|1,--strategy-option)
+ usage ;;
+ *,-X|*,--strategy-option)
+ newopt="$2"
+ shift ;;
+ *,--strategy-option=*)
+ newopt="$(expr " $1" : ' --strategy-option=\(.*\)')" ;;
+ *,-X*)
+ newopt="$(expr " $1" : ' -X\(.*\)')" ;;
+ 1,*)
+ usage ;;
+ esac
+ strategy_opts="$strategy_opts $(git rev-parse --sq-quote "--$newopt")"
+ do_merge=t
+ ;;
-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
--strateg=*|--strategy=*|\
-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
--strateg=*|--strategy=*|\
-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
--root)
rebase_root=t
;;
--root)
rebase_root=t
;;
- -f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase)
+ -f|--f|--fo|--for|--forc|--force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase|--no-ff)
force_rebase=t
;;
force_rebase=t
;;
+ --rerere-autoupdate|--no-rerere-autoupdate)
+ allow_rerere_autoupdate="$1"
+ ;;
-*)
usage
;;
-*)
usage
;;
done
test $# -gt 2 && usage
done
test $# -gt 2 && usage
+if test $# -eq 0 && test -z "$rebase_root"
+then
+ test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply || usage
+ test -d "$dotest" -o -f "$GIT_DIR"/rebase-apply/rebasing &&
+ die 'A rebase is in progress, try --continue, --skip or --abort.'
+fi
+
# Make sure we do not have $GIT_DIR/rebase-apply
if test -z "$do_merge"
then
# Make sure we do not have $GIT_DIR/rebase-apply
if test -z "$do_merge"
then
fi
fi
fi
fi
-# The tree must be really really clean.
-if ! git update-index --ignore-submodules --refresh > /dev/null; then
- echo >&2 "cannot rebase: you have unstaged changes"
- git diff-files --name-status -r --ignore-submodules -- >&2
- exit 1
-fi
-diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --)
-case "$diff" in
-?*) echo >&2 "cannot rebase: your index contains uncommitted changes"
- echo >&2 "$diff"
- exit 1
- ;;
-esac
+require_clean_work_tree "rebase" "Please commit or stash them."
if test -z "$rebase_root"
then
if test -z "$rebase_root"
then
# Make sure the branch to rebase onto is valid.
onto_name=${newbase-"$upstream_name"}
# Make sure the branch to rebase onto is valid.
onto_name=${newbase-"$upstream_name"}
-onto=$(git rev-parse --verify "${onto_name}^0") || exit
+case "$onto_name" in
+*...*)
+ if left=${onto_name%...*} right=${onto_name#*...} &&
+ onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})
+ then
+ case "$onto" in
+ ?*"$LF"?*)
+ die "$onto_name: there are more than one merge bases"
+ ;;
+ '')
+ die "$onto_name: there is no merge base"
+ ;;
+ esac
+ else
+ die "$onto_name: there is no merge base"
+ fi
+ ;;
+*)
+ onto=$(git rev-parse --verify "${onto_name}^0") || exit
+ ;;
+esac
# If a hook exists, give it a chance to interrupt
run_pre_rebase_hook "$upstream_arg" "$@"
# If a hook exists, give it a chance to interrupt
run_pre_rebase_hook "$upstream_arg" "$@"
then
head_name="detached HEAD"
else
then
head_name="detached HEAD"
else
+ echo >&2 "fatal: no such branch: $1"
usage
fi
;;
usage
fi
;;
if test -z "$force_rebase"
then
# Lazily switch to the target branch if needed...
if test -z "$force_rebase"
then
# Lazily switch to the target branch if needed...
- test -z "$switch_to" || git checkout "$switch_to"
+ test -z "$switch_to" || git checkout "$switch_to" --
say "Current branch $branch_name is up to date."
exit 0
else
say "Current branch $branch_name is up to date."
exit 0
else
if test -z "$do_merge"
then
git format-patch -k --stdout --full-index --ignore-if-in-upstream \
if test -z "$do_merge"
then
git format-patch -k --stdout --full-index --ignore-if-in-upstream \
- $root_flag "$revisions" |
+ --src-prefix=a/ --dst-prefix=b/ \
+ --no-renames $root_flag "$revisions" |
git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" &&
move_to_original_branch
ret=$?
git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" &&
move_to_original_branch
ret=$?