remote: refactor some logic into get_stale_heads()
[gitweb.git] / git-rebase.sh
index 368c0ef4342df990a5617fd6fbe2cd973b1b208b..6ec155cf03c98f2e075f298039037d0e099311b1 100755 (executable)
@@ -3,7 +3,7 @@
 # Copyright (c) 2005 Junio C Hamano.
 #
 
-USAGE='[--interactive | -i] [-v] [--onto <newbase>] [<upstream>|--root] [<branch>]'
+USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--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>
@@ -46,8 +46,10 @@ do_merge=
 dotest="$GIT_DIR"/rebase-merge
 prec=4
 verbose=
+diffstat=$(git config --bool rebase.stat)
 git_am_opt=
 rebase_root=
+force_rebase=
 
 continue_merge () {
        test -n "$prev_head" || die "prev_head must be defined"
@@ -70,11 +72,20 @@ continue_merge () {
                        echo "directly, but instead do one of the following: "
                        die "$RESOLVEMSG"
                fi
-               printf "Committed: %0${prec}d " $msgnum
+               if test -z "$GIT_QUIET"
+               then
+                       printf "Committed: %0${prec}d " $msgnum
+               fi
        else
-               printf "Already applied: %0${prec}d " $msgnum
+               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
-       git rev-list --pretty=oneline -1 "$cmt" | sed -e 's/^[^ ]* //'
 
        prev_head=`git rev-parse HEAD^0`
        # save the resulting commit so we can read-tree on it later
@@ -95,6 +106,10 @@ call_merge () {
        eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
        eval GITHEAD_$hd='$(cat "$dotest/onto_name")'
        export GITHEAD_$cmt GITHEAD_$hd
+       if test -n "$GIT_QUIET"
+       then
+               export GIT_MERGE_VERBOSITY=1
+       fi
        git-merge-$strategy "$cmt^" -- "$hd" "$cmt"
        rv=$?
        case "$rv" in
@@ -136,7 +151,7 @@ move_to_original_branch () {
 finish_rb_merge () {
        move_to_original_branch
        rm -r "$dotest"
-       echo "All done."
+       say All done.
 }
 
 is_interactive () {
@@ -166,10 +181,8 @@ run_pre_rebase_hook () {
        if test -z "$OK_TO_SKIP_PRE_REBASE" &&
           test -x "$GIT_DIR/hooks/pre-rebase"
        then
-               "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
-                       echo >&2 "The pre-rebase hook refused to rebase."
-                       exit 1
-               }
+               "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} ||
+               die "The pre-rebase hook refused to rebase."
        fi
 }
 
@@ -207,6 +220,7 @@ do
                        end=$(cat "$dotest/end")
                        msgnum=$(cat "$dotest/msgnum")
                        onto=$(cat "$dotest/onto")
+                       GIT_QUIET=$(cat "$dotest/quiet")
                        continue_merge
                        while test "$msgnum" -le "$end"
                        do
@@ -219,6 +233,7 @@ do
                head_name=$(cat "$GIT_DIR"/rebase-apply/head-name) &&
                onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
                orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
+               GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet)
                git am --resolved --3way --resolvemsg="$RESOLVEMSG" &&
                move_to_original_branch
                exit
@@ -236,6 +251,7 @@ do
                        msgnum=$(cat "$dotest/msgnum")
                        msgnum=$(($msgnum + 1))
                        onto=$(cat "$dotest/onto")
+                       GIT_QUIET=$(cat "$dotest/quiet")
                        while test "$msgnum" -le "$end"
                        do
                                call_merge "$msgnum"
@@ -247,6 +263,7 @@ do
                head_name=$(cat "$GIT_DIR"/rebase-apply/head-name) &&
                onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
                orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
+               GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet)
                git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
                move_to_original_branch
                exit
@@ -258,9 +275,11 @@ do
                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
                git reset --hard $(cat "$dotest/orig-head")
@@ -289,18 +308,47 @@ do
                esac
                do_merge=t
                ;;
+       -n|--no-stat)
+               diffstat=
+               ;;
+       --stat)
+               diffstat=t
+               ;;
        -v|--verbose)
                verbose=t
+               diffstat=t
+               GIT_QUIET=
+               ;;
+       -q|--quiet)
+               GIT_QUIET=t
+               git_am_opt="$git_am_opt -q"
+               verbose=
+               diffstat=
                ;;
        --whitespace=*)
+               git_am_opt="$git_am_opt $1"
+               case "$1" in
+               --whitespace=fix|--whitespace=strip)
+                       force_rebase=t
+                       ;;
+               esac
+               ;;
+       --ignore-whitespace)
                git_am_opt="$git_am_opt $1"
                ;;
+       --committer-date-is-author-date|--ignore-date)
+               git_am_opt="$git_am_opt $1"
+               force_rebase=t
+               ;;
        -C*)
                git_am_opt="$git_am_opt $1"
                ;;
        --root)
                rebase_root=t
                ;;
+       -f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase)
+               force_rebase=t
+               ;;
        -*)
                usage
                ;;
@@ -337,8 +385,9 @@ else
 fi
 
 # The tree must be really really clean.
-if ! git update-index --ignore-submodules --refresh; then
+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 --)
@@ -420,29 +469,37 @@ if test "$upstream" = "$onto" && test "$mb" = "$onto" &&
        # linear history?
        ! (git rev-list --parents "$onto".."$branch" | grep " .* ") > /dev/null
 then
-       # Lazily switch to the target branch if needed...
-       test -z "$switch_to" || git checkout "$switch_to"
-       echo >&2 "Current branch $branch_name is up to date."
-       exit 0
+       if test -z "$force_rebase"
+       then
+               # Lazily switch to the target branch if needed...
+               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, rebase forced."
+       fi
 fi
 
-if test -n "$verbose"
+# Detach HEAD and reset the tree
+say "First, rewinding head to replay your work on top of it..."
+git checkout -q "$onto^0" || die "could not detach HEAD"
+git update-ref ORIG_HEAD $branch
+
+if test -n "$diffstat"
 then
-       echo "Changes from $mb to $onto:"
+       if test -n "$verbose"
+       then
+               echo "Changes from $mb to $onto:"
+       fi
        # We want color (if set), but no pager
        GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
 fi
 
-# Detach HEAD and reset the tree
-echo "First, rewinding head to replay your work on top of it..."
-git checkout -q "$onto^0" || die "could not detach HEAD"
-git update-ref ORIG_HEAD $branch
-
 # If the $onto is a proper descendant of the tip of the branch, then
 # we just fast forwarded.
 if test "$mb" = "$branch"
 then
-       echo >&2 "Fast-forwarded $branch_name to $onto_name."
+       say "Fast-forwarded $branch_name to $onto_name."
        move_to_original_branch
        exit 0
 fi
@@ -464,7 +521,8 @@ then
        test 0 != $ret -a -d "$GIT_DIR"/rebase-apply &&
                echo $head_name > "$GIT_DIR"/rebase-apply/head-name &&
                echo $onto > "$GIT_DIR"/rebase-apply/onto &&
-               echo $orig_head > "$GIT_DIR"/rebase-apply/orig-head
+               echo $orig_head > "$GIT_DIR"/rebase-apply/orig-head &&
+               echo "$GIT_QUIET" > "$GIT_DIR"/rebase-apply/quiet
        exit $ret
 fi
 
@@ -478,6 +536,7 @@ prev_head=$orig_head
 echo "$prev_head" > "$dotest/prev_head"
 echo "$orig_head" > "$dotest/orig-head"
 echo "$head_name" > "$dotest/head-name"
+echo "$GIT_QUIET" > "$dotest/quiet"
 
 msgnum=0
 for cmt in `git rev-list --reverse --no-merges "$revisions"`