{"thread":{"id":"17786","subject":"[PATCH] teach the new \"@{-1} syntax to \"git branch\"","startedAt":"2009-02-14T07:08:05Z","lastAt":"2009-02-27T06:49:39Z","messageCount":21,"participants":["Junio C Hamano","Jay Soffian","Johannes Schindelin","Nanako Shiraishi","Deskin Miller"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"104603","messageId":"7v4oyxzeay.fsf@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":null,"subject":"[PATCH] teach the new \"@{-1} syntax to \"git branch\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-14T07:08:05Z","receivedAt":"2009-02-14T07:08:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This teaches the new \"@{-1} syntax to refer to the previous branch to \"git\nbranch\".  After looking at somebody's faulty patch series on a topic\nbranch too long, if you decide it is not worth merging, you can just say:\n\n    $ git checkout master\n    $ git branch -D @{-1}\n\nto get rid of it without having to type the name of the topic you now hate\nso much for wasting a lot of your time.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n branch.c         |   19 ++++++++++++++-----\n builtin-branch.c |   31 +++++++++++++++++++------------\n 2 files changed, 33 insertions(+), 17 deletions(-)\n\ndiff --git a/branch.c b/branch.c\nindex b1ac837..1f00e44 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -103,14 +103,22 @@ void create_branch(const char *head,\n \tstruct ref_lock *lock;\n \tstruct commit *commit;\n \tunsigned char sha1[20];\n-\tchar *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20];\n+\tchar *real_ref, msg[PATH_MAX + 20];\n+\tstruct strbuf ref = STRBUF_INIT;\n \tint forcing = 0;\n+\tint len;\n \n-\tsnprintf(ref, sizeof ref, \"refs/heads/%s\", name);\n-\tif (check_ref_format(ref))\n+\tlen = strlen(name);\n+\tif (interpret_nth_last_branch(name, &ref) != len) {\n+\t\tstrbuf_reset(&ref);\n+\t\tstrbuf_add(&ref, name, len);\n+\t}\n+\tstrbuf_splice(&ref, 0, 0, \"refs/heads/\", 11);\n+\n+\tif (check_ref_format(ref.buf))\n \t\tdie(\"'%s' is not a valid branch name.\", name);\n \n-\tif (resolve_ref(ref, sha1, 1, NULL)) {\n+\tif (resolve_ref(ref.buf, sha1, 1, NULL)) {\n \t\tif (!force)\n \t\t\tdie(\"A branch named '%s' already exists.\", name);\n \t\telse if (!is_bare_repository() && !strcmp(head, name))\n@@ -142,7 +150,7 @@ void create_branch(const char *head,\n \t\tdie(\"Not a valid branch point: '%s'.\", start_name);\n \thashcpy(sha1, commit->object.sha1);\n \n-\tlock = lock_any_ref_for_update(ref, NULL, 0);\n+\tlock = lock_any_ref_for_update(ref.buf, NULL, 0);\n \tif (!lock)\n \t\tdie(\"Failed to lock ref for update: %s.\", strerror(errno));\n \n@@ -162,6 +170,7 @@ void create_branch(const char *head,\n \tif (write_ref_sha1(lock, sha1, msg) < 0)\n \t\tdie(\"Failed to write ref: %s.\", strerror(errno));\n \n+\tstrbuf_release(&ref);\n \tfree(real_ref);\n }\n \ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 56a1971..504a981 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -99,6 +99,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)\n \tconst char *fmt, *remote;\n \tint i;\n \tint ret = 0;\n+\tstruct strbuf bname = STRBUF_INIT;\n \n \tswitch (kinds) {\n \tcase REF_REMOTE_BRANCH:\n@@ -119,20 +120,25 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)\n \t\tif (!head_rev)\n \t\t\tdie(\"Couldn't look up commit object for HEAD\");\n \t}\n-\tfor (i = 0; i < argc; i++) {\n-\t\tif (kinds == REF_LOCAL_BRANCH && !strcmp(head, argv[i])) {\n+\tfor (i = 0; i < argc; i++, strbuf_release(&bname)) {\n+\t\tint len = strlen(argv[i]);\n+\n+\t\tif (interpret_nth_last_branch(argv[i], &bname) != len)\n+\t\t\tstrbuf_add(&bname, argv[i], len);\n+\n+\t\tif (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {\n \t\t\terror(\"Cannot delete the branch '%s' \"\n-\t\t\t\t\"which you are currently on.\", argv[i]);\n+\t\t\t      \"which you are currently on.\", bname.buf);\n \t\t\tret = 1;\n \t\t\tcontinue;\n \t\t}\n \n \t\tfree(name);\n \n-\t\tname = xstrdup(mkpath(fmt, argv[i]));\n+\t\tname = xstrdup(mkpath(fmt, bname.buf));\n \t\tif (!resolve_ref(name, sha1, 1, NULL)) {\n \t\t\terror(\"%sbranch '%s' not found.\",\n-\t\t\t\t\tremote, argv[i]);\n+\t\t\t\t\tremote, bname.buf);\n \t\t\tret = 1;\n \t\t\tcontinue;\n \t\t}\n@@ -152,22 +158,23 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)\n \t\tif (!force &&\n \t\t    !in_merge_bases(rev, &head_rev, 1)) {\n \t\t\terror(\"The branch '%s' is not an ancestor of \"\n-\t\t\t\t\"your current HEAD.\\n\"\n-\t\t\t\t\"If you are sure you want to delete it, \"\n-\t\t\t\t\"run 'git branch -D %s'.\", argv[i], argv[i]);\n+\t\t\t      \"your current HEAD.\\n\"\n+\t\t\t      \"If you are sure you want to delete it, \"\n+\t\t\t      \"run 'git branch -D %s'.\", bname.buf, bname.buf);\n \t\t\tret = 1;\n \t\t\tcontinue;\n \t\t}\n \n \t\tif (delete_ref(name, sha1, 0)) {\n \t\t\terror(\"Error deleting %sbranch '%s'\", remote,\n-\t\t\t       argv[i]);\n+\t\t\t      bname.buf);\n \t\t\tret = 1;\n \t\t} else {\n \t\t\tstruct strbuf buf = STRBUF_INIT;\n-\t\t\tprintf(\"Deleted %sbranch %s (%s).\\n\", remote, argv[i],\n-\t\t\t\tfind_unique_abbrev(sha1, DEFAULT_ABBREV));\n-\t\t\tstrbuf_addf(&buf, \"branch.%s\", argv[i]);\n+\t\t\tprintf(\"Deleted %sbranch %s (%s).\\n\", remote,\n+\t\t\t       bname.buf,\n+\t\t\t       find_unique_abbrev(sha1, DEFAULT_ABBREV));\n+\t\t\tstrbuf_addf(&buf, \"branch.%s\", bname.buf);\n \t\t\tif (git_config_rename_section(buf.buf, NULL) < 0)\n \t\t\t\twarning(\"Update of config-file failed\");\n \t\t\tstrbuf_release(&buf);\n-- \n1.6.2.rc0.80.ge11dd\n"},{"id":"104604","messageId":"76718490902132311j5add87bcpb103c951a8192b05@mail.gmail.com","threadId":"17786","inReplyTo":"7v4oyxzeay.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] teach the new \"@{-1} syntax to \"git branch\"","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2009-02-14T07:11:41Z","receivedAt":"2009-02-14T07:11:41Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Sat, Feb 14, 2009 at 2:08 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> This teaches the new \"@{-1} syntax to refer to the previous branch to \"git\n> branch\".  After looking at somebody's faulty patch series on a topic\n> branch too long, if you decide it is not worth merging, you can just say:\n>\n>    $ git checkout master\n>    $ git branch -D @{-1}\n>\n> to get rid of it without having to type the name of the topic you now hate\n> so much for wasting a lot of your time.\n\nI hope I'm not the person who motivated this new syntax. :-)\n\nj.\n"},{"id":"104606","messageId":"7vzlgpxz4g.fsf@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"76718490902132311j5add87bcpb103c951a8192b05@mail.gmail.com","subject":"Re: [PATCH] teach the new \"@{-1} syntax to \"git branch\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-14T07:21:19Z","receivedAt":"2009-02-14T07:21:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jay Soffian <jaysoffian@gmail.com> writes:\n\n> On Sat, Feb 14, 2009 at 2:08 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> This teaches the new \"@{-1} syntax to refer to the previous branch to \"git\n>> branch\".  After looking at somebody's faulty patch series on a topic\n>> branch too long, if you decide it is not worth merging, you can just say:\n>>\n>>    $ git checkout master\n>>    $ git branch -D @{-1}\n>>\n>> to get rid of it without having to type the name of the topic you now hate\n>> so much for wasting a lot of your time.\n>\n> I hope I'm not the person who motivated this new syntax. :-)\n\nDon't worry.\n\nThe @{-1} syntax was added long before you started getting hyperactive\nthis round, but it will be in 1.6.2 and has been advertised as \"usable\nanywhere you can use a branch name\", but in reality it is not.\n\nI have been fixing up various places to match the reality with the claim.\nI am making \"git merge @{-1}\" work now.\n"},{"id":"104618","messageId":"7vwsbtuzo8.fsf_-_@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"7vzlgpxz4g.fsf@gitster.siamese.dyndns.org","subject":"[PATCH v2 1/2] Teach the \"@{-1} syntax to \"git branch\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-14T09:37:43Z","receivedAt":"2009-02-14T09:37:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This teaches the new \"@{-1} syntax to refer to the previous branch to \"git\nbranch\".  After looking at somebody's faulty patch series on a topic\nbranch too long, if you decide it is not worth merging, you can just say:\n\n    $ git checkout master\n    $ git branch -D @{-1}\n\nto get rid of it without having to type the name of the topic you now hate\nso much for wasting a lot of your time.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n * Now comes with test.\n branch.c            |   19 ++++++++++++++-----\n builtin-branch.c    |   31 +++++++++++++++++++------------\n t/t0100-previous.sh |   26 ++++++++++++++++++++++++++\n 3 files changed, 59 insertions(+), 17 deletions(-)\n create mode 100755 t/t0100-previous.sh\n\ndiff --git a/branch.c b/branch.c\nindex b1ac837..1f00e44 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -103,14 +103,22 @@ void create_branch(const char *head,\n \tstruct ref_lock *lock;\n \tstruct commit *commit;\n \tunsigned char sha1[20];\n-\tchar *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20];\n+\tchar *real_ref, msg[PATH_MAX + 20];\n+\tstruct strbuf ref = STRBUF_INIT;\n \tint forcing = 0;\n+\tint len;\n \n-\tsnprintf(ref, sizeof ref, \"refs/heads/%s\", name);\n-\tif (check_ref_format(ref))\n+\tlen = strlen(name);\n+\tif (interpret_nth_last_branch(name, &ref) != len) {\n+\t\tstrbuf_reset(&ref);\n+\t\tstrbuf_add(&ref, name, len);\n+\t}\n+\tstrbuf_splice(&ref, 0, 0, \"refs/heads/\", 11);\n+\n+\tif (check_ref_format(ref.buf))\n \t\tdie(\"'%s' is not a valid branch name.\", name);\n \n-\tif (resolve_ref(ref, sha1, 1, NULL)) {\n+\tif (resolve_ref(ref.buf, sha1, 1, NULL)) {\n \t\tif (!force)\n \t\t\tdie(\"A branch named '%s' already exists.\", name);\n \t\telse if (!is_bare_repository() && !strcmp(head, name))\n@@ -142,7 +150,7 @@ void create_branch(const char *head,\n \t\tdie(\"Not a valid branch point: '%s'.\", start_name);\n \thashcpy(sha1, commit->object.sha1);\n \n-\tlock = lock_any_ref_for_update(ref, NULL, 0);\n+\tlock = lock_any_ref_for_update(ref.buf, NULL, 0);\n \tif (!lock)\n \t\tdie(\"Failed to lock ref for update: %s.\", strerror(errno));\n \n@@ -162,6 +170,7 @@ void create_branch(const char *head,\n \tif (write_ref_sha1(lock, sha1, msg) < 0)\n \t\tdie(\"Failed to write ref: %s.\", strerror(errno));\n \n+\tstrbuf_release(&ref);\n \tfree(real_ref);\n }\n \ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 56a1971..504a981 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -99,6 +99,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)\n \tconst char *fmt, *remote;\n \tint i;\n \tint ret = 0;\n+\tstruct strbuf bname = STRBUF_INIT;\n \n \tswitch (kinds) {\n \tcase REF_REMOTE_BRANCH:\n@@ -119,20 +120,25 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)\n \t\tif (!head_rev)\n \t\t\tdie(\"Couldn't look up commit object for HEAD\");\n \t}\n-\tfor (i = 0; i < argc; i++) {\n-\t\tif (kinds == REF_LOCAL_BRANCH && !strcmp(head, argv[i])) {\n+\tfor (i = 0; i < argc; i++, strbuf_release(&bname)) {\n+\t\tint len = strlen(argv[i]);\n+\n+\t\tif (interpret_nth_last_branch(argv[i], &bname) != len)\n+\t\t\tstrbuf_add(&bname, argv[i], len);\n+\n+\t\tif (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {\n \t\t\terror(\"Cannot delete the branch '%s' \"\n-\t\t\t\t\"which you are currently on.\", argv[i]);\n+\t\t\t      \"which you are currently on.\", bname.buf);\n \t\t\tret = 1;\n \t\t\tcontinue;\n \t\t}\n \n \t\tfree(name);\n \n-\t\tname = xstrdup(mkpath(fmt, argv[i]));\n+\t\tname = xstrdup(mkpath(fmt, bname.buf));\n \t\tif (!resolve_ref(name, sha1, 1, NULL)) {\n \t\t\terror(\"%sbranch '%s' not found.\",\n-\t\t\t\t\tremote, argv[i]);\n+\t\t\t\t\tremote, bname.buf);\n \t\t\tret = 1;\n \t\t\tcontinue;\n \t\t}\n@@ -152,22 +158,23 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)\n \t\tif (!force &&\n \t\t    !in_merge_bases(rev, &head_rev, 1)) {\n \t\t\terror(\"The branch '%s' is not an ancestor of \"\n-\t\t\t\t\"your current HEAD.\\n\"\n-\t\t\t\t\"If you are sure you want to delete it, \"\n-\t\t\t\t\"run 'git branch -D %s'.\", argv[i], argv[i]);\n+\t\t\t      \"your current HEAD.\\n\"\n+\t\t\t      \"If you are sure you want to delete it, \"\n+\t\t\t      \"run 'git branch -D %s'.\", bname.buf, bname.buf);\n \t\t\tret = 1;\n \t\t\tcontinue;\n \t\t}\n \n \t\tif (delete_ref(name, sha1, 0)) {\n \t\t\terror(\"Error deleting %sbranch '%s'\", remote,\n-\t\t\t       argv[i]);\n+\t\t\t      bname.buf);\n \t\t\tret = 1;\n \t\t} else {\n \t\t\tstruct strbuf buf = STRBUF_INIT;\n-\t\t\tprintf(\"Deleted %sbranch %s (%s).\\n\", remote, argv[i],\n-\t\t\t\tfind_unique_abbrev(sha1, DEFAULT_ABBREV));\n-\t\t\tstrbuf_addf(&buf, \"branch.%s\", argv[i]);\n+\t\t\tprintf(\"Deleted %sbranch %s (%s).\\n\", remote,\n+\t\t\t       bname.buf,\n+\t\t\t       find_unique_abbrev(sha1, DEFAULT_ABBREV));\n+\t\t\tstrbuf_addf(&buf, \"branch.%s\", bname.buf);\n \t\t\tif (git_config_rename_section(buf.buf, NULL) < 0)\n \t\t\t\twarning(\"Update of config-file failed\");\n \t\t\tstrbuf_release(&buf);\ndiff --git a/t/t0100-previous.sh b/t/t0100-previous.sh\nnew file mode 100755\nindex 0000000..db51b42\n--- /dev/null\n+++ b/t/t0100-previous.sh\n@@ -0,0 +1,26 @@\n+#!/bin/sh\n+\n+test_description='previous branch syntax @{-n}'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'branch -d @{-1}' '\n+\ttest_commit A &&\n+\tgit checkout -b junk &&\n+\tgit checkout - &&\n+\ttest \"$(git symbolic-ref HEAD)\" = refs/heads/master &&\n+\tgit branch -d @{-1} &&\n+\ttest_must_fail git rev-parse --verify refs/heads/junk\n+'\n+\n+test_expect_success 'branch -d @{-12} when there is not enough switches yet' '\n+\tgit reflog expire --expire=now &&\n+\tgit checkout -b junk2 &&\n+\tgit checkout - &&\n+\ttest \"$(git symbolic-ref HEAD)\" = refs/heads/master &&\n+\ttest_must_fail git branch -d @{-12} &&\n+\tgit rev-parse --verify refs/heads/master\n+'\n+\n+test_done\n+\n-- \n1.6.2.rc0.80.ge11dd\n"},{"id":"104619","messageId":"7vskmhuzla.fsf_-_@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"7vzlgpxz4g.fsf@gitster.siamese.dyndns.org","subject":"[PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-14T09:39:29Z","receivedAt":"2009-02-14T09:39:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"1.6.2 will have @{-1} syntax advertised as \"usable anywhere you can use\na branch name\".  However, \"git merge @{-1}\" did not work.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n * I know \"show-branch @{-1} HEAD\" does not dereference @{-1}, but I\n   suspect there may be many others.\n\n builtin-merge.c     |   15 ++++++++++++---\n t/t0100-previous.sh |   23 +++++++++++++++++++++++\n 2 files changed, 35 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex 885fad9..6d2160d 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -356,9 +356,14 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \tstruct object *remote_head;\n \tunsigned char branch_head[20], buf_sha[20];\n \tstruct strbuf buf = STRBUF_INIT;\n+\tstruct strbuf bname = STRBUF_INIT;\n \tconst char *ptr;\n \tint len, early;\n \n+\tlen = strlen(remote);\n+\tif (interpret_nth_last_branch(remote, &bname) == len)\n+\t\tremote = bname.buf;\n+\n \tmemset(branch_head, 0, sizeof(branch_head));\n \tremote_head = peel_to_type(remote, 0, NULL, OBJ_COMMIT);\n \tif (!remote_head)\n@@ -371,7 +376,7 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \tif (!hashcmp(remote_head->sha1, branch_head)) {\n \t\tstrbuf_addf(msg, \"%s\\t\\tbranch '%s' of .\\n\",\n \t\t\tsha1_to_hex(branch_head), remote);\n-\t\treturn;\n+\t\tgoto cleanup;\n \t}\n \n \t/* See if remote matches <name>^^^.. or <name>~<number> */\n@@ -411,7 +416,8 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \t\t\t\t    sha1_to_hex(remote_head->sha1),\n \t\t\t\t    truname.buf + 11,\n \t\t\t\t    (early ? \" (early part)\" : \"\"));\n-\t\t\treturn;\n+\t\t\tstrbuf_release(&truname);\n+\t\t\tgoto cleanup;\n \t\t}\n \t}\n \n@@ -432,10 +438,13 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \t\t\tstrbuf_remove(&line, ptr-line.buf+1, 13);\n \t\tstrbuf_addbuf(msg, &line);\n \t\tstrbuf_release(&line);\n-\t\treturn;\n+\t\tgoto cleanup;\n \t}\n \tstrbuf_addf(msg, \"%s\\t\\tcommit '%s'\\n\",\n \t\tsha1_to_hex(remote_head->sha1), remote);\n+cleanup:\n+\tstrbuf_release(&buf);\n+\tstrbuf_release(&bname);\n }\n \n static int git_merge_config(const char *k, const char *v, void *cb)\ndiff --git a/t/t0100-previous.sh b/t/t0100-previous.sh\nindex db51b42..315b9b3 100755\n--- a/t/t0100-previous.sh\n+++ b/t/t0100-previous.sh\n@@ -22,5 +22,28 @@ test_expect_success 'branch -d @{-12} when there is not enough switches yet' '\n \tgit rev-parse --verify refs/heads/master\n '\n \n+test_expect_success 'merge @{-1}' '\n+\tgit checkout A &&\n+\ttest_commit B &&\n+\tgit checkout A &&\n+\ttest_commit C &&\n+\tgit branch -f master B &&\n+\tgit branch -f other &&\n+\tgit checkout other &&\n+\tgit checkout master &&\n+\tgit merge @{-1} &&\n+\tgit cat-file commit HEAD | grep \"Merge branch '\\''other'\\''\"\n+'\n+\n+test_expect_success 'merge @{-1} when there is not enough switches yet' '\n+\tgit reflog expire --expire=now &&\n+\tgit checkout -f master &&\n+\tgit reset --hard B &&\n+\tgit branch -f other C &&\n+\tgit checkout other &&\n+\tgit checkout master &&\n+\ttest_must_fail git merge @{-12}\n+'\n+\n test_done\n \n-- \n1.6.2.rc0.80.ge11dd\n"},{"id":"104714","messageId":"alpine.DEB.1.00.0902142332210.10279@pacific.mpi-cbg.de","threadId":"17786","inReplyTo":"7vskmhuzla.fsf_-_@gitster.siamese.dyndns.org","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-14T22:52:42Z","receivedAt":"2009-02-14T22:52:42Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 14 Feb 2009, Junio C Hamano wrote:\n\n>  * I know \"show-branch @{-1} HEAD\" does not dereference @{-1}, but I\n>    suspect there may be many others.\n\nI scanned command-list.txt briefly, and could verify (by testing rather \nthan code inspection) that\n\n- bundle works as expected (thanks to dwim_ref()),\n\n- fast-export (like bundle, dwim_ref() makes it work),\n\n- so does filter-branch, thanks to rev-parse --symbolic-full-name \n  resolving @{-<n>} correctly,\n\n- log and reflog also substitute @{-<n>} by the branch name,\n\n- update-ref does _not_ interpret @{-<n>} as the branch name (which I \n  find okay, as update-ref is plumbing), but instead creates the file \n  '.git/@{-<n>}' (which I think is a bug).\n\nNow, show-branch indeed does not substitute the branch _name_, but \notherwise it works correctly, no?  And given the fact that show-branch \ndoes not substitute \"HEAD\" with the current branch name, either, I wonder \nif show-branch needs fixing at all.\n\nCiao,\nDscho\n"},{"id":"104720","messageId":"7vfxigqwsp.fsf@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"alpine.DEB.1.00.0902142332210.10279@pacific.mpi-cbg.de","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-15T02:05:42Z","receivedAt":"2009-02-15T02:05:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> - update-ref does _not_ interpret @{-<n>} as the branch name (which I \n>   find okay, as update-ref is plumbing), but instead creates the file \n>   '.git/@{-<n>}' (which I think is a bug).\n\nI do not think it make any sense for update-ref to expand @{-1} to the\nname of the last branch, as you end up creating a not-a-ref \".git/next\"\nand not \".git/refs/heads/next\".  It might be Ok to say that @{-1} expands\nto refs/heads followed by the name of the last branch only for this\nplumbing command, but such an inconsistency feels very wrong.\n\nThe particular plumbing command, following the example of recent loosening\nthe rule back to \"HEAD is allowed to point outside refs/heads/\", should be\nallowed to create anything that passes check_ref_format(), and perhaps bit\nmore because we would need to allow \".git/HEAD\".\n\n> Now, show-branch indeed does not substitute the branch _name_, but \n> otherwise it works correctly, no?\n> otherwise it works correctly, no?  And given the fact that show-branch \n> does not substitute \"HEAD\" with the current branch name, either,...\n\nThe tip commits come from get_sha1(), so obviously it would \"work\", but it\ndoes not show what branch it talks about.  HEAD is shown only when the\nuser says HEAD (e.g. \"git show-branch master HEAD\") so I do not see much\nsimilarity there.\n\nThe advertised new feature is that you can use the @{-1} syntax anywhere\nyou would use a branch name and it would work as if you typed the name of\nthe branch, so in that sense show-branch that shows @{-1} and does not\nshow the name of the branch is a bug.\n\nIt is the same thing for \"git-merge @{-1}\".  Sure, it would record a\ncorrect tree in the resulting commit, but without the fix it would say\n\"Merge branch @{-1}\" which is wrong and needs to be fixed.\n\nAnd no, \"update-ref @{-1}\" should not create \".git/next\" when you were on\n'next' the last time.  When you say \"update-ref next\", you may have typed\nthe four characters and that may look the same as the name of a branch,\nbut obviously the argument to the command does not *mean* the name of a\nbranch, so it falls outside the \"anywhere you would use a branch name\"\nrule.\n"},{"id":"104722","messageId":"7v63jcqvjh.fsf@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"7vfxigqwsp.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-15T02:32:50Z","receivedAt":"2009-02-15T02:32:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> The advertised new feature is that you can use the @{-1} syntax anywhere\n> you would use a branch name and it would work as if you typed the name of\n> the branch, so in that sense show-branch that shows @{-1} and does not\n> show the name of the branch is a bug.\n\nI've checked \"checkout -b new -t @{-1}\", too.  Just for completeness's\nsake.\n"},{"id":"104751","messageId":"20090215182405.6117@nanako3.lavabit.com","threadId":"17786","inReplyTo":"7vfxigqwsp.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Nanako Shiraishi","fromEmail":"nanako3@lavabit.com","sentAt":"2009-02-15T09:24:05Z","receivedAt":"2009-02-15T09:24:05Z","isPatch":true,"sender":{"key":"nanako3@lavabit.com","avatar":"https://gravatar.com/avatar/3777b9e201c5883a62b1a6fdf7c53f2d712d1d80989146063ea861e33aad72a8?d=mp&s=160"},"body":"Quoting Junio C Hamano <gitster@pobox.com>:\n\n> The tip commits come from get_sha1(), so obviously it would \"work\", but it\n> does not show what branch it talks about.  HEAD is shown only when the\n> user says HEAD (e.g. \"git show-branch master HEAD\") so I do not see much\n> similarity there.\n>\n> The advertised new feature is that you can use the @{-1} syntax anywhere\n> you would use a branch name and it would work as if you typed the name of\n> the branch, so in that sense show-branch that shows @{-1} and does not\n> show the name of the branch is a bug.\n>\n> It is the same thing for \"git-merge @{-1}\".  Sure, it would record a\n> correct tree in the resulting commit, but without the fix it would say\n> \"Merge branch @{-1}\" which is wrong and needs to be fixed.\n\nI am sorry, but I don't understand your logic.\n\n'git-merge' can merge any commit. The argument doesn't have to be a branch name. But it behaves differently when the argument is a branch name. Therefore, @{-1} syntax must behave in the same way as any branch name. I can understand that part.\n\nWhat I don't understand is your comments about 'git-show-branch'. It also takes any commits, not just branch names, and it's output doesn't seem to treat a branch name any specially from other commits.\n\nI think Johannes'es analogy with HEAD is correct.\n\n-- \nNanako Shiraishi\nhttp://ivory.ap.teacup.com/nanako3/\n"},{"id":"104754","messageId":"7vbpt4nhl2.fsf@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"20090215182405.6117@nanako3.lavabit.com","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-15T10:02:33Z","receivedAt":"2009-02-15T10:02:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nanako Shiraishi <nanako3@lavabit.com> writes:\n\n> What I don't understand is your comments about 'git-show-branch'. It\n> also takes any commits, not just branch names, and it's output doesn't\n> seem to treat a branch name any specially from other commits.\n>\n> I think Johannes'es analogy with HEAD is correct.\n\nI agree with you after thinking about it again; I stand corrected.\n"},{"id":"104760","messageId":"alpine.DEB.1.00.0902151212320.10279@pacific.mpi-cbg.de","threadId":"17786","inReplyTo":"7vfxigqwsp.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-15T11:21:44Z","receivedAt":"2009-02-15T11:21:44Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 14 Feb 2009, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > - update-ref does _not_ interpret @{-<n>} as the branch name (which I \n> >   find okay, as update-ref is plumbing), but instead creates the file \n> >   '.git/@{-<n>}' (which I think is a bug).\n> \n> I do not think it make any sense for update-ref to expand @{-1} to the\n> name of the last branch,\n\nAs I said, I find the behavior okay.\n\n> The particular plumbing command, following the example of recent \n> loosening the rule back to \"HEAD is allowed to point outside \n> refs/heads/\", should be allowed to create anything that passes \n> check_ref_format(), and perhaps bit more because we would need to allow \n> \".git/HEAD\".\n\nThat was what I was referring to when talking about a bug.\n\n> > Now, show-branch indeed does not substitute the branch _name_, but \n> > otherwise it works correctly, no?\n> > otherwise it works correctly, no?  And given the fact that show-branch \n> > does not substitute \"HEAD\" with the current branch name, either,...\n> \n> The tip commits come from get_sha1(), so obviously it would \"work\", but it\n> does not show what branch it talks about.  HEAD is shown only when the\n> user says HEAD (e.g. \"git show-branch master HEAD\") so I do not see much\n> similarity there.\n\nWell, it _is_ a substitution.  If you ask for \"HEAD\", you get \"HEAD\".  As \na new user, if passing \"@{-2}\" to show-branch would not show \"@{-2}\", but \nDWIM the branch name, I would expect, really, that passing \"HEAD\" does the \nsame sort of DWIMming for me.\n\nIn the name of consistency, I'd rather leave show-branch as it is.\n\nHowever, IMO there is a much worse issue lurking: people might want to \n_know_ what \"@{-2}\" would expand to, _without_ switching branches.  At the \nmoment, I can only think of\n\n\tgit show -s --decorate --pretty=format:%d @{-2}\n\nwhich is\n\n- convoluted (I would not expect _any_ new user to think of this),\n\n- wrong (it shows all the refs that point to the commit, not only the one \n  we wanted to find out).\n\nAnd no, do not suggest using \"git rev-parse --symbolic-full-name @{-2}\", \nyou know exactly what I think of teaching new users plumbing, and you know \nI am right in this respect.\n\nCiao,\nDscho\n"},{"id":"104901","messageId":"7v1vtzf234.fsf@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"alpine.DEB.1.00.0902151212320.10279@pacific.mpi-cbg.de","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-16T04:16:47Z","receivedAt":"2009-02-16T04:16:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> In the name of consistency, I'd rather leave show-branch as it is.\n\nYes, Nana explained why I was wrong on this one.\n\n> However, IMO there is a much worse issue lurking: people might want to \n> _know_ what \"@{-2}\" would expand to, _without_ switching branches.\n\n\"git branch --history\" anyone?\n"},{"id":"104930","messageId":"alpine.DEB.1.00.0902161140160.10279@pacific.mpi-cbg.de","threadId":"17786","inReplyTo":"7v1vtzf234.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-16T10:41:00Z","receivedAt":"2009-02-16T10:41:00Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 15 Feb 2009, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > However, IMO there is a much worse issue lurking: people might want to \n> > _know_ what \"@{-2}\" would expand to, _without_ switching branches.\n> \n> \"git branch --history\" anyone?\n\nFor a moment, you had me convinced it already exists, and I only \nunderstood after \"git grep history builtin-branch.c\" came up empty.\n\n;-)\n\nCiao,\nDscho\n"},{"id":"104970","messageId":"76718490902160840t2d6af366jf14ced67d125040c@mail.gmail.com","threadId":"17786","inReplyTo":"alpine.DEB.1.00.0902161140160.10279@pacific.mpi-cbg.de","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2009-02-16T16:40:13Z","receivedAt":"2009-02-16T16:40:13Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Mon, Feb 16, 2009 at 5:41 AM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n>> \"git branch --history\" anyone?\n>\n> For a moment, you had me convinced it already exists, and I only\n> understood after \"git grep history builtin-branch.c\" came up empty.\n\nAnd I've labeled that mail as TODO. :-)\n\nj.\n"},{"id":"106276","messageId":"7v8wnuys44.fsf@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"alpine.DEB.1.00.0902161140160.10279@pacific.mpi-cbg.de","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-26T00:11:23Z","receivedAt":"2009-02-26T00:11:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> Hi,\n>\n> On Sun, 15 Feb 2009, Junio C Hamano wrote:\n>\n>> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>> \n>> > However, IMO there is a much worse issue lurking: people might want to \n>> > _know_ what \"@{-2}\" would expand to, _without_ switching branches.\n>> \n>> \"git branch --history\" anyone?\n>\n> For a moment, you had me convinced it already exists, and I only \n> understood after \"git grep history builtin-branch.c\" came up empty.\n>\n> ;-)\n\n$ git rev-parse --symbolic-full-name @{-24}\n\nseem to work for this purpose ;-)\n"},{"id":"106311","messageId":"alpine.DEB.1.00.0902261118140.6258@intel-tinevez-2-302","threadId":"17786","inReplyTo":"7v8wnuys44.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-26T10:18:57Z","receivedAt":"2009-02-26T10:18:57Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 25 Feb 2009, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > On Sun, 15 Feb 2009, Junio C Hamano wrote:\n> >\n> >> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> >> \n> >> > However, IMO there is a much worse issue lurking: people might want \n> >> > to _know_ what \"@{-2}\" would expand to, _without_ switching \n> >> > branches.\n> >> \n> >> \"git branch --history\" anyone?\n> >\n> > For a moment, you had me convinced it already exists, and I only \n> > understood after \"git grep history builtin-branch.c\" came up empty.\n> >\n> > ;-)\n> \n> $ git rev-parse --symbolic-full-name @{-24}\n> \n> seem to work for this purpose ;-)\n\nAFAIR I mentioned that command, together with a reminder that teaching \nregular Git users plumbing commands is harmful.\n\nCiao,\nDscho\n"},{"id":"106392","messageId":"86d4c5e00902262027y13b19eb7nf89a45e83b986801@mail.gmail.com","threadId":"17786","inReplyTo":"alpine.DEB.1.00.0902142332210.10279@pacific.mpi-cbg.de","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Deskin Miller","fromEmail":"deskinm@gmail.com","sentAt":"2009-02-27T04:27:05Z","receivedAt":"2009-02-27T04:27:05Z","isPatch":true,"sender":{"key":"deskinm@gmail.com","avatar":null},"body":"On Sat, Feb 14, 2009 at 17:52, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> I scanned command-list.txt briefly, and could verify (by testing rather\n> than code inspection) that\n>\n> - bundle works as expected (thanks to dwim_ref()),\n>\n> - fast-export (like bundle, dwim_ref() makes it work),\n>\n> - so does filter-branch, thanks to rev-parse --symbolic-full-name\n>  resolving @{-<n>} correctly,\n>\n> - log and reflog also substitute @{-<n>} by the branch name,\n>\n> - update-ref does _not_ interpret @{-<n>} as the branch name (which I\n>  find okay, as update-ref is plumbing), but instead creates the file\n>  '.git/@{-<n>}' (which I think is a bug).\n>\n\nI did 'git branch -M @{-1}' yesterday and ended up renaming my branch\nto refs/heads/@{-1}.  Personally my usage felt like it should work\n(but of course I think that); curious to know what others think, if\nthis is a bug.\n\nDeskin Miller\n"},{"id":"106393","messageId":"7veixkpi4a.fsf@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"86d4c5e00902262027y13b19eb7nf89a45e83b986801@mail.gmail.com","subject":"Re: [PATCH v2 2/2] Teach @{-1} to git merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-27T05:24:21Z","receivedAt":"2009-02-27T05:24:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Deskin Miller <deskinm@gmail.com> writes:\n\n> I did 'git branch -M @{-1}' yesterday and ended up renaming my branch\n> to refs/heads/@{-1}.  Personally my usage felt like it should work\n> (but of course I think that); curious to know what others think, if\n> this is a bug.\n\nThe @{-n} notation is supposed to be usable anywhere you would write a\nbranch name and should behave as if you wrote the name itself.  And 'git\nbranch -M <name> [<name>]' does expect a branch name, not a random\nextended SHA-1 expression.\n\nI'd say it is a bug.\n"},{"id":"106394","messageId":"7vvdqwo1fe.fsf_-_@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"7veixkpi4a.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] git-branch: a detached HEAD and branch called HEAD are different","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-27T06:10:13Z","receivedAt":"2009-02-27T06:10:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"While on a detached HEAD, builtin-branch.c passed string \"HEAD\" around in\nthe varilable \"head\" that held the current branch name.  This did not\nallow you to distinguish between a local branch whose name is \"HEAD\" and a\ndetached HEAD.\n\nAllow the variable to contain NULL when the HEAD is detached.  The change\nis primarily to protect !strcmp(head, name) to see if we are try to\nmanipulate the current branch with \"head &&\"; we won't be futzing with the\ncurrent branch when the HEAD is detached by definition.\n\nCreating a local branch \"HEAD\" is not useful at all, but if you managed to\ncreate one by mistake, \"git branch -d HEAD\" couldn't delete it while your\nHEAD is detached, due to this bug.\n\nOne of the functions, rename_branch(), even expected NULL to signal this\nsituation, to prevent \"git branch -m othername\" while on detached HEAD,\nand this change incidentally fixes this unrelated bug.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * I wasn't personally very much interested in these \"C-rewrites\" of\n   Porcelains, and I have never looked at the implementation very\n   carefully, but some parts of them are disgustingly crappy, and I am\n   finding these inconsistencies after looking at them only for 5\n   minutes.  Oh well...\n\n   Anyway, this is a preparatory clean-up.\n\n branch.c         |    2 +-\n builtin-branch.c |    8 +++++---\n 2 files changed, 6 insertions(+), 4 deletions(-)\n\ndiff --git a/branch.c b/branch.c\nindex 1f00e44..e287eab 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -121,7 +121,7 @@ void create_branch(const char *head,\n \tif (resolve_ref(ref.buf, sha1, 1, NULL)) {\n \t\tif (!force)\n \t\t\tdie(\"A branch named '%s' already exists.\", name);\n-\t\telse if (!is_bare_repository() && !strcmp(head, name))\n+\t\telse if (!is_bare_repository() && head && !strcmp(head, name))\n \t\t\tdie(\"Cannot force update the current branch.\");\n \t\tforcing = 1;\n \t}\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 504a981..c34af27 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -126,7 +126,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)\n \t\tif (interpret_nth_last_branch(argv[i], &bname) != len)\n \t\t\tstrbuf_add(&bname, argv[i], len);\n \n-\t\tif (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {\n+\t\tif (kinds == REF_LOCAL_BRANCH && head && !strcmp(head, bname.buf)) {\n \t\t\terror(\"Cannot delete the branch '%s' \"\n \t\t\t      \"which you are currently on.\", bname.buf);\n \t\t\tret = 1;\n@@ -408,7 +408,7 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str\n \tfor (i = 0; i < ref_list.index; i++) {\n \t\tint current = !detached &&\n \t\t\t(ref_list.list[i].kind == REF_LOCAL_BRANCH) &&\n-\t\t\t!strcmp(ref_list.list[i].name, head);\n+\t\t\thead && !strcmp(ref_list.list[i].name, head);\n \t\tprint_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,\n \t\t\t       abbrev, current);\n \t}\n@@ -541,6 +541,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \thead = xstrdup(head);\n \tif (!strcmp(head, \"HEAD\")) {\n \t\tdetached = 1;\n+\t\thead = NULL;\n \t} else {\n \t\tif (prefixcmp(head, \"refs/heads/\"))\n \t\t\tdie(\"HEAD not found below refs/heads!\");\n@@ -561,7 +562,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \telse if (rename && (argc == 2))\n \t\trename_branch(argv[0], argv[1], rename > 1);\n \telse if (argc <= 2)\n-\t\tcreate_branch(head, argv[0], (argc == 2) ? argv[1] : head,\n+\t\tcreate_branch(head, argv[0],\n+\t\t\t      (argc == 2) ? argv[1] : head ? head : \"HEAD\",\n \t\t\t      force_create, reflog, track);\n \telse\n \t\tusage_with_options(builtin_branch_usage, options);\n"},{"id":"106395","messageId":"7vprh4o1bt.fsf_-_@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"7veixkpi4a.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] \"git branch -M @{-1}\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-27T06:12:22Z","receivedAt":"2009-02-27T06:12:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Earlier, we've taught \"git branch -d <name>\" that <name> is supposed to be\na branch name and not a random extended SHA-1.  \"git branch -m <name> [<name>]\" \nneeds to be taught the same.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-branch.c |   14 ++++++++++----\n 1 files changed, 10 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex c34af27..3f97838 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -425,21 +425,27 @@ static void rename_branch(const char *oldname, const char *newname, int force)\n \tif (!oldname)\n \t\tdie(\"cannot rename the current branch while not on any.\");\n \n-\tstrbuf_addf(&oldref, \"refs/heads/%s\", oldname);\n+\tif (interpret_nth_last_branch(oldname, &oldref) == strlen(oldname))\n+\t\tstrbuf_splice(&oldref, 0, 0, \"refs/heads/\", 11);\n+\telse\n+\t\tstrbuf_addf(&oldref, \"refs/heads/%s\", oldname);\n \n \tif (check_ref_format(oldref.buf))\n \t\tdie(\"Invalid branch name: %s\", oldref.buf);\n \n-\tstrbuf_addf(&newref, \"refs/heads/%s\", newname);\n+\tif (interpret_nth_last_branch(newname, &newref) == strlen(newname))\n+\t\tstrbuf_splice(&newref, 0, 0, \"refs/heads/\", 11);\n+\telse\n+\t\tstrbuf_addf(&newref, \"refs/heads/%s\", newname);\n \n \tif (check_ref_format(newref.buf))\n \t\tdie(\"Invalid branch name: %s\", newref.buf);\n \n \tif (resolve_ref(newref.buf, sha1, 1, NULL) && !force)\n-\t\tdie(\"A branch named '%s' already exists.\", newname);\n+\t\tdie(\"A branch named '%s' already exists.\", newref.buf + 11);\n \n \tstrbuf_addf(&logmsg, \"Branch: renamed %s to %s\",\n-\t\t oldref.buf, newref.buf);\n+\t\t    oldref.buf, newref.buf);\n \n \tif (rename_ref(oldref.buf, newref.buf, logmsg.buf))\n \t\tdie(\"Branch rename failed\");\n"},{"id":"106400","messageId":"7vljrsnzlo.fsf@gitster.siamese.dyndns.org","threadId":"17786","inReplyTo":"7vprh4o1bt.fsf_-_@gitster.siamese.dyndns.org","subject":"Re: [PATCH] \"git branch -M @{-1}\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-27T06:49:39Z","receivedAt":"2009-02-27T06:49:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Earlier, we've taught \"git branch -d <name>\" that <name> is supposed to be\n> a branch name and not a random extended SHA-1.  \"git branch -m <name> [<name>]\" \n> needs to be taught the same.\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  builtin-branch.c |   14 ++++++++++----\n>  1 files changed, 10 insertions(+), 4 deletions(-)\n>\n> diff --git a/builtin-branch.c b/builtin-branch.c\n> index c34af27..3f97838 100644\n> --- a/builtin-branch.c\n> +++ b/builtin-branch.c\n> @@ -425,21 +425,27 @@ static void rename_branch(const char *oldname, const char *newname, int force)\n>  \tif (!oldname)\n>  \t\tdie(\"cannot rename the current branch while not on any.\");\n>  \n> -\tstrbuf_addf(&oldref, \"refs/heads/%s\", oldname);\n> +\tif (interpret_nth_last_branch(oldname, &oldref) == strlen(oldname))\n> +\t\tstrbuf_splice(&oldref, 0, 0, \"refs/heads/\", 11);\n> +\telse\n> +\t\tstrbuf_addf(&oldref, \"refs/heads/%s\", oldname);\n\nA few comments on this patch.\n\n (1) I am actually very reluctant to queue this, or any unproven \"fix\"\n     that adds obscure codepath, for 1.6.2, this close to the final.  Most\n     likely I won't be queueing any more @{-n] fixes until 1.6.2 final and\n     defer them to 1.6.2.X series if necessary.\n\n (2) If we are to have full @{-n} support, and if we do not mind small\n     leaks, it would make more sense to introduce a leaky helper function\n     like this and use it everywhere:\n\n\tconst char *handle_branch_arg(const char *name)\n        {\n        \tstruct strbuf buf = STRBUF_INIT;\n\t\tsize_t len = strlen(name);\n                if (interpret_nth_last_branch(name, &buf) == len)\n\t\t\treturn strbuf_detach(&buf);\n\t\treturn name;\n\t}\n\n (3) I think this \"The argument could be previous branch name\" conversion\n     should be done only when the command is about local branch names\n     (i.e. when run without -r option), and the above codepath needs to be\n     protected with if (kinds == REF_LOCAL_BRANCH)\n"}]}