X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=git-checkout.sh;h=33f1e87c0c209b89eb785381db62d826818b602d;hb=0cae23467ada9b94210a0e770064841efea8ad40;hp=66e40b90ebfa8e65e9c42731203f10dde0424b8c;hpb=6de33478affbf252066cc5863add213ca5cdc13c;p=git.git diff --git a/git-checkout.sh b/git-checkout.sh index 66e40b90e..33f1e87c0 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -1,6 +1,6 @@ #!/bin/sh -USAGE='[-f] [-b ] [-m] [] [...]' +USAGE='[-q] [-f] [-b ] [-m] [] [...]' SUBDIRECTORY_OK=Sometimes . git-sh-setup require_work_tree @@ -12,9 +12,12 @@ new= new_name= force= branch= +track= newbranch= newbranch_log= merge= +quiet= +v=-v LF=' ' while [ "$#" != "0" ]; do @@ -32,7 +35,10 @@ while [ "$#" != "0" ]; do die "git checkout: we do not like '$newbranch' as a branch name." ;; "-l") - newbranch_log=1 + newbranch_log=-l + ;; + "--track"|"--no-track") + track="$arg" ;; "-f") force=1 @@ -40,6 +46,10 @@ while [ "$#" != "0" ]; do -m) merge=1 ;; + "-q") + quiet=1 + v= + ;; --) break ;; @@ -53,12 +63,13 @@ while [ "$#" != "0" ]; do echo "unknown flag $arg" exit 1 fi - new="$rev" new_name="$arg" if git-show-ref --verify --quiet -- "refs/heads/$arg" then + rev=$(git-rev-parse --verify "refs/heads/$arg^0") branch="$arg" fi + new="$rev" elif rev=$(git-rev-parse --verify "$arg^{tree}" 2>/dev/null) then # checking out selected paths from a tree-ish. @@ -81,6 +92,11 @@ while [ "$#" != "0" ]; do esac done +case "$newbranch,$track" in +,--*) + die "git checkout: --track and --no-track require -b" +esac + case "$force$merge" in 11) die "git checkout: -f and -m are incompatible" @@ -150,44 +166,41 @@ cd_to_toplevel detached= detach_warn= -if test -z "$branch$newbranch" && test "$new" != "$old" +describe_detached_head () { + test -n "$quiet" || { + printf >&2 "$1 " + GIT_PAGER= git log >&2 -1 --pretty=oneline --abbrev-commit "$2" + } +} + +if test -z "$branch$newbranch" && test "$new_name" != "$old_name" then detached="$new" - if test -n "$oldbranch" + if test -n "$oldbranch" && test -z "$quiet" then - detach_warn="warning: you are not on ANY branch anymore. -If you meant to create a new branch from the commit, you need -b to -associate a new branch with the wanted checkout. Example: - git checkout -b $arg" + detach_warn="Note: moving to \"$new_name\" which isn't a local branch +If you want to create a new branch from this checkout, you may do so +(now or later) by using -b with the checkout command again. Example: + git checkout -b " fi -elif test -z "$oldbranch" && test -n "$branch" +elif test -z "$oldbranch" && test "$new" != "$old" then - # Coming back... - if test -z "$force" - then - git show-ref -d -s | grep "$old" >/dev/null || { - echo >&2 \ -"You are not on any branch and switching to branch '$new_name' -may lose your changes. At this point, you can do one of two things: - (1) Decide it is Ok and say 'git checkout -f $new_name'; - (2) Start a new branch from the current commit, by saying - 'git checkout -b '. -Leaving your HEAD detached; not switching to branch '$new_name'." - exit 1; - } - fi + describe_detached_head 'Previous HEAD position was' "$old" fi if [ "X$old" = X ] then - echo >&2 "warning: You appear to be on a branch yet to be born." - echo >&2 "warning: Forcing checkout of $new_name." + if test -z "$quiet" + then + echo >&2 "warning: You appear to be on a branch yet to be born." + echo >&2 "warning: Forcing checkout of $new_name." + fi force=1 fi if [ "$force" ] then - git-read-tree --reset -u $new + git-read-tree $v --reset -u $new else git-update-index --refresh >/dev/null merge_error=$(git-read-tree -m -u --exclude-per-directory=.gitignore $old $new 2>&1) || ( @@ -198,24 +211,20 @@ else esac # Match the index to the working tree, and do a three-way. - git diff-files --name-only | git update-index --remove --stdin && + git diff-files --name-only | git update-index --remove --stdin && work=`git write-tree` && - git read-tree --reset -u $new && - git read-tree -m -u --aggressive --exclude-per-directory=.gitignore $old $new $work || - exit + git read-tree $v --reset -u $new || exit - if result=`git write-tree 2>/dev/null` - then - echo >&2 "Trivially automerged." - else - git merge-index -o git-merge-one-file -a - fi + eval GITHEAD_$new='${new_name:-${branch:-$new}}' && + eval GITHEAD_$work=local && + export GITHEAD_$new GITHEAD_$work && + git merge-recursive $old -- $new $work # Do not register the cleanly merged paths in the index yet. # this is not a real merge before committing, but just carrying # the working tree changes along. unmerged=`git ls-files -u` - git read-tree --reset $new + git read-tree $v --reset $new case "$unmerged" in '') ;; *) @@ -230,14 +239,14 @@ else exit 0 ) saved_err=$? - if test "$saved_err" = 0 + if test "$saved_err" = 0 && test -z "$quiet" then - test "$new" = "$old" || git diff-index --name-status "$new" + git diff-index --name-status "$new" fi (exit $saved_err) fi -# +# # Switch the HEAD pointer to the new branch if we # checked out a branch head, and remove any potential # old MERGE_HEAD's (subsequent commits will clearly not @@ -245,31 +254,30 @@ fi # if [ "$?" -eq 0 ]; then if [ "$newbranch" ]; then - if [ "$newbranch_log" ]; then - mkdir -p $(dirname "$GIT_DIR/logs/refs/heads/$newbranch") - touch "$GIT_DIR/logs/refs/heads/$newbranch" - fi - git-update-ref -m "checkout: Created from $new_name" "refs/heads/$newbranch" $new || exit + git-branch $track $newbranch_log "$newbranch" "$new_name" || exit branch="$newbranch" fi if test -n "$branch" then - GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD "refs/heads/$branch" + GIT_DIR="$GIT_DIR" git-symbolic-ref -m "checkout: moving to $branch" HEAD "refs/heads/$branch" + if test -n "$quiet" + then + true # nothing + elif test "refs/heads/$branch" = "$oldbranch" + then + echo >&2 "Already on branch \"$branch\"" + else + echo >&2 "Switched to${newbranch:+ a new} branch \"$branch\"" + fi elif test -n "$detached" then - # NEEDSWORK: we would want a command to detach the HEAD - # atomically, instead of this handcrafted command sequence. - # Perhaps: - # git update-ref --detach HEAD $new - # or something like that... - # - echo "$detached" >"$GIT_DIR/HEAD.new" && - mv "$GIT_DIR/HEAD.new" "$GIT_DIR/HEAD" || + git-update-ref --no-deref -m "checkout: moving to $arg" HEAD "$detached" || die "Cannot detach HEAD" if test -n "$detach_warn" then echo >&2 "$detach_warn" fi + describe_detached_head 'HEAD is now at' HEAD fi rm -f "$GIT_DIR/MERGE_HEAD" else