From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thomas Rast Subject: [PATCH/RFC v3 6/6] checkout: implement '@{-N}' and '-' special abbreviations Date: Sat, 17 Jan 2009 04:30:11 +0100 Message-ID: <1232163011-20088-7-git-send-email-trast@student.ethz.ch> References: <1232163011-20088-1-git-send-email-trast@student.ethz.ch> <1232163011-20088-2-git-send-email-trast@student.ethz.ch> <1232163011-20088-3-git-send-email-trast@student.ethz.ch> <1232163011-20088-4-git-send-email-trast@student.ethz.ch> <1232163011-20088-5-git-send-email-trast@student.ethz.ch> <1232163011-20088-6-git-send-email-trast@student.ethz.ch> Cc: Junio C Hamano , Johannes Schindelin , Johannes Sixt , Johan Herland To: git@vger.kernel.org X-From: git-owner@vger.kernel.org Sat Jan 17 04:32:09 2009 Return-path: Envelope-to: gcvg-git-2@gmane.org Received: from vger.kernel.org ([209.132.176.167]) by lo.gmane.org with esmtp (Exim 4.50) id 1LO1up-0006IU-Ge for gcvg-git-2@gmane.org; Sat, 17 Jan 2009 04:32:07 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754444AbZAQDaV (ORCPT ); Fri, 16 Jan 2009 22:30:21 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753988AbZAQDaT (ORCPT ); Fri, 16 Jan 2009 22:30:19 -0500 Received: from xsmtp0.ethz.ch ([82.130.70.14]:5404 "EHLO XSMTP0.ethz.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753773AbZAQDaL (ORCPT ); Fri, 16 Jan 2009 22:30:11 -0500 Received: from xfe0.d.ethz.ch ([82.130.124.40]) by XSMTP0.ethz.ch with Microsoft SMTPSVC(6.0.3790.3959); Sat, 17 Jan 2009 04:30:08 +0100 Received: from localhost.localdomain ([84.75.148.62]) by xfe0.d.ethz.ch over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959); Sat, 17 Jan 2009 04:30:08 +0100 X-Mailer: git-send-email 1.6.1.315.g92577 In-Reply-To: <1232163011-20088-6-git-send-email-trast@student.ethz.ch> In-Reply-To: <7v8wpcs38c.fsf@gitster.siamese.dyndns.org> References: <7v8wpcs38c.fsf@gitster.siamese.dyndns.org> X-OriginalArrivalTime: 17 Jan 2009 03:30:08.0430 (UTC) FILETIME=[E578FCE0:01C97853] Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Archived-At: Checks if the branch to be checked out is either '@{-N}' or the special shorthand '-' for '@{-1}' (i.e. the last checked out branch). If so, we take it to mean the branch name, not the corresponding SHA, so that we check out an attached HEAD on that branch. Signed-off-by: Thomas Rast --- Documentation/git-checkout.txt | 4 +++ builtin-checkout.c | 15 ++++++++++- t/t2012-checkout-last.sh | 50 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100755 t/t2012-checkout-last.sh diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 9cd5151..3bccffa 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -133,6 +133,10 @@ the conflicted merge in the specified paths. + When this parameter names a non-branch (but still a valid commit object), your HEAD becomes 'detached'. ++ +As a special case, the "`@\{-N\}`" syntax for the N-th last branch +checks out the branch (instead of detaching). You may also specify +"`-`" which is synonymous with "`@\{-1\}`". Detached HEAD diff --git a/builtin-checkout.c b/builtin-checkout.c index b5dd9c0..b0a101b 100644 --- a/builtin-checkout.c +++ b/builtin-checkout.c @@ -361,8 +361,16 @@ struct branch_info { static void setup_branch_path(struct branch_info *branch) { struct strbuf buf = STRBUF_INIT; - strbuf_addstr(&buf, "refs/heads/"); - strbuf_addstr(&buf, branch->name); + int ret; + + if ((ret = interpret_nth_last_branch(branch->name, &buf)) + && ret == strlen(branch->name)) { + branch->name = xstrdup(buf.buf); + strbuf_splice(&buf, 0, 0, "refs/heads/", 11); + } else { + strbuf_addstr(&buf, "refs/heads/"); + strbuf_addstr(&buf, branch->name); + } branch->path = strbuf_detach(&buf, NULL); } @@ -671,6 +679,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) arg = argv[0]; has_dash_dash = (argc > 1) && !strcmp(argv[1], "--"); + if (!strcmp(arg, "-")) + arg = "@{-1}"; + if (get_sha1(arg, rev)) { if (has_dash_dash) /* case (1) */ die("invalid reference: %s", arg); diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh new file mode 100755 index 0000000..320f6eb --- /dev/null +++ b/t/t2012-checkout-last.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +test_description='checkout can switch to last branch' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo hello >world && + git add world && + git commit -m initial && + git branch other && + echo "hello again" >>world && + git add world && + git commit -m second +' + +test_expect_success '"checkout -" does not work initially' ' + test_must_fail git checkout - +' + +test_expect_success 'first branch switch' ' + git checkout other +' + +test_expect_success '"checkout -" switches back' ' + git checkout - && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master" +' + +test_expect_success '"checkout -" switches forth' ' + git checkout - && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/other" +' + +test_expect_success 'detach HEAD' ' + git checkout $(git rev-parse HEAD) +' + +test_expect_success '"checkout -" attaches again' ' + git checkout - && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/other" +' + +test_expect_success '"checkout -" detaches again' ' + git checkout - && + test "z$(git rev-parse HEAD)" = "z$(git rev-parse other)" && + test_must_fail git symbolic-ref HEAD +' + +test_done -- 1.6.1.315.g92577