From: Jonathan Nieder <jrnieder@gmail.com>
To: Jeff King <peff@peff.net>
Cc: Junio C Hamano <gitster@pobox.com>,
Sverre Rabbelier <srabbelier@gmail.com>,
Martin von Zweigbergk <martin.von.zweigbergk@gmail.com>,
git@vger.kernel.org
Subject: [PATCH/WIP] checkout: introduce --detach synonym for "git checkout foo^{commit}"
Date: Mon, 7 Feb 2011 18:52:53 -0600 [thread overview]
Message-ID: <20110208005238.GB24340@elie> (raw)
In-Reply-To: <20110207234526.GA28336@sigill.intra.peff.net>
From: Junio C Hamano <gitster@pobox.com>
For example, one might use this when making a temporary merge to
test that two topics work well together.
Patch by Junio, tests from Jeff King.
Suggested-by: Jeff King <peff@peff.net>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
Jeff King wrote:
> Jonathan, do you want to roll all of these up into a single patch?
Okay, here it is. Two of the new tests fail. :)
Documentation/git-checkout.txt | 13 +++++-
builtin/checkout.c | 8 +++-
t/t2020-checkout-detach.sh | 89 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 107 insertions(+), 3 deletions(-)
create mode 100755 t/t2020-checkout-detach.sh
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 22d3611..d162117 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -9,6 +9,7 @@ SYNOPSIS
--------
[verse]
'git checkout' [-q] [-f] [-m] [<branch>]
+'git checkout' [-q] [-f] [-m] [--detach] [<commit>]
'git checkout' [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>]
'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
'git checkout' --patch [<tree-ish>] [--] [<paths>...]
@@ -22,9 +23,10 @@ branch.
'git checkout' [<branch>]::
'git checkout' -b|-B <new_branch> [<start point>]::
+'git checkout' [--detach] [<commit>]::
This form switches branches by updating the index, working
- tree, and HEAD to reflect the specified branch.
+ tree, and HEAD to reflect the specified branch or commit.
+
If `-b` is given, a new branch is created as if linkgit:git-branch[1]
were called and then checked out; in this case you can
@@ -115,6 +117,13 @@ explicitly give a name with '-b' in such a case.
Create the new branch's reflog; see linkgit:git-branch[1] for
details.
+--detach::
+ Rather than checking out a branch to work on it, check out a
+ commit for inspection and discardable experiments.
+ This is the default behavior of "git checkout <commit>" when
+ <commit> is not a branch name. See the "DETACHED HEAD" section
+ below for details.
+
--orphan::
Create a new 'orphan' branch, named <new_branch>, started from
<start_point> and switch to it. The first commit made on this
@@ -204,7 +213,7 @@ leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.
-Detached HEAD
+DETACHED HEAD
-------------
It is sometimes useful to be able to 'checkout' a commit that is
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 953abdd..526abb9 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -685,6 +685,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
char *conflict_style = NULL;
int patch_mode = 0;
int dwim_new_local_branch = 1;
+ int force_detach = 0;
struct option options[] = {
OPT__QUIET(&opts.quiet),
OPT_STRING('b', NULL, &opts.new_branch, "branch",
@@ -692,6 +693,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
OPT_STRING('B', NULL, &opts.new_branch_force, "branch",
"create/reset and checkout a branch"),
OPT_BOOLEAN('l', NULL, &opts.new_branch_log, "create reflog for new branch"),
+ OPT_BOOLEAN(0, "detach", &force_detach, "detach the HEAD at named commit"),
OPT_SET_INT('t', "track", &opts.track, "set upstream info for new branch",
BRANCH_TRACK_EXPLICIT),
OPT_STRING(0, "orphan", &opts.new_orphan_branch, "new branch", "new unparented branch"),
@@ -726,6 +728,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
if (opts.new_branch && opts.new_branch_force)
die("-B cannot be used with -b");
+ if ((opts.new_branch || opts.new_orphan_branch) && force_detach)
+ die("--detach cannot be used with -b/-B/--orphan");
+
/* copy -B over to -b, so that we can just check the latter */
if (opts.new_branch_force)
opts.new_branch = opts.new_branch_force;
@@ -834,7 +839,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
new.name = arg;
setup_branch_path(&new);
- if (check_ref_format(new.path) == CHECK_REF_FORMAT_OK &&
+ if (!force_detach &&
+ check_ref_format(new.path) == CHECK_REF_FORMAT_OK &&
resolve_ref(new.path, branch_rev, 1, NULL))
hashcpy(rev, branch_rev);
else
diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh
new file mode 100755
index 0000000..e57f253
--- /dev/null
+++ b/t/t2020-checkout-detach.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+test_description='checkout into detached HEAD state'
+. ./test-lib.sh
+
+check_detached () {
+ test_must_fail git symbolic-ref -q HEAD >/dev/null
+}
+
+check_not_detached () {
+ git symbolic-ref -q HEAD >/dev/null
+}
+
+reset () {
+ git checkout master &&
+ check_not_detached
+}
+
+test_expect_success 'setup' '
+ test_commit one &&
+ test_commit two &&
+ git branch branch &&
+ git tag tag
+'
+
+test_expect_success 'checkout branch does not detach' '
+ reset &&
+ git checkout branch &&
+ check_not_detached
+'
+
+test_expect_success 'checkout tag detaches' '
+ reset &&
+ git checkout tag &&
+ check_detached
+'
+
+test_expect_success 'checkout branch by full name detaches' '
+ reset &&
+ git checkout refs/heads/branch &&
+ check_detached
+'
+
+test_expect_success 'checkout non-ref detaches' '
+ reset &&
+ git checkout branch^ &&
+ check_detached
+'
+
+test_expect_success 'checkout ref^0 detaches' '
+ reset &&
+ git checkout branch^0 &&
+ check_detached
+'
+
+test_expect_success 'checkout --detach detaches' '
+ reset &&
+ git checkout --detach branch &&
+ check_detached
+'
+
+test_expect_failure 'checkout --detach without branch name' '
+ reset &&
+ git checkout --detach &&
+ check_detached
+'
+
+test_expect_failure 'checkout --detach errors out for extra argument' '
+ reset &&
+ git checkout master &&
+ test_expect_code 129 git checkout --detach tag nonsense &&
+ check_not_detached
+'
+
+test_expect_success 'checkout --detached and -b are incompatible' '
+ check_not_detached &&
+ test_must_fail git checkout --detach -b newbranch tag &&
+ check_not_detached
+'
+
+test_expect_success 'checkout --detach moves HEAD' '
+ reset &&
+ git checkout one &&
+ git checkout --detach two &&
+ git diff --exit-code HEAD &&
+ git diff --exit-code two
+'
+
+test_done
--
1.7.4
next prev parent reply other threads:[~2011-02-08 0:53 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-07 11:01 [1.8.0] git checkout refs/heads/foo checks out branch foo Martin von Zweigbergk
2011-02-07 20:53 ` Junio C Hamano
2011-02-07 20:59 ` Jeff King
2011-02-07 21:36 ` Sverre Rabbelier
2011-02-07 22:00 ` Jonathan Nieder
2011-02-07 23:37 ` Junio C Hamano
2011-02-07 23:45 ` Jeff King
2011-02-08 0:01 ` Jonathan Nieder
2011-02-08 0:28 ` Jeff King
2011-02-08 0:31 ` Martin von Zweigbergk
2011-02-08 0:52 ` Jonathan Nieder [this message]
2011-02-08 0:55 ` [PATCH/WIP] checkout: introduce --detach synonym for "git checkout foo^{commit}" Jonathan Nieder
2011-02-08 10:26 ` [PATCH v2 0/3] " Jonathan Nieder
2011-02-08 10:29 ` [PATCH 1/3] checkout: split off a function to peel away branchname arg Jonathan Nieder
2011-02-08 10:32 ` [PATCH 2/3] checkout: introduce --detach synonym for "git checkout foo^{commit}" Jonathan Nieder
2011-02-08 10:34 ` [PATCH 3/3] checkout: rearrange update_refs_for_switch for clarity Jonathan Nieder
2011-02-07 21:11 ` [1.8.0] git checkout refs/heads/foo checks out branch foo Heiko Voigt
2011-02-08 0:22 ` Martin von Zweigbergk
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110208005238.GB24340@elie \
--to=jrnieder@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=martin.von.zweigbergk@gmail.com \
--cc=peff@peff.net \
--cc=srabbelier@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).