1#!/bin/sh 2. git-sh-setup|| die "Not a git archive" 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" 15shift 16case"$arg"in 17"-b") 18 newbranch="$1" 19shift 20[-z"$newbranch"] && 21 die "git checkout: -b needs a branch name" 22[-e"$GIT_DIR/refs/heads/$newbranch"] && 23 die "git checkout: branch$newbranchalready 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--) 31break 32;; 33-*) 34 usage 35;; 36*) 37ifrev=$(git-rev-parse --verify "$arg^0" 2>/dev/null) 38then 39if[-z"$rev"];then 40echo"unknown flag$arg" 41exit1 42fi 43 new="$rev" 44if[-f"$GIT_DIR/refs/heads/$arg"];then 45 branch="$arg" 46fi 47elifrev=$(git-rev-parse --verify "$arg^{tree}" 2>/dev/null) 48then 49# checking out selected paths from a tree-ish. 50 new="$rev" 51 branch= 52else 53 new= 54 branch= 55set x "$arg""$@" 56shift 57fi 58break 59;; 60esac 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 73iftest"$#"-ge1 74then 75iftest''!="$newbranch$force" 76then 77 die "updating paths and switching branches or forcing are incompatible." 78fi 79iftest''!="$new" 80then 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 $? 86fi 87 git-checkout-index -f -u --"$@" 88exit $? 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. 93iftest''!="$new" 94then 95 git-rev-parse --verify"$new^{commit}">/dev/null 2>&1|| 96 die "Cannot switch branch to a non-commit." 97fi 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["$?"-eq0];then 127if["$newbranch"];then 128 leading=`expr "refs/heads/$newbranch" : '\(.*\)/'`&& 129mkdir-p"$GIT_DIR/$leading"&& 130echo$new>"$GIT_DIR/refs/heads/$newbranch"||exit 131 branch="$newbranch" 132fi 133["$branch"] && 134 GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD "refs/heads/$branch" 135rm-f"$GIT_DIR/MERGE_HEAD" 136else 137exit1 138fi