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