git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch
@ 2007-03-29  8:02 Junio C Hamano
  2007-03-29 10:44 ` Xavier Maillard
  2007-03-31  0:11 ` Jakub Narebski
  0 siblings, 2 replies; 8+ messages in thread
From: Junio C Hamano @ 2007-03-29  8:02 UTC (permalink / raw)
  To: git

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@cox.net>
---
 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

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch
  2007-03-29  8:02 [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch Junio C Hamano
@ 2007-03-29 10:44 ` Xavier Maillard
  2007-03-29 17:10   ` Alex Riesen
  2007-03-31  0:11 ` Jakub Narebski
  1 sibling, 1 reply; 8+ messages in thread
From: Xavier Maillard @ 2007-03-29 10:44 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

   This allows you to detach your HEAD and place it at such a

       $ git checkout -d master

Hum, excuse my ignorance, but can you explain what exactly could
be a use case of this ?

Xavier

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch
  2007-03-29 10:44 ` Xavier Maillard
@ 2007-03-29 17:10   ` Alex Riesen
  2007-03-29 20:54     ` Xavier Maillard
  0 siblings, 1 reply; 8+ messages in thread
From: Alex Riesen @ 2007-03-29 17:10 UTC (permalink / raw)
  To: Xavier Maillard; +Cc: Junio C Hamano, git

Xavier Maillard, Thu, Mar 29, 2007 12:44:42 +0200:
>    This allows you to detach your HEAD and place it at such a
> 
>        $ git checkout -d master
> 
> Hum, excuse my ignorance, but can you explain what exactly could
> be a use case of this ?

A throw-away or an experimental work. A commit importer which cares
about the branch it commits on: to update the branch reference only
when it has reached a stable state.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch
  2007-03-29 17:10   ` Alex Riesen
@ 2007-03-29 20:54     ` Xavier Maillard
  0 siblings, 0 replies; 8+ messages in thread
From: Xavier Maillard @ 2007-03-29 20:54 UTC (permalink / raw)
  To: Alex Riesen; +Cc: junkio, git


   A throw-away or an experimental work. A commit importer which cares
   about the branch it commits on: to update the branch reference only
   when it has reached a stable state.

Hum, yes, I see. Thank you.

Xavier

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch
  2007-03-29  8:02 [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch Junio C Hamano
  2007-03-29 10:44 ` Xavier Maillard
@ 2007-03-31  0:11 ` Jakub Narebski
  2007-03-31 14:55   ` Xavier Maillard
  1 sibling, 1 reply; 8+ messages in thread
From: Jakub Narebski @ 2007-03-31  0:11 UTC (permalink / raw)
  To: git

Junio C Hamano wrote:

> 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

What about

      $ git checkout master^0

trick to force detaching?

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch
  2007-03-31  0:11 ` Jakub Narebski
@ 2007-03-31 14:55   ` Xavier Maillard
  2007-04-04  0:11     ` Junio C Hamano
  0 siblings, 1 reply; 8+ messages in thread
From: Xavier Maillard @ 2007-03-31 14:55 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git


   > 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

   What about

	 $ git checkout master^0

   trick to force detaching?

I love this idea.

Xavier

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch
  2007-03-31 14:55   ` Xavier Maillard
@ 2007-04-04  0:11     ` Junio C Hamano
  2007-04-04  1:55       ` Linus Torvalds
  0 siblings, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2007-04-04  0:11 UTC (permalink / raw)
  To: Xavier Maillard; +Cc: Jakub Narebski, Linus Torvalds, git

Xavier Maillard <zedek@gnu.org> writes:

>    > 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
>
>    What about
>
> 	 $ git checkout master^0
>
>    trick to force detaching?
>
> I love this idea.

Could anybody remind me why we have the "new != old" check here?

diff --git a/git-checkout.sh b/git-checkout.sh
index a7390e8..573a3c0 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -170,7 +170,7 @@ describe_detached_head () {
 	}
 }
 
-if test -z "$branch$newbranch" && test "$new" != "$old"
+if test -z "$branch$newbranch"
 then
 	detached="$new"
 	if test -n "$oldbranch" && test -z "$quiet"

I think I do not need an explicit -d option if we just remove
that second test.  It is coming from an ancient commit 91dcdfd3,
and I _think_ it was to prevent something like:

	git-checkout-script v2.6.12^0

from succeeding, while allowing

	git-checkout-script HEAD^0

to be a no-op (as it happens to be naming the same commit).

commit 91dcdfd3b5331d955cfb60edf8930f1b5c142905
Author: Linus Torvalds <torvalds@g5.osdl.org>
Date:   Mon Jul 11 20:44:20 2005 -0700

    Make "git checkout" create new branches on demand

diff --git a/git-checkout-script b/git-checkout-script
index 48e1da9..7e70338 100755
--- a/git-checkout-script
+++ b/git-checkout-script
@@ -5,10 +5,19 @@ old=$(git-rev-parse HEAD)
 ...
@@ -32,6 +41,16 @@ while [ "$#" != "0" ]; do
 done
 [ -z "$new" ] && new=$old
 
+#
+# If we don't have an old branch that we're switching to,
+# and we don't have a new branch name for the target we
+# are switching to, then we'd better just be checking out
+# what we already had
+#
+[ -z "$branch$newbranch" ] &&
+	[ "$new" != "$old" ] &&
+	die "git checkout: you need to specify a new branch name"
+
 if [ "$force" ]
 then
     git-read-tree --reset $new &&
@@ -47,6 +66,10 @@ fi
 ...

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch
  2007-04-04  0:11     ` Junio C Hamano
@ 2007-04-04  1:55       ` Linus Torvalds
  0 siblings, 0 replies; 8+ messages in thread
From: Linus Torvalds @ 2007-04-04  1:55 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Xavier Maillard, Jakub Narebski, git



On Tue, 3 Apr 2007, Junio C Hamano wrote:
> 
> Could anybody remind me why we have the "new != old" check here?

Afaik, it's just so that you can do

	git checkout -f

without having it complain. And I think it just comes from the earlier:

	[ -z "$new" ] && new=$old && new_name="$old_name"

that we did - ie without that it would incorrectly just overwrite the 
current working tree with the new commit, but not actually do the "git 
reset" part.

So without that check, the way things used to work (*before* detached 
heads), if you were to have done

	git checkout <some-random-head>

it would have screwed up the current branch horribly.

With detached heads, I don't think it's needed.

		Linus

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2007-04-04  1:55 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-29  8:02 [PATCH] checkout -d: explicitly detach HEAD even when switching to the tip of a branch Junio C Hamano
2007-03-29 10:44 ` Xavier Maillard
2007-03-29 17:10   ` Alex Riesen
2007-03-29 20:54     ` Xavier Maillard
2007-03-31  0:11 ` Jakub Narebski
2007-03-31 14:55   ` Xavier Maillard
2007-04-04  0:11     ` Junio C Hamano
2007-04-04  1:55       ` Linus Torvalds

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).