2005-06-25 17:23:43 +08:00
|
|
|
#!/bin/sh
|
|
|
|
#
|
|
|
|
# Copyright (c) 2005 Junio C Hamano.
|
|
|
|
#
|
|
|
|
|
2007-01-13 04:52:03 +08:00
|
|
|
SUBDIRECTORY_OK=Yes
|
2011-03-01 09:59:26 +08:00
|
|
|
OPTIONS_KEEPDASHDASH=
|
2014-02-10 09:03:36 +08:00
|
|
|
OPTIONS_STUCKLONG=t
|
2011-03-01 09:59:26 +08:00
|
|
|
OPTIONS_SPEC="\
|
2012-06-12 16:05:12 +08:00
|
|
|
git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]
|
2012-07-16 12:38:41 +08:00
|
|
|
git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]
|
2012-09-18 09:28:09 +08:00
|
|
|
git-rebase --continue | --abort | --skip | --edit-todo
|
2011-03-01 09:59:26 +08:00
|
|
|
--
|
|
|
|
Available options are
|
|
|
|
v,verbose! display a diffstat of what changed upstream
|
|
|
|
q,quiet! be quiet. implies --no-stat
|
2013-05-12 19:56:41 +08:00
|
|
|
autostash! automatically stash/stash pop before and after
|
2013-12-10 07:16:16 +08:00
|
|
|
fork-point use 'merge-base --fork-point' to refine upstream
|
2011-03-01 09:59:26 +08:00
|
|
|
onto=! rebase onto given branch instead of upstream
|
|
|
|
p,preserve-merges! try to recreate merges instead of ignoring them
|
|
|
|
s,strategy=! use the given merge strategy
|
|
|
|
no-ff! cherry-pick all commits, even if unchanged
|
|
|
|
m,merge! use merging strategies to rebase
|
|
|
|
i,interactive! let the user edit the list of commits to rebase
|
2012-06-12 16:05:12 +08:00
|
|
|
x,exec=! add exec lines after each commit of the editable list
|
2012-04-20 22:36:17 +08:00
|
|
|
k,keep-empty preserve empty commits during rebase
|
2011-03-01 09:59:26 +08:00
|
|
|
f,force-rebase! force rebase even if branch is up to date
|
|
|
|
X,strategy-option=! pass the argument through to the merge strategy
|
|
|
|
stat! display a diffstat of what changed upstream
|
|
|
|
n,no-stat! do not show diffstat of what changed upstream
|
|
|
|
verify allow pre-rebase hook to run
|
|
|
|
rerere-autoupdate allow rerere to update index with resolved conflicts
|
|
|
|
root! rebase all reachable commits up to the root(s)
|
|
|
|
autosquash move commits that begin with squash!/fixup! under -i
|
|
|
|
committer-date-is-author-date! passed to 'git am'
|
|
|
|
ignore-date! passed to 'git am'
|
|
|
|
whitespace=! passed to 'git apply'
|
|
|
|
ignore-whitespace! passed to 'git apply'
|
|
|
|
C=! passed to 'git apply'
|
2014-02-10 09:03:37 +08:00
|
|
|
S,gpg-sign? GPG-sign commits
|
2011-03-01 09:59:26 +08:00
|
|
|
Actions:
|
2011-07-14 11:47:06 +08:00
|
|
|
continue! continue
|
|
|
|
abort! abort and check out the original branch
|
|
|
|
skip! skip current patch and continue
|
2012-09-18 09:28:09 +08:00
|
|
|
edit-todo! edit the todo list during an interactive rebase
|
2011-03-01 09:59:26 +08:00
|
|
|
"
|
2005-11-24 16:12:11 +08:00
|
|
|
. git-sh-setup
|
2012-07-25 22:53:08 +08:00
|
|
|
. git-sh-i18n
|
2006-12-28 15:34:48 +08:00
|
|
|
set_reflog_action rebase
|
pull,rebase: handle GIT_WORK_TREE better
You can't currently run git-pull or git-rebase from outside
of the work tree, even with GIT_WORK_TREE set, due to an
overeager require_work_tree function. Commit e2eb527
documents this problem and provides the infrastructure for a
fix, but left it to later commits to audit and update
individual scripts.
Changing these scripts to use require_work_tree_exists is
easy to verify. We immediately call cd_to_toplevel, anyway.
Therefore no matter which function we use, the state
afterwards is one of:
1. We have a work tree, and we are at the top level.
2. We don't have a work tree, and we have died.
The only catch is that we must also make sure no code that
ran before the cd_to_toplevel assumed that we were already
in the working tree.
In this case, we will only have included shell libraries and
called set_reflog_action, neither of which care about the
current working directory at all.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-13 23:59:24 +08:00
|
|
|
require_work_tree_exists
|
2007-01-13 04:52:03 +08:00
|
|
|
cd_to_toplevel
|
2005-08-08 06:51:09 +08:00
|
|
|
|
2009-11-20 19:02:44 +08:00
|
|
|
LF='
|
|
|
|
'
|
2011-02-07 02:43:37 +08:00
|
|
|
ok_to_skip_pre_rebase=
|
|
|
|
resolvemsg="
|
2012-07-25 22:53:08 +08:00
|
|
|
$(gettext 'When you have resolved this problem, run "git rebase --continue".
|
|
|
|
If you prefer to skip this patch, run "git rebase --skip" instead.
|
|
|
|
To check out the original branch and stop rebasing, run "git rebase --abort".')
|
2006-05-14 11:34:08 +08:00
|
|
|
"
|
2011-02-07 02:43:37 +08:00
|
|
|
unset onto
|
2014-07-17 03:23:49 +08:00
|
|
|
unset restrict_revision
|
2012-06-12 16:05:12 +08:00
|
|
|
cmd=
|
2011-02-07 02:43:38 +08:00
|
|
|
strategy=
|
2010-07-29 06:04:29 +08:00
|
|
|
strategy_opts=
|
2006-06-21 18:04:41 +08:00
|
|
|
do_merge=
|
2011-02-07 02:43:30 +08:00
|
|
|
merge_dir="$GIT_DIR"/rebase-merge
|
|
|
|
apply_dir="$GIT_DIR"/rebase-apply
|
2006-10-04 00:29:31 +08:00
|
|
|
verbose=
|
2010-11-10 04:59:00 +08:00
|
|
|
diffstat=
|
|
|
|
test "$(git config --bool rebase.stat)" = true && diffstat=t
|
2013-05-12 19:56:41 +08:00
|
|
|
autostash="$(git config --bool rebase.autostash || echo false)"
|
2013-12-10 07:16:16 +08:00
|
|
|
fork_point=auto
|
2007-02-08 21:57:08 +08:00
|
|
|
git_am_opt=
|
2009-01-06 01:35:16 +08:00
|
|
|
rebase_root=
|
2009-02-14 06:48:01 +08:00
|
|
|
force_rebase=
|
2009-12-04 16:20:48 +08:00
|
|
|
allow_rerere_autoupdate=
|
2011-02-07 02:43:34 +08:00
|
|
|
# Non-empty if a rebase was in progress when 'git rebase' was invoked
|
|
|
|
in_progress=
|
|
|
|
# One of {am, merge, interactive}
|
|
|
|
type=
|
|
|
|
# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge}
|
|
|
|
state_dir=
|
2011-02-07 02:43:35 +08:00
|
|
|
# One of {'', continue, skip, abort}, as parsed from command line
|
|
|
|
action=
|
2011-02-07 02:43:39 +08:00
|
|
|
preserve_merges=
|
|
|
|
autosquash=
|
2012-04-20 22:36:17 +08:00
|
|
|
keep_empty=
|
2011-02-07 02:43:39 +08:00
|
|
|
test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
|
2014-02-10 09:03:37 +08:00
|
|
|
gpg_sign_opt=
|
2006-06-21 18:04:41 +08:00
|
|
|
|
2011-02-07 02:43:47 +08:00
|
|
|
read_basic_state () {
|
2013-06-14 00:06:11 +08:00
|
|
|
test -f "$state_dir/head-name" &&
|
|
|
|
test -f "$state_dir/onto" &&
|
rebase: refactor reading of state
The code reading the state saved in $merge_dir or $rebase_dir is
currently spread out in many places, making it harder to read and to
introduce additional state. Extract this code into one method that
reads the state. Only extract the code associated with the state that
is written when the rebase is initiated. Leave the state that changes
for each commmit, at least for now.
Currently, when resuming a merge-based rebase using --continue or
--skip, move_to_original_branch (via finish_rb_merge) will be called
without head_name and orig_head set. These variables are then lazily
read in move_to_original_branch if head_name is not set (together with
onto, which is unnecessarily read again). Change this by always
eagerly reading the state, for both am-based and merge-based rebase,
in the --continue and --skip cases. Note that this does not change the
behavior for am-based rebase, which read the state eagerly even before
this commit.
Reading the state eagerly means that part of the state will sometimes
be read unnecessarily. One example is when the rebase is continued,
but stops again at another merge conflict. Another example is when the
rebase is aborted. However, since both of these cases involve user
interaction, the delay is hopefully not noticeable. The
call_merge/continue_merge loop is not affected.
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Martin von Zweigbergk <martin.von.zweigbergk@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-02-07 02:43:31 +08:00
|
|
|
head_name=$(cat "$state_dir"/head-name) &&
|
|
|
|
onto=$(cat "$state_dir"/onto) &&
|
2011-02-07 02:43:53 +08:00
|
|
|
# We always write to orig-head, but interactive rebase used to write to
|
|
|
|
# head. Fall back to reading from head to cover for the case that the
|
|
|
|
# user upgraded git with an ongoing interactive rebase.
|
|
|
|
if test -f "$state_dir"/orig-head
|
2011-02-07 02:43:52 +08:00
|
|
|
then
|
|
|
|
orig_head=$(cat "$state_dir"/orig-head)
|
2011-02-07 02:43:53 +08:00
|
|
|
else
|
|
|
|
orig_head=$(cat "$state_dir"/head)
|
2011-02-07 02:43:52 +08:00
|
|
|
fi &&
|
2011-02-07 02:43:54 +08:00
|
|
|
GIT_QUIET=$(cat "$state_dir"/quiet) &&
|
|
|
|
test -f "$state_dir"/verbose && verbose=t
|
2011-02-07 02:43:55 +08:00
|
|
|
test -f "$state_dir"/strategy && strategy="$(cat "$state_dir"/strategy)"
|
|
|
|
test -f "$state_dir"/strategy_opts &&
|
|
|
|
strategy_opts="$(cat "$state_dir"/strategy_opts)"
|
2011-02-07 02:43:56 +08:00
|
|
|
test -f "$state_dir"/allow_rerere_autoupdate &&
|
|
|
|
allow_rerere_autoupdate="$(cat "$state_dir"/allow_rerere_autoupdate)"
|
2014-02-10 09:03:37 +08:00
|
|
|
test -f "$state_dir"/gpg_sign_opt &&
|
|
|
|
gpg_sign_opt="$(cat "$state_dir"/gpg_sign_opt)"
|
rebase: refactor reading of state
The code reading the state saved in $merge_dir or $rebase_dir is
currently spread out in many places, making it harder to read and to
introduce additional state. Extract this code into one method that
reads the state. Only extract the code associated with the state that
is written when the rebase is initiated. Leave the state that changes
for each commmit, at least for now.
Currently, when resuming a merge-based rebase using --continue or
--skip, move_to_original_branch (via finish_rb_merge) will be called
without head_name and orig_head set. These variables are then lazily
read in move_to_original_branch if head_name is not set (together with
onto, which is unnecessarily read again). Change this by always
eagerly reading the state, for both am-based and merge-based rebase,
in the --continue and --skip cases. Note that this does not change the
behavior for am-based rebase, which read the state eagerly even before
this commit.
Reading the state eagerly means that part of the state will sometimes
be read unnecessarily. One example is when the rebase is continued,
but stops again at another merge conflict. Another example is when the
rebase is aborted. However, since both of these cases involve user
interaction, the delay is hopefully not noticeable. The
call_merge/continue_merge loop is not affected.
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Martin von Zweigbergk <martin.von.zweigbergk@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-02-07 02:43:31 +08:00
|
|
|
}
|
|
|
|
|
2011-02-07 02:43:53 +08:00
|
|
|
write_basic_state () {
|
|
|
|
echo "$head_name" > "$state_dir"/head-name &&
|
|
|
|
echo "$onto" > "$state_dir"/onto &&
|
|
|
|
echo "$orig_head" > "$state_dir"/orig-head &&
|
2011-02-07 02:43:54 +08:00
|
|
|
echo "$GIT_QUIET" > "$state_dir"/quiet &&
|
|
|
|
test t = "$verbose" && : > "$state_dir"/verbose
|
2011-02-07 02:43:55 +08:00
|
|
|
test -n "$strategy" && echo "$strategy" > "$state_dir"/strategy
|
|
|
|
test -n "$strategy_opts" && echo "$strategy_opts" > \
|
|
|
|
"$state_dir"/strategy_opts
|
2011-02-07 02:43:56 +08:00
|
|
|
test -n "$allow_rerere_autoupdate" && echo "$allow_rerere_autoupdate" > \
|
|
|
|
"$state_dir"/allow_rerere_autoupdate
|
2014-02-10 09:03:37 +08:00
|
|
|
test -n "$gpg_sign_opt" && echo "$gpg_sign_opt" > "$state_dir"/gpg_sign_opt
|
2011-02-07 02:43:53 +08:00
|
|
|
}
|
|
|
|
|
2011-02-07 02:43:51 +08:00
|
|
|
output () {
|
|
|
|
case "$verbose" in
|
|
|
|
'')
|
|
|
|
output=$("$@" 2>&1 )
|
|
|
|
status=$?
|
|
|
|
test $status != 0 && printf "%s\n" "$output"
|
|
|
|
return $status
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
"$@"
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
2007-11-09 02:19:08 +08:00
|
|
|
move_to_original_branch () {
|
|
|
|
case "$head_name" in
|
|
|
|
refs/*)
|
|
|
|
message="rebase finished: $head_name onto $onto"
|
|
|
|
git update-ref -m "$message" \
|
|
|
|
$head_name $(git rev-parse HEAD) $orig_head &&
|
2011-05-28 04:16:14 +08:00
|
|
|
git symbolic-ref \
|
|
|
|
-m "rebase finished: returning to $head_name" \
|
|
|
|
HEAD $head_name ||
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(gettext "Could not move back to $head_name")"
|
2007-11-09 02:19:08 +08:00
|
|
|
;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
2014-05-20 06:05:20 +08:00
|
|
|
apply_autostash () {
|
2013-05-12 19:56:41 +08:00
|
|
|
if test -f "$state_dir/autostash"
|
|
|
|
then
|
|
|
|
stash_sha1=$(cat "$state_dir/autostash")
|
|
|
|
if git stash apply $stash_sha1 2>&1 >/dev/null
|
|
|
|
then
|
|
|
|
echo "$(gettext 'Applied autostash.')"
|
|
|
|
else
|
2013-06-15 21:13:26 +08:00
|
|
|
git stash store -m "autostash" -q $stash_sha1 ||
|
|
|
|
die "$(eval_gettext "Cannot store \$stash_sha1")"
|
2013-05-12 19:56:41 +08:00
|
|
|
gettext 'Applying autostash resulted in conflicts.
|
|
|
|
Your changes are safe in the stash.
|
2013-07-29 12:24:43 +08:00
|
|
|
You can run "git stash pop" or "git stash drop" at any time.
|
2013-05-12 19:56:41 +08:00
|
|
|
'
|
|
|
|
fi
|
|
|
|
fi
|
2014-05-20 06:05:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
finish_rebase () {
|
|
|
|
apply_autostash &&
|
2013-05-12 19:56:41 +08:00
|
|
|
git gc --auto &&
|
|
|
|
rm -rf "$state_dir"
|
|
|
|
}
|
|
|
|
|
2014-04-11 16:28:18 +08:00
|
|
|
run_specific_rebase () {
|
2008-09-30 04:28:57 +08:00
|
|
|
if [ "$interactive_rebase" = implied ]; then
|
|
|
|
GIT_EDITOR=:
|
|
|
|
export GIT_EDITOR
|
2012-05-24 21:57:26 +08:00
|
|
|
autosquash=
|
2008-09-30 04:28:57 +08:00
|
|
|
fi
|
2011-02-07 02:43:48 +08:00
|
|
|
. git-rebase--$type
|
2013-05-12 19:56:37 +08:00
|
|
|
ret=$?
|
|
|
|
if test $ret -eq 0
|
|
|
|
then
|
2013-05-12 19:56:41 +08:00
|
|
|
finish_rebase
|
2014-05-20 06:05:20 +08:00
|
|
|
elif test $ret -eq 2 # special exit status for rebase -i
|
|
|
|
then
|
|
|
|
apply_autostash &&
|
|
|
|
rm -rf "$state_dir" &&
|
|
|
|
die "Nothing to do"
|
2013-05-12 19:56:37 +08:00
|
|
|
fi
|
|
|
|
exit $ret
|
2007-06-25 08:11:14 +08:00
|
|
|
}
|
|
|
|
|
2008-10-06 13:14:24 +08:00
|
|
|
run_pre_rebase_hook () {
|
2011-02-07 02:43:37 +08:00
|
|
|
if test -z "$ok_to_skip_pre_rebase" &&
|
2014-11-30 16:24:38 +08:00
|
|
|
test -x "$(git rev-parse --git-path hooks/pre-rebase)"
|
2008-10-06 13:14:24 +08:00
|
|
|
then
|
2014-11-30 16:24:38 +08:00
|
|
|
"$(git rev-parse --git-path hooks/pre-rebase)" ${1+"$@"} ||
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(gettext "The pre-rebase hook refused to rebase.")"
|
2008-10-06 13:14:24 +08:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2011-02-07 02:43:30 +08:00
|
|
|
test -f "$apply_dir"/applying &&
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(gettext "It looks like git-am is in progress. Cannot rebase.")"
|
2008-08-17 12:25:43 +08:00
|
|
|
|
2011-02-07 02:43:34 +08:00
|
|
|
if test -d "$apply_dir"
|
|
|
|
then
|
|
|
|
type=am
|
|
|
|
state_dir="$apply_dir"
|
|
|
|
elif test -d "$merge_dir"
|
|
|
|
then
|
|
|
|
if test -f "$merge_dir"/interactive
|
|
|
|
then
|
|
|
|
type=interactive
|
|
|
|
interactive_rebase=explicit
|
|
|
|
else
|
|
|
|
type=merge
|
|
|
|
fi
|
|
|
|
state_dir="$merge_dir"
|
|
|
|
fi
|
|
|
|
test -n "$type" && in_progress=t
|
|
|
|
|
2011-02-07 02:43:36 +08:00
|
|
|
total_argc=$#
|
2007-09-24 04:42:08 +08:00
|
|
|
while test $# != 0
|
2006-02-15 06:42:05 +08:00
|
|
|
do
|
|
|
|
case "$1" in
|
2008-10-06 13:14:29 +08:00
|
|
|
--no-verify)
|
2011-02-07 02:43:37 +08:00
|
|
|
ok_to_skip_pre_rebase=yes
|
2008-10-06 13:14:29 +08:00
|
|
|
;;
|
2010-11-23 04:21:01 +08:00
|
|
|
--verify)
|
2011-02-07 02:43:37 +08:00
|
|
|
ok_to_skip_pre_rebase=
|
2010-11-23 04:21:01 +08:00
|
|
|
;;
|
2012-09-18 09:28:09 +08:00
|
|
|
--continue|--skip|--abort|--edit-todo)
|
2011-03-01 09:59:26 +08:00
|
|
|
test $total_argc -eq 2 || usage
|
2011-02-07 02:43:35 +08:00
|
|
|
action=${1##--}
|
2006-04-26 22:49:38 +08:00
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--onto=*)
|
|
|
|
onto="${1#--onto=}"
|
2006-02-15 06:42:05 +08:00
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--exec=*)
|
|
|
|
cmd="${cmd}exec ${1#--exec=}${LF}"
|
2012-06-12 16:05:12 +08:00
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--interactive)
|
2011-02-07 02:43:39 +08:00
|
|
|
interactive_rebase=explicit
|
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--keep-empty)
|
2012-04-20 22:36:17 +08:00
|
|
|
keep_empty=yes
|
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--preserve-merges)
|
2011-02-07 02:43:39 +08:00
|
|
|
preserve_merges=t
|
|
|
|
test -z "$interactive_rebase" && interactive_rebase=implied
|
|
|
|
;;
|
|
|
|
--autosquash)
|
|
|
|
autosquash=t
|
|
|
|
;;
|
|
|
|
--no-autosquash)
|
|
|
|
autosquash=
|
|
|
|
;;
|
2013-12-10 07:16:16 +08:00
|
|
|
--fork-point)
|
|
|
|
fork_point=t
|
|
|
|
;;
|
|
|
|
--no-fork-point)
|
|
|
|
fork_point=
|
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--merge)
|
2006-06-21 18:04:41 +08:00
|
|
|
do_merge=t
|
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--strategy-option=*)
|
|
|
|
strategy_opts="$strategy_opts $(git rev-parse --sq-quote "--${1#--strategy-option=}")"
|
2010-07-29 06:04:29 +08:00
|
|
|
do_merge=t
|
2011-02-07 02:43:38 +08:00
|
|
|
test -z "$strategy" && strategy=recursive
|
2010-07-29 06:04:29 +08:00
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--strategy=*)
|
|
|
|
strategy="${1#--strategy=}"
|
2006-06-21 18:04:41 +08:00
|
|
|
do_merge=t
|
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--no-stat)
|
2009-03-02 06:11:38 +08:00
|
|
|
diffstat=
|
|
|
|
;;
|
|
|
|
--stat)
|
|
|
|
diffstat=t
|
|
|
|
;;
|
2013-05-12 19:56:41 +08:00
|
|
|
--autostash)
|
|
|
|
autostash=true
|
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--verbose)
|
2006-10-04 00:29:31 +08:00
|
|
|
verbose=t
|
2009-03-02 06:11:38 +08:00
|
|
|
diffstat=t
|
2009-06-17 06:33:01 +08:00
|
|
|
GIT_QUIET=
|
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--quiet)
|
2009-06-17 06:33:01 +08:00
|
|
|
GIT_QUIET=t
|
|
|
|
git_am_opt="$git_am_opt -q"
|
|
|
|
verbose=
|
|
|
|
diffstat=
|
2006-10-04 00:29:31 +08:00
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--whitespace=*)
|
|
|
|
git_am_opt="$git_am_opt --whitespace=${1#--whitespace=}"
|
|
|
|
case "${1#--whitespace=}" in
|
2011-03-01 09:59:26 +08:00
|
|
|
fix|strip)
|
2009-02-14 06:48:01 +08:00
|
|
|
force_rebase=t
|
|
|
|
;;
|
|
|
|
esac
|
2007-09-07 22:20:50 +08:00
|
|
|
;;
|
2009-08-04 19:16:49 +08:00
|
|
|
--ignore-whitespace)
|
|
|
|
git_am_opt="$git_am_opt $1"
|
|
|
|
;;
|
2009-03-19 04:53:49 +08:00
|
|
|
--committer-date-is-author-date|--ignore-date)
|
|
|
|
git_am_opt="$git_am_opt $1"
|
|
|
|
force_rebase=t
|
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
-C*)
|
|
|
|
git_am_opt="$git_am_opt $1"
|
2007-02-08 21:57:08 +08:00
|
|
|
;;
|
2009-01-06 01:35:16 +08:00
|
|
|
--root)
|
|
|
|
rebase_root=t
|
|
|
|
;;
|
2014-02-10 09:03:36 +08:00
|
|
|
--force-rebase|--no-ff)
|
2009-02-14 06:48:01 +08:00
|
|
|
force_rebase=t
|
|
|
|
;;
|
2009-12-04 16:20:48 +08:00
|
|
|
--rerere-autoupdate|--no-rerere-autoupdate)
|
|
|
|
allow_rerere_autoupdate="$1"
|
|
|
|
;;
|
2014-02-10 09:03:37 +08:00
|
|
|
--gpg-sign)
|
|
|
|
gpg_sign_opt=-S
|
|
|
|
;;
|
|
|
|
--gpg-sign=*)
|
|
|
|
gpg_sign_opt="-S${1#--gpg-sign=}"
|
|
|
|
;;
|
2011-03-01 09:59:26 +08:00
|
|
|
--)
|
|
|
|
shift
|
2006-02-15 06:42:05 +08:00
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
2009-02-18 21:44:02 +08:00
|
|
|
test $# -gt 2 && usage
|
2005-12-14 19:11:37 +08:00
|
|
|
|
2012-06-12 16:05:12 +08:00
|
|
|
if test -n "$cmd" &&
|
|
|
|
test "$interactive_rebase" != explicit
|
|
|
|
then
|
2012-07-25 22:53:09 +08:00
|
|
|
die "$(gettext "The --exec option must be used with the --interactive option")"
|
2012-06-12 16:05:12 +08:00
|
|
|
fi
|
|
|
|
|
2011-02-07 02:43:39 +08:00
|
|
|
if test -n "$action"
|
|
|
|
then
|
2012-07-25 22:53:08 +08:00
|
|
|
test -z "$in_progress" && die "$(gettext "No rebase in progress?")"
|
2011-02-07 02:43:52 +08:00
|
|
|
# Only interactive rebase uses detailed reflog messages
|
|
|
|
if test "$type" = interactive && test "$GIT_REFLOG_ACTION" = rebase
|
|
|
|
then
|
|
|
|
GIT_REFLOG_ACTION="rebase -i ($action)"
|
|
|
|
export GIT_REFLOG_ACTION
|
|
|
|
fi
|
2011-02-07 02:43:39 +08:00
|
|
|
fi
|
2011-02-07 02:43:35 +08:00
|
|
|
|
2012-09-18 09:28:09 +08:00
|
|
|
if test "$action" = "edit-todo" && test "$type" != "interactive"
|
|
|
|
then
|
|
|
|
die "$(gettext "The --edit-todo action can only be used during interactive rebase.")"
|
|
|
|
fi
|
|
|
|
|
2011-02-07 02:43:35 +08:00
|
|
|
case "$action" in
|
|
|
|
continue)
|
2011-02-07 02:43:52 +08:00
|
|
|
# Sanity check
|
|
|
|
git rev-parse --verify HEAD >/dev/null ||
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(gettext "Cannot read HEAD")"
|
2011-02-07 02:43:35 +08:00
|
|
|
git update-index --ignore-submodules --refresh &&
|
|
|
|
git diff-files --quiet --ignore-submodules || {
|
2012-07-25 22:53:08 +08:00
|
|
|
echo "$(gettext "You must edit all merge conflicts and then
|
|
|
|
mark them as resolved using git add")"
|
2011-02-07 02:43:35 +08:00
|
|
|
exit 1
|
|
|
|
}
|
2011-02-07 02:43:47 +08:00
|
|
|
read_basic_state
|
|
|
|
run_specific_rebase
|
2011-02-07 02:43:35 +08:00
|
|
|
;;
|
|
|
|
skip)
|
2011-02-07 02:43:51 +08:00
|
|
|
output git reset --hard HEAD || exit $?
|
2011-02-07 02:43:47 +08:00
|
|
|
read_basic_state
|
|
|
|
run_specific_rebase
|
2011-02-07 02:43:35 +08:00
|
|
|
;;
|
|
|
|
abort)
|
|
|
|
git rerere clear
|
2011-02-07 02:43:47 +08:00
|
|
|
read_basic_state
|
2011-02-07 02:43:35 +08:00
|
|
|
case "$head_name" in
|
|
|
|
refs/*)
|
2011-05-28 04:13:02 +08:00
|
|
|
git symbolic-ref -m "rebase: aborting" HEAD $head_name ||
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(eval_gettext "Could not move back to \$head_name")"
|
2011-02-07 02:43:35 +08:00
|
|
|
;;
|
|
|
|
esac
|
2011-02-07 02:43:51 +08:00
|
|
|
output git reset --hard $orig_head
|
2013-05-12 19:56:41 +08:00
|
|
|
finish_rebase
|
2011-02-07 02:43:35 +08:00
|
|
|
exit
|
|
|
|
;;
|
2012-09-18 09:28:09 +08:00
|
|
|
edit-todo)
|
|
|
|
run_specific_rebase
|
|
|
|
;;
|
2011-02-07 02:43:35 +08:00
|
|
|
esac
|
|
|
|
|
2011-02-07 02:43:34 +08:00
|
|
|
# Make sure no rebase is in progress
|
|
|
|
if test -n "$in_progress"
|
2005-11-29 05:00:31 +08:00
|
|
|
then
|
2012-07-25 22:53:08 +08:00
|
|
|
state_dir_base=${state_dir##*/}
|
|
|
|
cmd_live_rebase="git rebase (--continue | --abort | --skip)"
|
|
|
|
cmd_clear_stale_rebase="rm -fr \"$state_dir\""
|
|
|
|
die "
|
|
|
|
$(eval_gettext 'It seems that there is already a $state_dir_base directory, and
|
2012-08-02 01:09:09 +08:00
|
|
|
I wonder if you are in the middle of another rebase. If that is the
|
2011-02-07 02:43:34 +08:00
|
|
|
case, please try
|
2012-07-25 22:53:08 +08:00
|
|
|
$cmd_live_rebase
|
2011-02-07 02:43:34 +08:00
|
|
|
If that is not the case, please
|
2012-07-25 22:53:08 +08:00
|
|
|
$cmd_clear_stale_rebase
|
2008-08-17 12:25:43 +08:00
|
|
|
and run me again. I am stopping in case you still have something
|
2012-07-25 22:53:08 +08:00
|
|
|
valuable there.')"
|
2005-11-29 05:00:31 +08:00
|
|
|
fi
|
|
|
|
|
2012-06-27 05:55:23 +08:00
|
|
|
if test -n "$rebase_root" && test -z "$onto"
|
|
|
|
then
|
|
|
|
test -z "$interactive_rebase" && interactive_rebase=implied
|
|
|
|
fi
|
|
|
|
|
2011-02-07 02:43:39 +08:00
|
|
|
if test -n "$interactive_rebase"
|
|
|
|
then
|
|
|
|
type=interactive
|
|
|
|
state_dir="$merge_dir"
|
|
|
|
elif test -n "$do_merge"
|
|
|
|
then
|
|
|
|
type=merge
|
|
|
|
state_dir="$merge_dir"
|
|
|
|
else
|
|
|
|
type=am
|
|
|
|
state_dir="$apply_dir"
|
|
|
|
fi
|
|
|
|
|
2009-01-06 01:35:16 +08:00
|
|
|
if test -z "$rebase_root"
|
|
|
|
then
|
2011-02-10 09:54:02 +08:00
|
|
|
case "$#" in
|
|
|
|
0)
|
|
|
|
if ! upstream_name=$(git rev-parse --symbolic-full-name \
|
|
|
|
--verify -q @{upstream} 2>/dev/null)
|
|
|
|
then
|
|
|
|
. git-parse-remote
|
|
|
|
error_on_missing_default_upstream "rebase" "rebase" \
|
2012-03-04 12:41:26 +08:00
|
|
|
"against" "git rebase <branch>"
|
2011-02-10 09:54:02 +08:00
|
|
|
fi
|
2013-12-10 07:16:16 +08:00
|
|
|
|
|
|
|
test "$fork_point" = auto && fork_point=t
|
2011-02-10 09:54:02 +08:00
|
|
|
;;
|
|
|
|
*) upstream_name="$1"
|
2014-03-19 19:02:15 +08:00
|
|
|
if test "$upstream_name" = "-"
|
|
|
|
then
|
|
|
|
upstream_name="@{-1}"
|
|
|
|
fi
|
2011-02-10 09:54:02 +08:00
|
|
|
shift
|
|
|
|
;;
|
|
|
|
esac
|
2013-06-14 21:17:52 +08:00
|
|
|
upstream=$(peel_committish "${upstream_name}") ||
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(eval_gettext "invalid upstream \$upstream_name")"
|
2009-01-06 01:35:16 +08:00
|
|
|
upstream_arg="$upstream_name"
|
|
|
|
else
|
2012-06-27 05:55:23 +08:00
|
|
|
if test -z "$onto"
|
|
|
|
then
|
2014-04-23 21:44:00 +08:00
|
|
|
empty_tree=$(git hash-object -t tree /dev/null)
|
|
|
|
onto=$(git commit-tree $empty_tree </dev/null)
|
2012-06-27 05:55:23 +08:00
|
|
|
squash_onto="$onto"
|
|
|
|
fi
|
2009-01-06 01:35:16 +08:00
|
|
|
unset upstream_name
|
|
|
|
unset upstream
|
2012-06-26 22:51:55 +08:00
|
|
|
test $# -gt 1 && usage
|
2011-02-07 02:43:48 +08:00
|
|
|
upstream_arg=--root
|
2009-01-06 01:35:16 +08:00
|
|
|
fi
|
2005-12-15 07:36:35 +08:00
|
|
|
|
2007-03-22 17:54:59 +08:00
|
|
|
# Make sure the branch to rebase onto is valid.
|
2011-02-07 02:43:37 +08:00
|
|
|
onto_name=${onto-"$upstream_name"}
|
2010-01-07 19:05:02 +08:00
|
|
|
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"?*)
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(eval_gettext "\$onto_name: there are more than one merge bases")"
|
2010-01-07 19:05:02 +08:00
|
|
|
;;
|
|
|
|
'')
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(eval_gettext "\$onto_name: there is no merge base")"
|
2010-01-07 19:05:02 +08:00
|
|
|
;;
|
|
|
|
esac
|
|
|
|
else
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(eval_gettext "\$onto_name: there is no merge base")"
|
2010-01-07 19:05:02 +08:00
|
|
|
fi
|
|
|
|
;;
|
|
|
|
*)
|
2013-06-14 21:17:52 +08:00
|
|
|
onto=$(peel_committish "$onto_name") ||
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(eval_gettext "Does not point to a valid commit: \$onto_name")"
|
2010-01-07 19:05:02 +08:00
|
|
|
;;
|
|
|
|
esac
|
2007-03-22 17:54:59 +08:00
|
|
|
|
2008-03-16 04:17:42 +08:00
|
|
|
# If the branch to rebase is given, that is the branch we will rebase
|
|
|
|
# $branch_name -- branch being rebased, or HEAD (already detached)
|
|
|
|
# $orig_head -- commit object name of tip of the branch before rebasing
|
|
|
|
# $head_name -- refs/heads/<that-branch> or "detached HEAD"
|
|
|
|
switch_to=
|
2005-06-25 17:23:43 +08:00
|
|
|
case "$#" in
|
2009-01-06 01:35:16 +08:00
|
|
|
1)
|
2008-03-16 04:17:42 +08:00
|
|
|
# Is it "rebase other $branchname" or "rebase other $commit"?
|
2009-01-06 01:35:16 +08:00
|
|
|
branch_name="$1"
|
|
|
|
switch_to="$1"
|
2008-03-16 04:17:42 +08:00
|
|
|
|
2009-01-06 01:35:16 +08:00
|
|
|
if git show-ref --verify --quiet -- "refs/heads/$1" &&
|
2011-02-07 02:43:46 +08:00
|
|
|
orig_head=$(git rev-parse -q --verify "refs/heads/$1")
|
2008-03-16 04:17:42 +08:00
|
|
|
then
|
2009-01-06 01:35:16 +08:00
|
|
|
head_name="refs/heads/$1"
|
2011-02-07 02:43:46 +08:00
|
|
|
elif orig_head=$(git rev-parse -q --verify "$1")
|
2008-03-16 04:17:42 +08:00
|
|
|
then
|
|
|
|
head_name="detached HEAD"
|
|
|
|
else
|
2012-07-25 22:53:08 +08:00
|
|
|
die "$(eval_gettext "fatal: no such branch: \$branch_name")"
|
2008-03-16 04:17:42 +08:00
|
|
|
fi
|
2006-02-15 06:42:05 +08:00
|
|
|
;;
|
2012-06-26 22:51:55 +08:00
|
|
|
0)
|
2008-03-16 04:17:42 +08:00
|
|
|
# Do not need to switch branches, we are already on it.
|
2014-04-23 21:44:00 +08:00
|
|
|
if branch_name=$(git symbolic-ref -q HEAD)
|
2007-01-21 11:11:29 +08:00
|
|
|
then
|
2008-03-16 04:17:42 +08:00
|
|
|
head_name=$branch_name
|
2014-04-23 21:44:00 +08:00
|
|
|
branch_name=$(expr "z$branch_name" : 'zrefs/heads/\(.*\)')
|
2007-01-21 11:11:29 +08:00
|
|
|
else
|
2008-03-16 04:17:42 +08:00
|
|
|
head_name="detached HEAD"
|
2007-01-21 11:11:29 +08:00
|
|
|
branch_name=HEAD ;# detached
|
|
|
|
fi
|
2013-04-24 06:51:14 +08:00
|
|
|
orig_head=$(git rev-parse --verify HEAD) || exit
|
2006-02-15 06:42:05 +08:00
|
|
|
;;
|
2012-06-26 22:51:55 +08:00
|
|
|
*)
|
|
|
|
die "BUG: unexpected number of arguments left to parse"
|
|
|
|
;;
|
2005-06-25 17:23:43 +08:00
|
|
|
esac
|
|
|
|
|
2013-12-10 07:16:16 +08:00
|
|
|
if test "$fork_point" = t
|
|
|
|
then
|
2014-01-10 03:47:34 +08:00
|
|
|
new_upstream=$(git merge-base --fork-point "$upstream_name" \
|
|
|
|
"${switch_to:-HEAD}")
|
2013-12-10 07:16:16 +08:00
|
|
|
if test -n "$new_upstream"
|
|
|
|
then
|
2014-07-17 03:23:49 +08:00
|
|
|
restrict_revision=$new_upstream
|
2013-12-10 07:16:16 +08:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2013-05-12 19:56:41 +08:00
|
|
|
if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null
|
|
|
|
then
|
|
|
|
stash_sha1=$(git stash create "autostash") ||
|
|
|
|
die "$(gettext 'Cannot autostash')"
|
|
|
|
|
|
|
|
mkdir -p "$state_dir" &&
|
|
|
|
echo $stash_sha1 >"$state_dir/autostash" &&
|
|
|
|
stash_abbrev=$(git rev-parse --short $stash_sha1) &&
|
|
|
|
echo "$(eval_gettext 'Created autostash: $stash_abbrev')" &&
|
|
|
|
git reset --hard
|
|
|
|
fi
|
|
|
|
|
2012-07-25 22:53:08 +08:00
|
|
|
require_clean_work_tree "rebase" "$(gettext "Please commit or stash them.")"
|
2011-02-07 02:43:41 +08:00
|
|
|
|
2011-02-07 02:43:46 +08:00
|
|
|
# Now we are rebasing commits $upstream..$orig_head (or with --root,
|
|
|
|
# everything leading up to $orig_head) on top of $onto
|
2006-02-15 06:42:05 +08:00
|
|
|
|
2007-07-05 04:09:10 +08:00
|
|
|
# Check if we are already based on $onto with linear history,
|
2011-02-07 02:43:44 +08:00
|
|
|
# but this should be done only when upstream and onto are the same
|
|
|
|
# and if this is not an interactive rebase.
|
2011-02-07 02:43:46 +08:00
|
|
|
mb=$(git merge-base "$onto" "$orig_head")
|
2011-02-07 02:43:44 +08:00
|
|
|
if test "$type" != interactive && test "$upstream" = "$onto" &&
|
2014-07-17 03:23:49 +08:00
|
|
|
test "$mb" = "$onto" && test -z "$restrict_revision" &&
|
2007-07-05 04:09:10 +08:00
|
|
|
# linear history?
|
2011-02-07 02:43:46 +08:00
|
|
|
! (git rev-list --parents "$onto".."$orig_head" | sane_grep " .* ") > /dev/null
|
2005-11-29 05:00:31 +08:00
|
|
|
then
|
2009-02-14 06:48:01 +08:00
|
|
|
if test -z "$force_rebase"
|
|
|
|
then
|
|
|
|
# Lazily switch to the target branch if needed...
|
2013-06-16 16:45:12 +08:00
|
|
|
test -z "$switch_to" ||
|
|
|
|
GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to" \
|
rebase: silence "git checkout" for noop rebase
When the branch to be rebased is already up to date, we
"git checkout" the branch, print an "up to date" message,
and end the rebase early. However, our checkout may print
"Switched to branch 'foo'" or "Already on 'foo'", even if
the user has asked for "--quiet".
We should avoid printing these messages at all, "--quiet" or
no. Since the rebase is a noop, this checkout can be seen as
optimizing out these other two checkout operations (that
happen in a real rebase):
1. Moving to the detached HEAD to start the rebase; we
always feed "-q" to checkout there, and instead rely on
our own custom message (which respects --quiet).
2. Finishing a rebase, where we move to the final branch.
Here we actually use update-ref rather than
git-checkout, and produce no messages.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-04-28 13:17:37 +08:00
|
|
|
git checkout -q "$switch_to" --
|
2012-07-25 22:53:08 +08:00
|
|
|
say "$(eval_gettext "Current branch \$branch_name is up to date.")"
|
2013-06-14 00:06:13 +08:00
|
|
|
finish_rebase
|
2009-02-14 06:48:01 +08:00
|
|
|
exit 0
|
|
|
|
else
|
2012-07-25 22:53:08 +08:00
|
|
|
say "$(eval_gettext "Current branch \$branch_name is up to date, rebase forced.")"
|
2009-02-14 06:48:01 +08:00
|
|
|
fi
|
2005-11-29 05:00:31 +08:00
|
|
|
fi
|
|
|
|
|
2011-02-07 02:43:41 +08:00
|
|
|
# If a hook exists, give it a chance to interrupt
|
|
|
|
run_pre_rebase_hook "$upstream_arg" "$@"
|
|
|
|
|
2009-03-02 06:11:38 +08:00
|
|
|
if test -n "$diffstat"
|
|
|
|
then
|
|
|
|
if test -n "$verbose"
|
|
|
|
then
|
2012-07-25 22:53:08 +08:00
|
|
|
echo "$(eval_gettext "Changes from \$mb to \$onto:")"
|
2009-03-02 06:11:38 +08:00
|
|
|
fi
|
|
|
|
# We want color (if set), but no pager
|
|
|
|
GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
|
|
|
|
fi
|
|
|
|
|
2011-02-07 02:43:47 +08:00
|
|
|
test "$type" = interactive && run_specific_rebase
|
2011-02-07 02:43:45 +08:00
|
|
|
|
|
|
|
# Detach HEAD and reset the tree
|
2012-07-25 22:53:08 +08:00
|
|
|
say "$(gettext "First, rewinding head to replay your work on top of it...")"
|
2013-06-16 16:45:12 +08:00
|
|
|
|
|
|
|
GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" \
|
|
|
|
git checkout -q "$onto^0" || die "could not detach HEAD"
|
2011-02-07 02:43:46 +08:00
|
|
|
git update-ref ORIG_HEAD $orig_head
|
2011-02-07 02:43:45 +08:00
|
|
|
|
2006-02-15 06:42:05 +08:00
|
|
|
# If the $onto is a proper descendant of the tip of the branch, then
|
2009-10-24 16:31:32 +08:00
|
|
|
# we just fast-forwarded.
|
2011-02-07 02:43:46 +08:00
|
|
|
if test "$mb" = "$orig_head"
|
2005-12-15 07:36:35 +08:00
|
|
|
then
|
2012-07-25 22:53:08 +08:00
|
|
|
say "$(eval_gettext "Fast-forwarded \$branch_name to \$onto_name.")"
|
2007-11-09 02:19:08 +08:00
|
|
|
move_to_original_branch
|
2013-06-14 00:06:12 +08:00
|
|
|
finish_rebase
|
2005-12-15 07:36:35 +08:00
|
|
|
exit 0
|
|
|
|
fi
|
|
|
|
|
2009-01-06 01:35:16 +08:00
|
|
|
if test -n "$rebase_root"
|
|
|
|
then
|
|
|
|
revisions="$onto..$orig_head"
|
|
|
|
else
|
2014-07-17 03:23:49 +08:00
|
|
|
revisions="${restrict_revision-$upstream}..$orig_head"
|
2009-01-06 01:35:16 +08:00
|
|
|
fi
|
|
|
|
|
2011-02-07 02:43:47 +08:00
|
|
|
run_specific_rebase
|