[PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



You cannot currently checkout the tip of an existing branch
without moving to the branch.

This allows you to detach your HEAD and place it at such a
commit, with:

    $ git checkout -d master

Signed-off-by: Junio C Hamano <junkio@xxxxxxx>
---
 Documentation/git-checkout.txt |    6 +++-
 git-checkout.sh                |   18 +++++++++--
 t/t7201-co.sh                  |   63 +++++++++++++++++++++++++++++++++++++++-
 3 files changed, 81 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index f5b2d50..d00eeaa 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -8,7 +8,7 @@ git-checkout - Checkout and switch to a branch
 SYNOPSIS
 --------
 [verse]
-'git-checkout' [-q] [-f] [-b [--track | --no-track] <new_branch> [-l]] [-m] [<branch>]
+'git-checkout' [-q] [-f] [-b [--track | --no-track] <new_branch> [-l] | -d] [-m] [<branch>]
 'git-checkout' [<tree-ish>] <paths>...
 
 DESCRIPTION
@@ -61,6 +61,10 @@ OPTIONS
 	all changes to made the branch ref, enabling use of date
 	based sha1 expressions such as "<branchname>@{yesterday}".
 
+-d::
+	Explicitly ask to detach HEAD, even when named revision
+	to switch to is at the tip of a branch.
+
 -m::
 	If you have local modifications to one or more files that
 	are different between the current branch and the branch to
diff --git a/git-checkout.sh b/git-checkout.sh
index a7390e8..e551443 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-USAGE='[-q] [-f] [-b <new_branch>] [-m] [<branch>] [<paths>...]'
+USAGE='[-q] [-f] [-b <new_branch> | -d] [-m] [<branch>] [<paths>...]'
 SUBDIRECTORY_OK=Sometimes
 . git-sh-setup
 require_work_tree
@@ -17,6 +17,7 @@ newbranch=
 newbranch_log=
 merge=
 quiet=
+explicit_detach=
 LF='
 '
 while [ "$#" != "0" ]; do
@@ -39,6 +40,9 @@ while [ "$#" != "0" ]; do
 	"--track"|"--no-track")
 		track="$arg"
 		;;
+	-d)
+		explicit_detach=1
+		;;
 	"-f")
 		force=1
 		;;
@@ -94,6 +98,11 @@ case "$newbranch,$track" in
 	die "git checkout: --track and --no-track require -b"
 esac
 
+case "$newbranch$explicit_detach" in
+11)
+	die "git checkout: -d and -b are incompatible"
+esac
+
 case "$force$merge" in
 11)
 	die "git checkout: -f and -m are incompatible"
@@ -117,7 +126,7 @@ then
 		hint="
 Did you intend to checkout '$@' which can not be resolved as commit?"
 	fi
-	if test '' != "$newbranch$force$merge"
+	if test '' != "$newbranch$force$merge$explicit_detach"
 	then
 		die "git checkout: updating paths is incompatible with switching branches/forcing$hint"
 	fi
@@ -170,7 +179,8 @@ describe_detached_head () {
 	}
 }
 
-if test -z "$branch$newbranch" && test "$new" != "$old"
+if test -z "$branch$newbranch" && test "$new" != "$old" ||
+   test -n "$explicit_detach"
 then
 	detached="$new"
 	if test -n "$oldbranch" && test -z "$quiet"
@@ -254,7 +264,7 @@ if [ "$?" -eq 0 ]; then
 		git-branch $track $newbranch_log "$newbranch" "$new_name" || exit
 		branch="$newbranch"
 	fi
-	if test -n "$branch"
+	if test -n "$branch" && test -z "$explicit_detach"
 	then
 		GIT_DIR="$GIT_DIR" git-symbolic-ref -m "checkout: moving to $branch" HEAD "refs/heads/$branch"
 		if test -n "$quiet"
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 867bbd2..caa04f9 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -3,7 +3,20 @@
 # Copyright (c) 2006 Junio C Hamano
 #
 
-test_description='git-checkout tests.'
+test_description='git-checkout tests.
+
+Creates master, forks renamer and side branches from it.
+Test switching across them.
+
+  ! [master] Initial A one, A two
+   * [renamer] Renamer R one->uno, M two
+    ! [side] Side M one, D two, A three
+  ---
+    + [side] Side M one, D two, A three
+   *  [renamer] Renamer R one->uno, M two
+  +*+ [master] Initial A one, A two
+
+'
 
 . ./test-lib.sh
 
@@ -129,4 +142,52 @@ test_expect_success 'checkout -m with merge conflict' '
 	! test -s current
 '
 
+test_expect_success 'checkout to detach HEAD' '
+
+	git checkout -f renamer && git clean &&
+	git checkout renamer^ &&
+	H=$(git rev-parse --verify HEAD) &&
+	M=$(git show-ref -s --verify refs/heads/master) &&
+	test "z$H" = "z$M" &&
+	if git symbolic-ref HEAD >/dev/null 2>&1
+	then
+		echo "OOPS, HEAD is still symbolic???"
+		false
+	else
+		: happy
+	fi
+'
+
+test_expect_success 'checkout to detach HEAD with explicit -d' '
+
+	git checkout -f master && git clean &&
+	git checkout -d renamer^ &&
+	H=$(git rev-parse --verify HEAD) &&
+	M=$(git show-ref -s --verify refs/heads/master) &&
+	test "z$H" = "z$M" &&
+	if git symbolic-ref HEAD >/dev/null 2>&1
+	then
+		echo "OOPS, HEAD is still symbolic???"
+		false
+	else
+		: happy
+	fi
+'
+
+test_expect_success 'checkout to detach HEAD with explicit -d' '
+
+	git checkout -f master && git clean &&
+	git checkout -d &&
+	H=$(git rev-parse --verify HEAD) &&
+	M=$(git show-ref -s --verify refs/heads/master) &&
+	test "z$H" = "z$M" &&
+	if git symbolic-ref HEAD >/dev/null 2>&1
+	then
+		echo "OOPS, HEAD is still symbolic???"
+		false
+	else
+		: happy
+	fi
+'
+
 test_done
-- 
1.5.1.rc3.1.ga429d


-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]