X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=git-rebase.sh;h=7a02f2975d443cfe35c98d3c62b656850d7d406c;hb=8960b5a7dfb160be65dc9122df8c7603a5f8aced;hp=546fa446fc3c6c63488b9ef38cb5bdc960953cb1;hpb=02a20456d2c5efccbdd0093ad2a16134f160c218;p=git.git diff --git a/git-rebase.sh b/git-rebase.sh index 546fa446f..7a02f2975 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano. # -USAGE='[-v] [--onto ] []' +USAGE='[--interactive | -i] [-v] [--onto ] []' LONG_USAGE='git-rebase replaces with a new branch of the same name. When the --onto option is provided the new branch starts out with a HEAD equal to , otherwise it is equal to @@ -27,7 +27,12 @@ Example: git-rebase master~1 topic / --> / D---E---F---G master D---E---F---G master ' + +SUBDIRECTORY_OK=Yes . git-sh-setup +set_reflog_action rebase +require_work_tree +cd_to_toplevel RESOLVEMSG=" When you have resolved this problem run \"git rebase --continue\". @@ -40,20 +45,21 @@ do_merge= dotest=$GIT_DIR/.dotest-merge prec=4 verbose= +git_am_opt= continue_merge () { test -n "$prev_head" || die "prev_head must be defined" test -d "$dotest" || die "$dotest directory does not exist" - unmerged=$(git-ls-files -u) + unmerged=$(git ls-files -u) if test -n "$unmerged" then echo "You still have unmerged paths in your index" - echo "did you forget update-index?" + echo "did you forget to use git add?" die "$RESOLVEMSG" fi - if test -n "`git-diff-index HEAD`" + if ! git diff-index --quiet HEAD then if ! git-commit -C "`cat $dotest/current`" then @@ -65,10 +71,10 @@ continue_merge () { else printf "Already applied: %0${prec}d" $msgnum fi - echo ' '`git-rev-list --pretty=oneline -1 HEAD | \ + echo ' '`git rev-list --pretty=oneline -1 HEAD | \ sed 's/^[a-f0-9]\+ //'` - prev_head=`git-rev-parse HEAD^0` + prev_head=`git rev-parse HEAD^0` # save the resulting commit so we can read-tree on it later echo "$prev_head" > "$dotest/prev_head" @@ -80,14 +86,22 @@ continue_merge () { call_merge () { cmt="$(cat $dotest/cmt.$1)" echo "$cmt" > "$dotest/current" - git-merge-$strategy "$cmt^" -- HEAD "$cmt" + hd=$(git rev-parse --verify HEAD) + cmt_name=$(git symbolic-ref HEAD) + msgnum=$(cat $dotest/msgnum) + end=$(cat $dotest/end) + eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"' + eval GITHEAD_$hd='"$(cat $dotest/onto_name)"' + export GITHEAD_$cmt GITHEAD_$hd + git-merge-$strategy "$cmt^" -- "$hd" "$cmt" rv=$? case "$rv" in 0) + unset GITHEAD_$cmt GITHEAD_$hd return ;; 1) - test -d "$GIT_DIR/rr-cache" && git-rerere + test -d "$GIT_DIR/rr-cache" && git rerere die "$RESOLVEMSG" ;; 2) @@ -106,17 +120,25 @@ finish_rb_merge () { echo "All done." } +is_interactive () { + test -f "$dotest"/interactive || + while case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac + do + shift + done && test -n "$1" +} + +is_interactive "$@" && exec git-rebase--interactive "$@" + while case "$#" in 0) break ;; esac do case "$1" in --continue) - diff=$(git-diff-files) - case "$diff" in - ?*) echo "You must edit all merge conflicts and then" - echo "mark them as resolved using git update-index" + git diff-files --quiet || { + echo "You must edit all merge conflicts and then" + echo "mark them as resolved using git add" exit 1 - ;; - esac + } if test -d "$dotest" then prev_head="`cat $dotest/prev_head`" @@ -132,13 +154,16 @@ do finish_rb_merge exit fi - git am --resolved --3way --resolvemsg="$RESOLVEMSG" \ - --reflog-action=rebase + git am --resolved --3way --resolvemsg="$RESOLVEMSG" exit ;; --skip) if test -d "$dotest" then + if test -d "$GIT_DIR/rr-cache" + then + git rerere clear + fi prev_head="`cat $dotest/prev_head`" end="`cat $dotest/end`" msgnum="`cat $dotest/msgnum`" @@ -152,11 +177,14 @@ do finish_rb_merge exit fi - git am -3 --skip --resolvemsg="$RESOLVEMSG" \ - --reflog-action=rebase + git am -3 --skip --resolvemsg="$RESOLVEMSG" exit ;; --abort) + if test -d "$GIT_DIR/rr-cache" + then + git rerere clear + fi if test -d "$dotest" then rm -r "$dotest" @@ -194,6 +222,10 @@ do -v|--verbose) verbose=t ;; + -C*) + git_am_opt=$1 + shift + ;; -*) usage ;; @@ -227,10 +259,11 @@ else fi # The tree must be really really clean. -git-update-index --refresh || exit -diff=$(git-diff-index --cached --name-status -r HEAD) +git update-index --refresh || exit +diff=$(git diff-index --cached --name-status -r HEAD) case "$diff" in -?*) echo "$diff" +?*) echo "cannot rebase: your index is not up-to-date" + echo "$diff" exit 1 ;; esac @@ -240,6 +273,10 @@ upstream_name="$1" upstream=`git rev-parse --verify "${upstream_name}^0"` || die "invalid upstream $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 + # If a hook exists, give it a chance to interrupt if test -x "$GIT_DIR/hooks/pre-rebase" then @@ -256,22 +293,24 @@ case "$#" in git-checkout "$2" || usage ;; *) - branch_name=`git symbolic-ref HEAD` || die "No current branch" - branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'` + if branch_name=`git symbolic-ref -q HEAD` + then + branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'` + else + branch_name=HEAD ;# detached + fi ;; esac -branch=$(git-rev-parse --verify "${branch_name}^0") || exit - -# Make sure the branch to rebase onto is valid. -onto_name=${newbase-"$upstream_name"} -onto=$(git-rev-parse --verify "${onto_name}^0") || exit +branch=$(git rev-parse --verify "${branch_name}^0") || exit # Now we are rebasing commits $upstream..$branch on top of $onto -# Check if we are already based on $onto, but this should be -# done only when upstream and onto are the same. -mb=$(git-merge-base "$onto" "$branch") -if test "$upstream" = "$onto" && test "$mb" = "$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. +mb=$(git merge-base "$onto" "$branch") +if test "$upstream" = "$onto" && test "$mb" = "$onto" && + # linear history? + ! git rev-list --parents "$onto".."$branch" | grep " .* " > /dev/null then echo >&2 "Current branch $branch_name is up to date." exit 0 @@ -280,10 +319,12 @@ fi if test -n "$verbose" then echo "Changes from $mb to $onto:" - git-diff-tree --stat --summary "$mb" "$onto" + # We want color (if set), but no pager + GIT_PAGER='' git diff --stat --summary "$mb" "$onto" fi # Rewind the head to "$onto"; this saves our current head in ORIG_HEAD. +echo "First, rewinding head to replay your work on top of it..." git-reset --hard "$onto" # If the $onto is a proper descendant of the tip of the branch, then @@ -296,32 +337,22 @@ fi if test -z "$do_merge" then - git-format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD | - git am --binary -3 -k --resolvemsg="$RESOLVEMSG" \ - --reflog-action=rebase + git format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD | + git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG" exit $? fi -if test "@@NO_PYTHON@@" && test "$strategy" = "recursive-old" -then - die 'The recursive-old merge strategy is written in Python, -which this installation of git was not configured with. Please consider -a different merge strategy (e.g. recursive, resolve, or stupid) -or install Python and git with Python support.' - -fi - # start doing a rebase with git-merge # this is rename-aware if the recursive (default) strategy is used mkdir -p "$dotest" echo "$onto" > "$dotest/onto" -prev_head=`git-rev-parse HEAD^0` +echo "$onto_name" > "$dotest/onto_name" +prev_head=`git rev-parse HEAD^0` echo "$prev_head" > "$dotest/prev_head" msgnum=0 -for cmt in `git-rev-list --no-merges "$upstream"..ORIG_HEAD \ - | @@PERL@@ -e 'print reverse <>'` +for cmt in `git rev-list --reverse --no-merges "$upstream"..ORIG_HEAD` do msgnum=$(($msgnum + 1)) echo "$cmt" > "$dotest/cmt.$msgnum"