]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Thu, 29 Nov 2007 01:06:57 +0000 (17:06 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 29 Nov 2007 01:06:57 +0000 (17:06 -0800)
* maint:
  scripts: do not get confused with HEAD in work tree
  Improve description of git-branch -d and -D in man page.

1  2 
Documentation/git-branch.txt
contrib/examples/git-merge-ours.sh
git-am.sh
git-filter-branch.sh
git-rebase--interactive.sh
git-rebase.sh
git-stash.sh

index 5ce905de862253aa2bd2ed619819306165e978f0,d64ad2502868c0103dafa6fa13764fc7a92d7caa..f87b6968b4808ebc7f831c814ca7e62924a19642
@@@ -45,17 -45,22 +45,22 @@@ to happen
  
  With a `-d` or `-D` option, `<branchname>` will be deleted.  You may
  specify more than one branch for deletion.  If the branch currently
- has a reflog then the reflog will also be deleted. Use -r together with -d
- to delete remote-tracking branches.
+ has a reflog then the reflog will also be deleted.
+ Use -r together with -d to delete remote-tracking branches. Note, that it
+ only makes sense to delete remote-tracking branches if they no longer exist
+ in remote repository or if gitlink:git-fetch[1] was configured not to fetch
+ them again. See also 'prune' subcommand of gitlink:git-remote[1] for way to
+ clean up all obsolete remote-tracking branches.
  
  
  OPTIONS
  -------
  -d::
-       Delete a branch. The branch must be fully merged.
+       Delete a branch. The branch must be fully merged in HEAD.
  
  -D::
-       Delete a branch irrespective of its index status.
+       Delete a branch irrespective of its merged status.
  
  -l::
        Create the branch's reflog.  This activates recording of
@@@ -85,7 -90,7 +90,7 @@@
  -a::
        List both remote-tracking branches and local branches.
  
 --v::
 +-v, --verbose::
        Show sha1 and commit subject line for each head.
  
  --abbrev=<length>::
@@@ -153,9 -158,11 +158,11 @@@ $ git branch -d -r origin/todo origin/h
  $ git branch -D test                                    <2>
  ------------
  +
- <1> Delete remote-tracking branches "todo", "html", "man"
- <2> Delete "test" branch even if the "master" branch does not have all
- commits from test branch.
+ <1> Delete remote-tracking branches "todo", "html", "man". Next 'fetch' or
+ 'pull' will create them again unless you configure them not to. See
+ gitlink:git-fetch[1].
+ <2> Delete "test" branch even if the "master" branch (or whichever branch is
+ currently checked out) does not have all commits from test branch.
  
  
  Notes
index c81a790aa60ea08144dd0899d1aee2ec334a1825,29dba4ba3a57c15bd430bd23c1cebe78e6dc03be..29dba4ba3a57c15bd430bd23c1cebe78e6dc03be
@@@ -9,6 -9,6 +9,6 @@@
  # because the current index is what we will be committing as the
  # merge result.
  
- git diff-index --quiet --cached HEAD || exit 2
+ git diff-index --quiet --cached HEAD -- || exit 2
  
  exit 0
diff --combined git-am.sh
index 4126f0e857bad273d6f44cabe34565de860bd119,5792631d848b0658a6a1a81093ee4eddabf1eea6..76c1c844a95d8af19f64a3278706daf907dace01
+++ b/git-am.sh
@@@ -2,26 -2,11 +2,26 @@@
  #
  # Copyright (c) 2005, 2006 Junio C Hamano
  
 -USAGE='[--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8]
 -  [--3way] [--interactive] [--binary]
 -  [--whitespace=<option>] [-C<n>] [-p<n>]
 -  <mbox>|<Maildir>...
 -  or, when resuming [--skip | --resolved]'
 +OPTIONS_KEEPDASHDASH=
 +OPTIONS_SPEC="\
 +git-am [options] <mbox>|<Maildir>...
 +git-am [options] --resolved
 +git-am [options] --skip
 +--
 +d,dotest=       use <dir> and not .dotest
 +i,interactive   run interactively
 +b,binary        pass --allo-binary-replacement to git-apply
 +3,3way          allow fall back on 3way merging if needed
 +s,signoff       add a Signed-off-by line to the commit message
 +u,utf8          recode into utf8 (default)
 +k,keep          pass -k flagg to git-mailinfo
 +whitespace=     pass it through git-apply
 +C=              pass it through git-apply
 +p=              pass it through git-apply
 +resolvemsg=     override error message when patch failure occurs
 +r,resolved      to be used after a patch failure
 +skip            skip the current patch"
 +
  . git-sh-setup
  set_reflog_action am
  require_work_tree
@@@ -125,38 -110,49 +125,38 @@@ git_apply_opt
  while test $# != 0
  do
        case "$1" in
 -      -d=*|--d=*|--do=*|--dot=*|--dote=*|--dotes=*|--dotest=*)
 -      dotest=`expr "z$1" : 'z-[^=]*=\(.*\)'`; shift ;;
 -      -d|--d|--do|--dot|--dote|--dotes|--dotest)
 -      case "$#" in 1) usage ;; esac; shift
 -      dotest="$1"; shift;;
 -
 -      -i|--i|--in|--int|--inte|--inter|--intera|--interac|--interact|\
 -      --interacti|--interactiv|--interactive)
 -      interactive=t; shift ;;
 -
 -      -b|--b|--bi|--bin|--bina|--binar|--binary)
 -      binary=t; shift ;;
 -
 -      -3|--3|--3w|--3wa|--3way)
 -      threeway=t; shift ;;
 -      -s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
 -      sign=t; shift ;;
 -      -u|--u|--ut|--utf|--utf8)
 -      utf8=t; shift ;; # this is now default
 -      --no-u|--no-ut|--no-utf|--no-utf8)
 -      utf8=; shift ;;
 -      -k|--k|--ke|--kee|--keep)
 -      keep=t; shift ;;
 -
 -      -r|--r|--re|--res|--reso|--resol|--resolv|--resolve|--resolved)
 -      resolved=t; shift ;;
 -
 -      --sk|--ski|--skip)
 -      skip=t; shift ;;
 -
 -      --whitespace=*|-C*|-p*)
 -      git_apply_opt="$git_apply_opt $1"; shift ;;
 -
 -      --resolvemsg=*)
 -      resolvemsg=${1#--resolvemsg=}; shift ;;
 -
 +      -i|--interactive)
 +              interactive=t ;;
 +      -b|--binary)
 +              binary=t ;;
 +      -3|--3way)
 +              threeway=t ;;
 +      -s|--signoff)
 +              sign=t ;;
 +      -u|--utf8)
 +              utf8=t ;; # this is now default
 +      --no-utf8)
 +              utf8= ;;
 +      -k|--keep)
 +              keep=t ;;
 +      -r|--resolved)
 +              resolved=t ;;
 +      --skip)
 +              skip=t ;;
 +      -d|--dotest)
 +              shift; dotest=$1;;
 +      --resolvemsg)
 +              shift; resolvemsg=$1 ;;
 +      --whitespace)
 +              git_apply_opt="$git_apply_opt $1=$2"; shift ;;
 +      -C|-p)
 +              git_apply_opt="$git_apply_opt $1$2"; shift ;;
        --)
 -      shift; break ;;
 -      -*)
 -      usage ;;
 +              shift; break ;;
        *)
 -      break ;;
 +              usage ;;
        esac
 +      shift
  done
  
  # If the dotest directory exists, but we have finished applying all the
@@@ -218,7 -214,7 +218,7 @@@ f
  
  case "$resolved" in
  '')
-       files=$(git diff-index --cached --name-only HEAD) || exit
+       files=$(git diff-index --cached --name-only HEAD --) || exit
        if [ "$files" ]; then
           echo "Dirty index: cannot apply patches (dirty: $files)" >&2
           exit 1
@@@ -352,7 -348,7 +352,7 @@@ d
                case "$resolved$interactive" in
                tt)
                        # This is used only for interactive view option.
-                       git diff-index -p --cached HEAD >"$dotest/patch"
+                       git diff-index -p --cached HEAD -- >"$dotest/patch"
                        ;;
                esac
        esac
                stop_here $this
        fi
  
 -      echo
        printf 'Applying %s\n' "$SUBJECT"
 -      echo
  
        case "$resolved" in
        '')
                # trust what the user has in the index file and the
                # working tree.
                resolved=
-               git diff-index --quiet --cached HEAD && {
+               git diff-index --quiet --cached HEAD -- && {
                        echo "No changes - did you forget to use 'git add'?"
                        stop_here_user_resolve $this
                }
                then
                    # Applying the patch to an earlier tree and merging the
                    # result may have produced the same tree as ours.
-                   git diff-index --quiet --cached HEAD && {
+                   git diff-index --quiet --cached HEAD -- && {
                        echo No changes -- Patch already applied.
                        go_next
                        continue
        fi
  
        tree=$(git write-tree) &&
 -      echo Wrote tree $tree &&
        parent=$(git rev-parse --verify HEAD) &&
        commit=$(git commit-tree $tree -p $parent <"$dotest/final-commit") &&
 -      echo Committed: $commit &&
        git update-ref -m "$GIT_REFLOG_ACTION: $SUBJECT" HEAD $commit $parent ||
        stop_here $this
  
                "$GIT_DIR"/hooks/post-applypatch
        fi
  
 +      git gc --auto
 +
        go_next
  done
  
diff --combined git-filter-branch.sh
index 19cab5a9a8b7ebbdf740158ba4f651457e3d53e5,dbab1a9a4ab91caae34f2baecd2439a7b15d11af..674a25d27e50b421e516e8ca6e1190d04e323e9c
@@@ -8,9 -8,6 +8,9 @@@
  # a new branch. You can specify a number of filters to modify the commits,
  # files and trees.
  
 +# The following functions will also be available in the commit filter:
 +
 +functions=$(cat << \EOF
  warn () {
          echo "$*" >&2
  }
@@@ -49,10 -46,6 +49,10 @@@ die(
        echo "$*" >&2
        exit 1
  }
 +EOF
 +)
 +
 +eval "$functions"
  
  # When piped a commit, output a script to set the ident of either
  # "author" or "committer
@@@ -87,6 -80,11 +87,6 @@@ set_ident () 
        echo "[ -n \"\$GIT_${uid}_NAME\" ] || export GIT_${uid}_NAME=\"\${GIT_${uid}_EMAIL%%@*}\""
  }
  
 -# This script can be sourced by the commit filter to get the functions
 -test "a$SOURCE_FUNCTIONS" = a1 && return
 -this_script="$(cd "$(dirname "$0")"; pwd)"/$(basename "$0")
 -export this_script
 -
  USAGE="[--env-filter <command>] [--tree-filter <command>] \
  [--index-filter <command>] [--parent-filter <command>] \
  [--msg-filter <command>] [--commit-filter <command>] \
  [--original <namespace>] [-d <directory>] [-f | --force] \
  [<rev-list options>...]"
  
 +OPTIONS_SPEC=
  . git-sh-setup
  
  git diff-files --quiet &&
-       git diff-index --cached --quiet HEAD ||
+       git diff-index --cached --quiet HEAD -- ||
        die "Cannot rewrite branch(es) with a dirty working directory."
  
  tempdir=.git-rewrite
@@@ -158,7 -155,7 +158,7 @@@ d
                filter_msg="$OPTARG"
                ;;
        --commit-filter)
 -              filter_commit='SOURCE_FUNCTIONS=1 . "$this_script";'" $OPTARG"
 +              filter_commit="$functions; $OPTARG"
                ;;
        --tag-name-filter)
                filter_tag_name="$OPTARG"
index bf44b6af58574273df9e7f549136a735f6e549fe,ff38a22edfa60a759c5e68d9e6968d11531e72d1..e9cd6fd999695daa1c5ba49835f53041d4131f3a
@@@ -13,7 -13,6 +13,7 @@@
  USAGE='(--continue | --abort | --skip | [--preserve-merges] [--verbose]
        [--onto <branch>] <upstream> [<branch>])'
  
 +OPTIONS_SPEC=
  . git-sh-setup
  require_work_tree
  
@@@ -37,14 -36,14 +37,14 @@@ warn () 
  output () {
        case "$VERBOSE" in
        '')
 -              "$@" > "$DOTEST"/output 2>&1
 +              output=$("$@" 2>&1 )
                status=$?
 -              test $status != 0 &&
 -                      cat "$DOTEST"/output
 +              test $status != 0 && printf "%s\n" "$output"
                return $status
 -      ;;
 +              ;;
        *)
                "$@"
 +              ;;
        esac
  }
  
@@@ -53,7 -52,7 +53,7 @@@ require_clean_work_tree () 
        git rev-parse --verify HEAD > /dev/null &&
        git update-index --refresh &&
        git diff-files --quiet &&
-       git diff-index --cached --quiet HEAD ||
+       git diff-index --cached --quiet HEAD -- ||
        die "Working tree is dirty"
  }
  
@@@ -64,7 -63,6 +64,7 @@@ comment_for_reflog () 
        ''|rebase*)
                GIT_REFLOG_ACTION="rebase -i ($1)"
                export GIT_REFLOG_ACTION
 +              ;;
        esac
  }
  
@@@ -72,23 -70,22 +72,23 @@@ mark_action_done () 
        sed -e 1q < "$TODO" >> "$DONE"
        sed -e 1d < "$TODO" >> "$TODO".new
        mv -f "$TODO".new "$TODO"
 -      count=$(($(wc -l < "$DONE")))
 -      total=$(($count+$(wc -l < "$TODO")))
 +      count=$(($(grep -ve '^$' -e '^#' < "$DONE" | wc -l)))
 +      total=$(($count+$(grep -ve '^$' -e '^#' < "$TODO" | wc -l)))
        printf "Rebasing (%d/%d)\r" $count $total
        test -z "$VERBOSE" || echo
  }
  
  make_patch () {
 -      parent_sha1=$(git rev-parse --verify "$1"^ 2> /dev/null)
 +      parent_sha1=$(git rev-parse --verify "$1"^) ||
 +              die "Cannot get patch for $1^"
        git diff-tree -p "$parent_sha1".."$1" > "$DOTEST"/patch
 +      test -f "$DOTEST"/message ||
 +              git cat-file commit "$1" | sed "1,/^$/d" > "$DOTEST"/message
 +      test -f "$DOTEST"/author-script ||
 +              get_author_ident_from_commit "$1" > "$DOTEST"/author-script
  }
  
  die_with_patch () {
 -      test -f "$DOTEST"/message ||
 -              git cat-file commit $sha1 | sed "1,/^$/d" > "$DOTEST"/message
 -      test -f "$DOTEST"/author-script ||
 -              get_author_ident_from_commit $sha1 > "$DOTEST"/author-script
        make_patch "$1"
        die "$2"
  }
@@@ -98,20 -95,15 +98,20 @@@ die_abort () 
        die "$1"
  }
  
 +has_action () {
 +      grep -vqe '^$' -e '^#' "$1"
 +}
 +
  pick_one () {
        no_ff=
        case "$1" in -n) sha1=$2; no_ff=t ;; *) sha1=$1 ;; esac
        output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
        test -d "$REWRITTEN" &&
                pick_one_preserving_merges "$@" && return
 -      parent_sha1=$(git rev-parse --verify $sha1^ 2>/dev/null)
 +      parent_sha1=$(git rev-parse --verify $sha1^) ||
 +              die "Could not get the parent of $sha1"
        current_sha1=$(git rev-parse --verify HEAD)
 -      if test $no_ff$current_sha1 = $parent_sha1; then
 +      if test "$no_ff$current_sha1" = "$parent_sha1"; then
                output git reset --hard $sha1
                test "a$1" = a-n && output git reset --soft $current_sha1
                sha1=$(git rev-parse --short $sha1)
@@@ -137,7 -129,7 +137,7 @@@ pick_one_preserving_merges () 
        fast_forward=t
        preserve=t
        new_parents=
 -      for p in $(git rev-list --parents -1 $sha1 | cut -d -f2-)
 +      for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
        do
                if test -f "$REWRITTEN"/$p
                then
                                ;; # do nothing; that parent is already there
                        *)
                                new_parents="$new_parents $new_p"
 +                              ;;
                        esac
                fi
        done
        case $fast_forward in
        t)
                output warn "Fast forward to $sha1"
 -              test $preserve=f && echo $sha1 > "$REWRITTEN"/$sha1
 +              test $preserve = f || echo $sha1 > "$REWRITTEN"/$sha1
                ;;
        f)
                test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
  
 -              first_parent=$(expr "$new_parents" : " \([^ ]*\)")
 +              first_parent=$(expr "$new_parents" : ' \([^ ]*\)')
                # detach HEAD to current parent
                output git checkout $first_parent 2> /dev/null ||
                        die "Cannot move HEAD to $first_parent"
  
                echo $sha1 > "$DOTEST"/current-commit
                case "$new_parents" in
 -              \ *\ *)
 +              ' '*' '*)
                        # redo merge
                        author_script=$(get_author_ident_from_commit $sha1)
                        eval "$author_script"
 -                      msg="$(git cat-file commit $sha1 | \
 -                              sed -e '1,/^$/d' -e "s/[\"\\]/\\\\&/g")"
 +                      msg="$(git cat-file commit $sha1 | sed -e '1,/^$/d')"
                        # No point in merging the first parent, that's HEAD
                        new_parents=${new_parents# $first_parent}
                        # NEEDSWORK: give rerere a chance
 -                      if ! output git merge $STRATEGY -m "$msg" $new_parents
 +                      if ! GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
 +                              GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
 +                              GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" \
 +                              output git merge $STRATEGY -m "$msg" \
 +                                      $new_parents
                        then
 -                              echo "$msg" > "$GIT_DIR"/MERGE_MSG
 +                              printf "%s\n" "$msg" > "$GIT_DIR"/MERGE_MSG
                                die Error redoing merge $sha1
                        fi
                        ;;
                *)
                        output git cherry-pick "$@" ||
                                die_with_patch $sha1 "Could not pick $sha1"
 +                      ;;
                esac
 +              ;;
        esac
  }
  
@@@ -228,28 -214,27 +228,28 @@@ peek_next_command () 
  }
  
  do_next () {
 -      test -f "$DOTEST"/message && rm "$DOTEST"/message
 -      test -f "$DOTEST"/author-script && rm "$DOTEST"/author-script
 +      rm -f "$DOTEST"/message "$DOTEST"/author-script \
 +              "$DOTEST"/amend || exit
        read command sha1 rest < "$TODO"
        case "$command" in
 -      \#|'')
 +      '#'*|'')
                mark_action_done
                ;;
 -      pick)
 +      pick|p)
                comment_for_reflog pick
  
                mark_action_done
                pick_one $sha1 ||
                        die_with_patch $sha1 "Could not apply $sha1... $rest"
                ;;
 -      edit)
 +      edit|e)
                comment_for_reflog edit
  
                mark_action_done
                pick_one $sha1 ||
                        die_with_patch $sha1 "Could not apply $sha1... $rest"
                make_patch $sha1
 +              : > "$DOTEST"/amend
                warn
                warn "You can amend the commit now, with"
                warn
                warn
                exit 0
                ;;
 -      squash)
 +      squash|s)
                comment_for_reflog squash
  
 -              test -z "$(grep -ve '^$' -e '^#' < $DONE)" &&
 +              has_action "$DONE" ||
                        die "Cannot 'squash' without a previous commit"
  
                mark_action_done
                make_squash_message $sha1 > "$MSG"
                case "$(peek_next_command)" in
 -              squash)
 +              squash|s)
                        EDIT_COMMIT=
                        USE_OUTPUT=output
                        cp "$MSG" "$SQUASH_MSG"
 -              ;;
 +                      ;;
                *)
                        EDIT_COMMIT=-e
                        USE_OUTPUT=
 -                      test -f "$SQUASH_MSG" && rm "$SQUASH_MSG"
 +                      rm -f "$SQUASH_MSG" || exit
 +                      ;;
                esac
  
                failed=f
                f)
                        # This is like --amend, but with a different message
                        eval "$author_script"
 -                      export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
 +                      GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
 +                      GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
 +                      GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" \
                        $USE_OUTPUT git commit -F "$MSG" $EDIT_COMMIT
                        ;;
                t)
                        warn
                        warn "Could not apply $sha1... $rest"
                        die_with_patch $sha1 ""
 +                      ;;
                esac
                ;;
        *)
                warn "Unknown command: $command $sha1 $rest"
                die_with_patch $sha1 "Please fix this in the file $TODO."
 +              ;;
        esac
        test -s "$TODO" && return
  
        else
                NEWHEAD=$(git rev-parse HEAD)
        fi &&
 -      message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)" &&
 -      git update-ref -m "$message" $HEADNAME $NEWHEAD $OLDHEAD &&
 -      git symbolic-ref HEAD $HEADNAME && {
 +      case $HEADNAME in
 +      refs/*)
 +              message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)" &&
 +              git update-ref -m "$message" $HEADNAME $NEWHEAD $OLDHEAD &&
 +              git symbolic-ref HEAD $HEADNAME
 +              ;;
 +      esac && {
                test ! -f "$DOTEST"/verbose ||
                        git diff-tree --stat $(cat "$DOTEST"/head)..HEAD
        } &&
        rm -rf "$DOTEST" &&
 +      git gc --auto &&
        warn "Successfully rebased and updated $HEADNAME."
  
        exit
                git rev-parse --verify HEAD > /dev/null &&
                git update-index --refresh &&
                git diff-files --quiet &&
-               ! git diff-index --cached --quiet HEAD &&
+               ! git diff-index --cached --quiet HEAD -- &&
 -              . "$DOTEST"/author-script &&
 +              . "$DOTEST"/author-script && {
 +                      test ! -f "$DOTEST"/amend || git reset --soft HEAD^
 +              } &&
                export GIT_AUTHOR_NAME GIT_AUTHOR_NAME GIT_AUTHOR_DATE &&
                git commit -F "$DOTEST"/message -e
  
  
                HEADNAME=$(cat "$DOTEST"/head-name)
                HEAD=$(cat "$DOTEST"/head)
 -              git symbolic-ref HEAD $HEADNAME &&
 +              case $HEADNAME in
 +              refs/*)
 +                      git symbolic-ref HEAD $HEADNAME
 +                      ;;
 +              esac &&
                output git reset --hard $HEAD &&
                rm -rf "$DOTEST"
                exit
  
                require_clean_work_tree
  
 -              mkdir "$DOTEST" || die "Could not create temporary $DOTEST"
                if test ! -z "$2"
                then
                        output git show-ref --verify --quiet "refs/heads/$2" ||
                HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
                UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
  
 +              mkdir "$DOTEST" || die "Could not create temporary $DOTEST"
 +
                test -z "$ONTO" && ONTO=$UPSTREAM
  
                : > "$DOTEST"/interactive || die "Could not mark as interactive"
 -              git symbolic-ref HEAD > "$DOTEST"/head-name ||
 -                      die "Could not get HEAD"
 +              git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||
 +                      echo "detached HEAD" > "$DOTEST"/head-name
  
                echo $HEAD > "$DOTEST"/head
                echo $UPSTREAM > "$DOTEST"/upstream
                SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM)
                SHORTHEAD=$(git rev-parse --short $HEAD)
                SHORTONTO=$(git rev-parse --short $ONTO)
 -              cat > "$TODO" << EOF
 -# Rebasing $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
 +              git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
 +                      --abbrev=7 --reverse --left-right --cherry-pick \
 +                      $UPSTREAM...$HEAD | \
 +                      sed -n "s/^>/pick /p" > "$TODO"
 +              cat >> "$TODO" << EOF
 +
 +# Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
  #
  # Commands:
  #  pick = use commit
  #  squash = use commit, but meld into previous commit
  #
  # If you remove a line here THAT COMMIT WILL BE LOST.
 +# However, if you remove everything, the rebase will be aborted.
  #
  EOF
 -              git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
 -                      --abbrev=7 --reverse --left-right --cherry-pick \
 -                      $UPSTREAM...$HEAD | \
 -                      sed -n "s/^>/pick /p" >> "$TODO"
  
 -              test -z "$(grep -ve '^$' -e '^#' < $TODO)" &&
 +              has_action "$TODO" ||
                        die_abort "Nothing to do"
  
                cp "$TODO" "$TODO".backup
                git_editor "$TODO" ||
                        die "Could not execute editor"
  
 -              test -z "$(grep -ve '^$' -e '^#' < $TODO)" &&
 +              has_action "$TODO" ||
                        die_abort "Nothing to do"
  
                output git checkout $ONTO && do_rest
 +              ;;
        esac
        shift
  done
diff --combined git-rebase.sh
index 461ca8d93f4ab5c43792b4658d53b2e39ad18af1,c9b284c751b2a81e482b2b6bdecb2fecaf68ac52..bdcea0ed703057e08fd4204245f4f0c8a308f8d0
@@@ -29,7 -29,6 +29,7 @@@ Example:       git-rebase master~1 topi
  '
  
  SUBDIRECTORY_OK=Yes
 +OPTIONS_SPEC=
  . git-sh-setup
  set_reflog_action rebase
  require_work_tree
@@@ -61,7 -60,7 +61,7 @@@ continue_merge () 
        fi
  
        cmt=`cat "$dotest/current"`
-       if ! git diff-index --quiet HEAD
+       if ! git diff-index --quiet HEAD --
        then
                if ! git-commit -C "$cmt"
                then
@@@ -88,7 -87,7 +88,7 @@@ call_merge () 
        cmt="$(cat "$dotest/cmt.$1")"
        echo "$cmt" > "$dotest/current"
        hd=$(git rev-parse --verify HEAD)
 -      cmt_name=$(git symbolic-ref HEAD)
 +      cmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD)
        msgnum=$(cat "$dotest/msgnum")
        end=$(cat "$dotest/end")
        eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
        esac
  }
  
 +move_to_original_branch () {
 +      test -z "$head_name" &&
 +              head_name="$(cat "$dotest"/head-name)" &&
 +              onto="$(cat "$dotest"/onto)" &&
 +              orig_head="$(cat "$dotest"/orig-head)"
 +      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 &&
 +              git symbolic-ref HEAD $head_name ||
 +              die "Could not move back to $head_name"
 +              ;;
 +      esac
 +}
 +
  finish_rb_merge () {
 +      move_to_original_branch
        rm -r "$dotest"
        echo "All done."
  }
                        finish_rb_merge
                        exit
                fi
 -              git am --resolved --3way --resolvemsg="$RESOLVEMSG"
 +              head_name=$(cat .dotest/head-name) &&
 +              onto=$(cat .dotest/onto) &&
 +              orig_head=$(cat .dotest/orig-head) &&
 +              git am --resolved --3way --resolvemsg="$RESOLVEMSG" &&
 +              move_to_original_branch
                exit
                ;;
        --skip)
 +              git reset --hard HEAD || exit $?
                if test -d "$dotest"
                then
                        git rerere clear
                        finish_rb_merge
                        exit
                fi
 -              git am -3 --skip --resolvemsg="$RESOLVEMSG"
 +              head_name=$(cat .dotest/head-name) &&
 +              onto=$(cat .dotest/onto) &&
 +              orig_head=$(cat .dotest/orig-head) &&
 +              git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
 +              move_to_original_branch
                exit
                ;;
        --abort)
                git rerere clear
                if test -d "$dotest"
                then
 +                      move_to_original_branch
                        rm -r "$dotest"
                elif test -d .dotest
                then
 +                      dotest=.dotest
 +                      move_to_original_branch
                        rm -r .dotest
                else
                        die "No rebase in progress?"
        -v|--verbose)
                verbose=t
                ;;
 +      --whitespace=*)
 +              git_am_opt="$git_am_opt $1"
 +              ;;
        -C*)
 -              git_am_opt=$1
 -              shift
 +              git_am_opt="$git_am_opt $1"
                ;;
        -*)
                usage
@@@ -285,7 -253,7 +285,7 @@@ f
  
  # The tree must be really really clean.
  git update-index --refresh || exit
- diff=$(git diff-index --cached --name-status -r HEAD)
+ diff=$(git diff-index --cached --name-status -r HEAD --)
  case "$diff" in
  ?*)   echo "cannot rebase: your index is not up-to-date"
        echo "$diff"
@@@ -348,19 -316,6 +348,19 @@@ the
        GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
  fi
  
 +# move to a detached HEAD
 +orig_head=$(git rev-parse HEAD^0)
 +head_name=$(git symbolic-ref HEAD 2> /dev/null)
 +case "$head_name" in
 +'')
 +      head_name="detached HEAD"
 +      ;;
 +*)
 +      git checkout "$orig_head" > /dev/null 2>&1 ||
 +              die "could not detach HEAD"
 +      ;;
 +esac
 +
  # 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 test "$mb" = "$branch"
  then
        echo >&2 "Fast-forwarded $branch_name to $onto_name."
 +      move_to_original_branch
        exit 0
  fi
  
  if test -z "$do_merge"
  then
        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 $?
 +      git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG" &&
 +      move_to_original_branch
 +      ret=$?
 +      test 0 != $ret -a -d .dotest &&
 +              echo $head_name > .dotest/head-name &&
 +              echo $onto > .dotest/onto &&
 +              echo $orig_head > .dotest/orig-head
 +      exit $ret
  fi
  
  # start doing a rebase with git-merge
  mkdir -p "$dotest"
  echo "$onto" > "$dotest/onto"
  echo "$onto_name" > "$dotest/onto_name"
 -prev_head=`git rev-parse HEAD^0`
 +prev_head=$orig_head
  echo "$prev_head" > "$dotest/prev_head"
 +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`
diff --combined git-stash.sh
index dd155568d96771b2dcd62ecae0cc2c050169bf52,77c94210b7f6532674c654274f41aa6733d67b8d..b1529e28b1c4eb8b236bd497c83690c20621d369
@@@ -4,7 -4,6 +4,7 @@@
  USAGE='[ | list | show | apply | clear]'
  
  SUBDIRECTORY_OK=Yes
 +OPTIONS_SPEC=
  . git-sh-setup
  require_work_tree
  cd_to_toplevel
@@@ -15,29 -14,35 +15,29 @@@ trap 'rm -f "$TMP-*"' 
  ref_stash=refs/stash
  
  no_changes () {
-       git diff-index --quiet --cached HEAD &&
+       git diff-index --quiet --cached HEAD -- &&
        git diff-files --quiet
  }
  
  clear_stash () {
        if current=$(git rev-parse --verify $ref_stash 2>/dev/null)
        then
 -              git update-ref -d refs/stash $current
 +              git update-ref -d $ref_stash $current
        fi
  }
  
 -save_stash () {
 +create_stash () {
        stash_msg="$1"
  
        if no_changes
        then
 -              echo >&2 'No local changes to save'
                exit 0
        fi
 -      test -f "$GIT_DIR/logs/$ref_stash" ||
 -              clear_stash || die "Cannot initialize stash"
 -
 -      # Make sure the reflog for stash is kept.
 -      : >>"$GIT_DIR/logs/$ref_stash"
  
        # state of the base commit
        if b_commit=$(git rev-parse --verify HEAD)
        then
 -              head=$(git log --abbrev-commit --pretty=oneline -n 1 HEAD)
 +              head=$(git log --no-color --abbrev-commit --pretty=oneline -n 1 HEAD --)
        else
                die "You do not have the initial commit yet"
        fi
        w_commit=$(printf '%s\n' "$stash_msg" |
                git commit-tree $w_tree -p $b_commit -p $i_commit) ||
                die "Cannot record working tree state"
 +}
 +
 +save_stash () {
 +      stash_msg="$1"
 +
 +      if no_changes
 +      then
 +              echo >&2 'No local changes to save'
 +              exit 0
 +      fi
 +      test -f "$GIT_DIR/logs/$ref_stash" ||
 +              clear_stash || die "Cannot initialize stash"
 +
 +      create_stash "$stash_msg"
 +
 +      # Make sure the reflog for stash is kept.
 +      : >>"$GIT_DIR/logs/$ref_stash"
  
        git update-ref -m "$stash_msg" $ref_stash $w_commit ||
                die "Cannot save the current status"
@@@ -108,7 -96,7 +108,7 @@@ have_stash () 
  
  list_stash () {
        have_stash || return 0
 -      git log --pretty=oneline -g "$@" $ref_stash |
 +      git log --no-color --pretty=oneline -g "$@" $ref_stash -- |
        sed -n -e 's/^[.0-9a-f]* refs\///p'
  }
  
@@@ -214,13 -202,6 +214,13 @@@ apply
  clear)
        clear_stash
        ;;
 +create)
 +      if test $# -gt 0 && test "$1" = create
 +      then
 +              shift
 +      fi
 +      create_stash "$*" && echo "$w_commit"
 +      ;;
  help | usage)
        usage
        ;;