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""$@"| 85sed-ne's/^\([0-7]*\) blob \(.*\)$/\1 \2/p'| 86 git-update-index --index-info||exit $? 87fi 88 git-checkout-index -f -u --"$@" 89exit $? 90else 91# Make sure we did not fall back on $arg^{tree} codepath 92# since we are not checking out from an arbitrary tree-ish, 93# but switching branches. 94iftest''!="$new" 95then 96 git-rev-parse --verify"$new^{commit}">/dev/null 2>&1|| 97 die "Cannot switch branch to a non-commit." 98fi 99fi 100 101[-z"$new"] && new=$old 102 103# If we don't have an old branch that we're switching to, 104# and we don't have a new branch name for the target we 105# are switching to, then we'd better just be checking out 106# what we already had 107 108[-z"$branch$newbranch"] && 109["$new"!="$old"] && 110 die "git checkout: you need to specify a new branch name" 111 112if["$force"] 113then 114 git-read-tree --reset$new&& 115 git-checkout-index -q -f -u -a 116else 117 git-update-index --refresh>/dev/null 118 git-read-tree -m -u$old $new 119fi 120 121# 122# Switch the HEAD pointer to the new branch if it we 123# checked out a branch head, and remove any potential 124# old MERGE_HEAD's (subsequent commits will clearly not 125# be based on them, since we re-set the index) 126# 127if["$?"-eq0];then 128if["$newbranch"];then 129 leading=`expr "refs/heads/$newbranch" : '\(.*\)/'`&& 130mkdir-p"$GIT_DIR/$leading"&& 131echo$new>"$GIT_DIR/refs/heads/$newbranch"||exit 132 branch="$newbranch" 133fi 134["$branch"] && 135 GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD "refs/heads/$branch" 136rm-f"$GIT_DIR/MERGE_HEAD" 137else 138exit1 139fi