git-checkout.shon commit Merge http://www.kernel.org/pub/scm/gitk/gitk (56fc631)
   1#!/bin/sh
   2. git-sh-setup
   3
   4usage () {
   5    die "usage: git checkout [-f] [-b <new_branch>] [<branch>] [<paths>...]"
   6}
   7
   8old=$(git-rev-parse HEAD)
   9new=
  10force=
  11branch=
  12newbranch=
  13while [ "$#" != "0" ]; do
  14    arg="$1"
  15    shift
  16    case "$arg" in
  17        "-b")
  18                newbranch="$1"
  19                shift
  20                [ -z "$newbranch" ] &&
  21                        die "git checkout: -b needs a branch name"
  22                [ -e "$GIT_DIR/refs/heads/$newbranch" ] &&
  23                        die "git checkout: branch $newbranch already exists"
  24                git-check-ref-format "heads/$newbranch" ||
  25                        die "we do not like '$newbranch' as a branch name."
  26                ;;
  27        "-f")
  28                force=1
  29                ;;
  30        --)
  31                break
  32                ;;
  33        -*)
  34                usage
  35                ;;
  36        *)
  37                if rev=$(git-rev-parse --verify "$arg^0" 2>/dev/null)
  38                then
  39                        if [ -z "$rev" ]; then
  40                                echo "unknown flag $arg"
  41                                exit 1
  42                        fi
  43                        new="$rev"
  44                        if [ -f "$GIT_DIR/refs/heads/$arg" ]; then
  45                                branch="$arg"
  46                        fi
  47                elif rev=$(git-rev-parse --verify "$arg^{tree}" 2>/dev/null)
  48                then
  49                        # checking out selected paths from a tree-ish.
  50                        new="$rev"
  51                        branch=
  52                else
  53                        new=
  54                        branch=
  55                        set x "$arg" "$@"
  56                        shift
  57                fi
  58                break
  59                ;;
  60    esac
  61done
  62
  63# The behaviour of the command with and without explicit path
  64# parameters is quite different.
  65#
  66# Without paths, we are checking out everything in the work tree,
  67# possibly switching branches.  This is the traditional behaviour.
  68#
  69# With paths, we are _never_ switching branch, but checking out
  70# the named paths from either index (when no rev is given),
  71# or the named tree-ish (when rev is given).
  72
  73if test "$#" -ge 1
  74then
  75        if test '' != "$newbranch$force"
  76        then
  77                die "updating paths and switching branches or forcing are incompatible."
  78        fi
  79        if test '' != "$new"
  80        then
  81                # from a specific tree-ish; note that this is for
  82                # rescuing paths and is never meant to remove what
  83                # is not in the named tree-ish.
  84                git-ls-tree -r "$new" "$@" |
  85                git-update-index --index-info || exit $?
  86        fi
  87        git-checkout-index -f -u -- "$@"
  88        exit $?
  89else
  90        # Make sure we did not fall back on $arg^{tree} codepath
  91        # since we are not checking out from an arbitrary tree-ish,
  92        # but switching branches.
  93        if test '' != "$new"
  94        then
  95                git-rev-parse --verify "$new^{commit}" >/dev/null 2>&1 ||
  96                die "Cannot switch branch to a non-commit."
  97        fi
  98fi
  99
 100[ -z "$new" ] && new=$old
 101
 102# If we don't have an old branch that we're switching to,
 103# and we don't have a new branch name for the target we
 104# are switching to, then we'd better just be checking out
 105# what we already had
 106
 107[ -z "$branch$newbranch" ] &&
 108        [ "$new" != "$old" ] &&
 109        die "git checkout: you need to specify a new branch name"
 110
 111if [ "$force" ]
 112then
 113    git-read-tree --reset $new &&
 114        git-checkout-index -q -f -u -a
 115else
 116    git-update-index --refresh >/dev/null
 117    git-read-tree -m -u $old $new
 118fi
 119
 120# 
 121# Switch the HEAD pointer to the new branch if it we
 122# checked out a branch head, and remove any potential
 123# old MERGE_HEAD's (subsequent commits will clearly not
 124# be based on them, since we re-set the index)
 125#
 126if [ "$?" -eq 0 ]; then
 127        if [ "$newbranch" ]; then
 128                leading=`expr "refs/heads/$newbranch" : '\(.*\)/'` &&
 129                mkdir -p "$GIT_DIR/$leading" &&
 130                echo $new >"$GIT_DIR/refs/heads/$newbranch" || exit
 131                branch="$newbranch"
 132        fi
 133        [ "$branch" ] &&
 134        GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD "refs/heads/$branch"
 135        rm -f "$GIT_DIR/MERGE_HEAD"
 136else
 137        exit 1
 138fi