{"thread":{"id":"38629","subject":"[RFC/PATCH] branch: name detached HEAD analogous to status","startedAt":"2015-02-22T17:38:20Z","lastAt":"2015-03-06T20:23:55Z","messageCount":11,"participants":["Michael J Gruber","Junio C Hamano","Marc Branchaud"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"256481","messageId":"71fc137d8015f6e81ab91cfcbcad4ec0fa0dc3e6.1424626271.git.git@drmicha.warpmail.net","threadId":"38629","inReplyTo":null,"subject":"[RFC/PATCH] branch: name detached HEAD analogous to status","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2015-02-22T17:38:20Z","receivedAt":"2015-02-22T17:38:20Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"\"git status\" carefully names a detached HEAD \"at\" resp. \"from\" a rev or\nref depending on whether the detached HEAD has moved since. \"git branch\"\nalways uses \"from\", which can be confusing, because a status-aware user\nwould interpret this as moved detached HEAD.\n\nMake \"git branch\" use the same logic and wording.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n\nNotes:\n    The wording is still different:\n    \n    HEAD detached at %s\n    * (detached at %s)\n    \n    for status (line 1) resp. branch (line 2). Maybe it's worthwhile to use the\n    exact same string so that l10n output is guaranteed to be the same? E.g.\n    \n    a)\n    HEAD detached at %s\n    * (HEAD detached at %s)\n    \n    or\n    b)\n    HEAD (detached at %s)\n    * (detached at %s)\n    \n    In case b), \"git status\" strings would need to change, in case a)\n    only \"git branch\" strings which change anyway by this patch.\n\n builtin/branch.c         | 13 ++++++++++---\n t/t3203-branch-output.sh | 39 ++++++++++++++++++++++++++++++++++++++-\n 2 files changed, 48 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex d8949cb..be391ee 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -589,9 +589,16 @@ static char *get_head_description(void)\n \telse if (state.bisect_in_progress)\n \t\tstrbuf_addf(&desc, _(\"(no branch, bisect started on %s)\"),\n \t\t\t    state.branch);\n-\telse if (state.detached_from)\n-\t\tstrbuf_addf(&desc, _(\"(detached from %s)\"),\n-\t\t\t    state.detached_from);\n+\telse if (state.detached_from) {\n+\t\tunsigned char sha1[20];\n+\t\tif (!get_sha1(\"HEAD\", sha1) &&\n+\t\t    !hashcmp(sha1, state.detached_sha1))\n+\t\t\tstrbuf_addf(&desc, _(\"(detached at %s)\"),\n+\t\t\t\tstate.detached_from);\n+\t\telse\n+\t\t\tstrbuf_addf(&desc, _(\"(detached from %s)\"),\n+\t\t\t\tstate.detached_from);\n+\t}\n \telse\n \t\tstrbuf_addstr(&desc, _(\"(no branch)\"));\n \tfree(state.branch);\ndiff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh\nindex ba4f98e..aaff885 100755\n--- a/t/t3203-branch-output.sh\n+++ b/t/t3203-branch-output.sh\n@@ -96,7 +96,7 @@ test_expect_success 'git branch -v pattern does not show branch summaries' '\n \n test_expect_success 'git branch shows detached HEAD properly' '\n \tcat >expect <<EOF &&\n-* (detached from $(git rev-parse --short HEAD^0))\n+* (detached at $(git rev-parse --short HEAD^0))\n   branch-one\n   branch-two\n   master\n@@ -106,4 +106,41 @@ EOF\n \ttest_i18ncmp expect actual\n '\n \n+test_expect_success 'git branch shows detached HEAD properly after moving' '\n+\tcat >expect <<EOF &&\n+* (detached from $(git rev-parse --short HEAD))\n+  branch-one\n+  branch-two\n+  master\n+EOF\n+\tgit reset --hard HEAD^1 &&\n+\tgit branch >actual &&\n+\ttest_i18ncmp expect actual\n+'\n+\n+test_expect_success 'git branch shows detached HEAD properly from tag' '\n+\tcat >expect <<EOF &&\n+* (detached at fromtag)\n+  branch-one\n+  branch-two\n+  master\n+EOF\n+\tgit tag fromtag master &&\n+\tgit checkout fromtag &&\n+\tgit branch >actual &&\n+\ttest_i18ncmp expect actual\n+'\n+\n+test_expect_success 'git branch shows detached HEAD properly after moving from tag' '\n+\tcat >expect <<EOF &&\n+* (detached from fromtag)\n+  branch-one\n+  branch-two\n+  master\n+EOF\n+\tgit reset --hard HEAD^1 &&\n+\tgit branch >actual &&\n+\ttest_i18ncmp expect actual\n+'\n+\n test_done\n-- \n2.3.0.296.g32c87e1\n"},{"id":"256485","messageId":"xmqqa905wy43.fsf@gitster.dls.corp.google.com","threadId":"38629","inReplyTo":"71fc137d8015f6e81ab91cfcbcad4ec0fa0dc3e6.1424626271.git.git@drmicha.warpmail.net","subject":"Re: [RFC/PATCH] branch: name detached HEAD analogous to status","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-02-22T19:21:48Z","receivedAt":"2015-02-22T19:21:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> \"git status\" carefully names a detached HEAD \"at\" resp. \"from\" a rev or\n> ref depending on whether the detached HEAD has moved since. \"git branch\"\n> always uses \"from\", which can be confusing, because a status-aware user\n> would interpret this as moved detached HEAD.\n>\n> Make \"git branch\" use the same logic and wording.\n\nYeah, otherwise the user would wonder why sometimes the object name\nafter that \"from\" matches \"git rev-parse HEAD\" and sometimes does\nnot.\n\nIn order to make sure that it will be easy for us to maintain that\nthese two commands will keep using the same logic and wording after\nthis \"fix\" is applied, should this patch do a bit more?  Or is it\nworth doing that for such a small piece of code to be shared?\n\nThe following is a tangent and I do not think it is likely we would\ndo anything about it, but I wonder what value we give the end users\nby showing the \"from\" information, both in \"status\" and \"branch\" in\nthe first place.  When I am on a detached HEAD, I'd be doing one of\nthese three things:\n\n (1) I am on some kind of sequencing machinery (e.g. \"rebase -i\",\n     \"cherry-pick A..B\", or \"bisect\").  It does not matter to me at\n     all if I am at the same commit at which I started the sequenced\n     operations or the sequencing machinery has moved me one or more\n     commits along its planned course of action, or where the\n     original point the sequencing machinery detached the HEAD at.\n     I suspect that I would not use \"git status\" or \"git branch\" in\n     this mode anyway.\n\n (2) I am sight-seeing, starting with e.g. \"git checkout v2.0.0\",\n     and moving around with \"git checkout $some_other_commit\".  I'd\n     always see that I am \"at\" the commit I last checked out, so the\n     distinctions would not be even shown to me.\n\n (3) I am experimenting to fix or enhance an existing thing that is\n     meant to eventually hit a concrete branch, but I do not know if\n     the experiment would pan out. \"git checkout $topic~$n\" would be\n     to start from near the tip of that $topic ($n may often be 0\n     but not always) and then I would \"git commit\" my experiments.\n     When I assess my progress, I'd be interested in what I have\n     that is not in $topic and vice versa since I started that\n     experiment, so\n\n     $ git log ...$topic\n     $ git show-branch HEAD $topic\n\n     would be a lot more useful than having to learn \"where did I\n     detach\" from either \"status\" or \"branch\" and then do something\n     about that the abbreviated object name (like feeding it to\n     \"describe\" or \"log\").\n\nOf course, the decision to make the point the HEAD was originally\ndetached at is not an issue this patch introduces, but it makes me\nwonder if that existing \"at vs from\" logic is an overall win or a\nloss.\n"},{"id":"256500","messageId":"54EAE9D1.3090504@drmicha.warpmail.net","threadId":"38629","inReplyTo":"xmqqa905wy43.fsf@gitster.dls.corp.google.com","subject":"Re: [RFC/PATCH] branch: name detached HEAD analogous to status","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2015-02-23T08:50:25Z","receivedAt":"2015-02-23T08:50:25Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Junio C Hamano venit, vidit, dixit 22.02.2015 20:21:\n> Michael J Gruber <git@drmicha.warpmail.net> writes:\n> \n>> \"git status\" carefully names a detached HEAD \"at\" resp. \"from\" a rev or\n>> ref depending on whether the detached HEAD has moved since. \"git branch\"\n>> always uses \"from\", which can be confusing, because a status-aware user\n>> would interpret this as moved detached HEAD.\n>>\n>> Make \"git branch\" use the same logic and wording.\n> \n> Yeah, otherwise the user would wonder why sometimes the object name\n> after that \"from\" matches \"git rev-parse HEAD\" and sometimes does\n> not.\n> \n> In order to make sure that it will be easy for us to maintain that\n> these two commands will keep using the same logic and wording after\n> this \"fix\" is applied, should this patch do a bit more?  Or is it\n> worth doing that for such a small piece of code to be shared?\n\nYes, I guess I meant RFD when I meant RFC. If that consistency is deemed\nworthwhile it should at least be guaranteed by the tests, which the test\namendments somehow do, but better by a shared code in wt-status.c.\n\nThat could possibly be reused by the decorate code - which is how I came\nabout this: In order to decide about consistent HEAD decorations I\nchecked what we have and got confused by status vs. branch.\n\n> The following is a tangent and I do not think it is likely we would\n> do anything about it, but I wonder what value we give the end users\n> by showing the \"from\" information, both in \"status\" and \"branch\" in\n> the first place.  When I am on a detached HEAD, I'd be doing one of\n> these three things:\n> \n>  (1) I am on some kind of sequencing machinery (e.g. \"rebase -i\",\n>      \"cherry-pick A..B\", or \"bisect\").  It does not matter to me at\n>      all if I am at the same commit at which I started the sequenced\n>      operations or the sequencing machinery has moved me one or more\n>      commits along its planned course of action, or where the\n>      original point the sequencing machinery detached the HEAD at.\n>      I suspect that I would not use \"git status\" or \"git branch\" in\n>      this mode anyway.\n> \n>  (2) I am sight-seeing, starting with e.g. \"git checkout v2.0.0\",\n>      and moving around with \"git checkout $some_other_commit\".  I'd\n>      always see that I am \"at\" the commit I last checked out, so the\n>      distinctions would not be even shown to me.\n> \n>  (3) I am experimenting to fix or enhance an existing thing that is\n>      meant to eventually hit a concrete branch, but I do not know if\n>      the experiment would pan out. \"git checkout $topic~$n\" would be\n>      to start from near the tip of that $topic ($n may often be 0\n>      but not always) and then I would \"git commit\" my experiments.\n>      When I assess my progress, I'd be interested in what I have\n>      that is not in $topic and vice versa since I started that\n>      experiment, so\n> \n>      $ git log ...$topic\n>      $ git show-branch HEAD $topic\n> \n>      would be a lot more useful than having to learn \"where did I\n>      detach\" from either \"status\" or \"branch\" and then do something\n>      about that the abbreviated object name (like feeding it to\n>      \"describe\" or \"log\").\n> \n> Of course, the decision to make the point the HEAD was originally\n> detached at is not an issue this patch introduces, but it makes me\n> wonder if that existing \"at vs from\" logic is an overall win or a\n> loss.\n\nNot for you nor anyone who routinely detaches heads :)\n\nDespite HEAD reflog and delayed pruning and all that, \"detached HEAD\" is\na state the average user may feel slightly uncomfortable with, and may\nnot even have gotten into on purpose. \"git checkout tag\" and \"git\ncheckout remotebranch\" are very easy ways to get there, even \"git\ncheckout HEAD^1\" and such when mistaking \"checkout\" for \"reset\".\nTherefore, I think about that \"at/from\" as information (or rather: quick\nguesstimate) on two things:\n\n- How did I get there? (For this it might be better to say 'at/from\nHEAD^1' which was sha1\" rather than resolving that to a sha1 only. I\ndunno. Detached heads move so easily...)\n\n- Has something (that could get lost) happened since?\n\nWe take a quick and overly cautious approach to answering the 2nd\nquestion, of course.\n\nMaybe a \"git head\" command would be really a better place for all that\ninformation:\n\ngit head\n \"master\" or \"HEAD\" (on branch resp. detached state)\ngit head -v\n \"master at...\" or \"HEAD at ..., detached from/at...\"\ngit head -l\n list of sha1s of childless prunable commits from HEAD's reflog\ngit head -d|--detach\n alias for \"git checkout -detach HEAD\"\n\n(just brainstorming)\n\nMichael\n"},{"id":"256511","messageId":"54EB436E.9060106@xiplink.com","threadId":"38629","inReplyTo":"71fc137d8015f6e81ab91cfcbcad4ec0fa0dc3e6.1424626271.git.git@drmicha.warpmail.net","subject":"Re: [RFC/PATCH] branch: name detached HEAD analogous to status","fromName":"Marc Branchaud","fromEmail":"marcnarc@xiplink.com","sentAt":"2015-02-23T15:12:46Z","receivedAt":"2015-02-23T15:12:46Z","isPatch":true,"sender":{"key":"marcnarc@xiplink.com","avatar":"https://avatars.githubusercontent.com/u/14980203?v=4"},"body":"On 15-02-22 12:38 PM, Michael J Gruber wrote:\n> \"git status\" carefully names a detached HEAD \"at\" resp. \"from\" a rev or\n> ref depending on whether the detached HEAD has moved since. \"git branch\"\n> always uses \"from\", which can be confusing, because a status-aware user\n> would interpret this as moved detached HEAD.\n> \n> Make \"git branch\" use the same logic and wording.\n\nExcept that the wording in \"git branch\" is more correct, especially if the\ndetached HEAD contains new commits.\n\nIn other words, \"at\" is only correct if the detached HEAD matches the ref.\nIf the HEAD has other commits, it is no longer \"at\" that ref but instead it\nhas grown \"from\" it.\n\nBut even if the detached HEAD matches the ref, saying it came \"from\" that ref\n(with 0 extra commits) is still better than saying\ndetached-HEAD-with-extra-commits is \"at\" the ref.\n\n\t\tM.\n"},{"id":"256512","messageId":"54EB4579.3000103@xiplink.com","threadId":"38629","inReplyTo":"xmqqa905wy43.fsf@gitster.dls.corp.google.com","subject":"Re: [RFC/PATCH] branch: name detached HEAD analogous to status","fromName":"Marc Branchaud","fromEmail":"marcnarc@xiplink.com","sentAt":"2015-02-23T15:21:29Z","receivedAt":"2015-02-23T15:21:29Z","isPatch":true,"sender":{"key":"marcnarc@xiplink.com","avatar":"https://avatars.githubusercontent.com/u/14980203?v=4"},"body":"On 15-02-22 02:21 PM, Junio C Hamano wrote:\n> Michael J Gruber <git@drmicha.warpmail.net> writes:\n> \n>> \"git status\" carefully names a detached HEAD \"at\" resp. \"from\" a rev or\n>> ref depending on whether the detached HEAD has moved since. \"git branch\"\n>> always uses \"from\", which can be confusing, because a status-aware user\n>> would interpret this as moved detached HEAD.\n>>\n>> Make \"git branch\" use the same logic and wording.\n> \n> Yeah, otherwise the user would wonder why sometimes the object name\n> after that \"from\" matches \"git rev-parse HEAD\" and sometimes does\n> not.\n> \n> In order to make sure that it will be easy for us to maintain that\n> these two commands will keep using the same logic and wording after\n> this \"fix\" is applied, should this patch do a bit more?  Or is it\n> worth doing that for such a small piece of code to be shared?\n> \n> The following is a tangent and I do not think it is likely we would\n> do anything about it, but I wonder what value we give the end users\n> by showing the \"from\" information, both in \"status\" and \"branch\" in\n> the first place.  When I am on a detached HEAD, I'd be doing one of\n> these three things:\n> \n>  (1) I am on some kind of sequencing machinery (e.g. \"rebase -i\",\n>      \"cherry-pick A..B\", or \"bisect\").  It does not matter to me at\n>      all if I am at the same commit at which I started the sequenced\n>      operations or the sequencing machinery has moved me one or more\n>      commits along its planned course of action, or where the\n>      original point the sequencing machinery detached the HEAD at.\n>      I suspect that I would not use \"git status\" or \"git branch\" in\n>      this mode anyway.\n> \n>  (2) I am sight-seeing, starting with e.g. \"git checkout v2.0.0\",\n>      and moving around with \"git checkout $some_other_commit\".  I'd\n>      always see that I am \"at\" the commit I last checked out, so the\n>      distinctions would not be even shown to me.\n> \n>  (3) I am experimenting to fix or enhance an existing thing that is\n>      meant to eventually hit a concrete branch, but I do not know if\n>      the experiment would pan out. \"git checkout $topic~$n\" would be\n>      to start from near the tip of that $topic ($n may often be 0\n>      but not always) and then I would \"git commit\" my experiments.\n>      When I assess my progress, I'd be interested in what I have\n>      that is not in $topic and vice versa since I started that\n>      experiment, so\n\nI find it very useful, because I often work on HEADs detached from remote\nbranches (\"git checkout origin/foo\").  If I'm sight-seeing, I like the\nreminder of which remote branch I checked out, especially because I often\nhave several working tress going at the same time.  I also often make trivial\nchanges, like typo fixes, on such detached HEADs, and here too I appreciate\nthe reminder of which remote branch I should push HEAD to.\n\n\t\tM.\n"},{"id":"256520","messageId":"54EB545A.2040309@drmicha.warpmail.net","threadId":"38629","inReplyTo":"54EB436E.9060106@xiplink.com","subject":"Re: [RFC/PATCH] branch: name detached HEAD analogous to status","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2015-02-23T16:24:58Z","receivedAt":"2015-02-23T16:24:58Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Marc Branchaud venit, vidit, dixit 23.02.2015 16:12:\n> On 15-02-22 12:38 PM, Michael J Gruber wrote:\n>> \"git status\" carefully names a detached HEAD \"at\" resp. \"from\" a rev or\n>> ref depending on whether the detached HEAD has moved since. \"git branch\"\n>> always uses \"from\", which can be confusing, because a status-aware user\n>> would interpret this as moved detached HEAD.\n>>\n>> Make \"git branch\" use the same logic and wording.\n> \n> Except that the wording in \"git branch\" is more correct, especially if the\n> detached HEAD contains new commits.\n> \n> In other words, \"at\" is only correct if the detached HEAD matches the ref.\n> If the HEAD has other commits, it is no longer \"at\" that ref but instead it\n> has grown \"from\" it.\n\nSure, but that's exactly what git status does. Haven't you tried out?\n\nAnd it's exactly what I suggest for git branch. It conveys more information.\n\n> But even if the detached HEAD matches the ref, saying it came \"from\" that ref\n> (with 0 extra commits) is still better than saying\n> detached-HEAD-with-extra-commits is \"at\" the ref.\n\nWhy? Both are true. \"at\" conveys the additional information that HEAD is\nstill at the that rev.\n\nMichael\n"},{"id":"256523","messageId":"54EB61FF.1080901@xiplink.com","threadId":"38629","inReplyTo":"54EB545A.2040309@drmicha.warpmail.net","subject":"Re: [RFC/PATCH] branch: name detached HEAD analogous to status","fromName":"Marc Branchaud","fromEmail":"marcnarc@xiplink.com","sentAt":"2015-02-23T17:23:11Z","receivedAt":"2015-02-23T17:23:11Z","isPatch":true,"sender":{"key":"marcnarc@xiplink.com","avatar":"https://avatars.githubusercontent.com/u/14980203?v=4"},"body":"On 15-02-23 11:24 AM, Michael J Gruber wrote:\n> Marc Branchaud venit, vidit, dixit 23.02.2015 16:12:\n>> On 15-02-22 12:38 PM, Michael J Gruber wrote:\n>>> \"git status\" carefully names a detached HEAD \"at\" resp. \"from\" a rev or\n>>> ref depending on whether the detached HEAD has moved since. \"git branch\"\n>>> always uses \"from\", which can be confusing, because a status-aware user\n>>> would interpret this as moved detached HEAD.\n>>>\n>>> Make \"git branch\" use the same logic and wording.\n>>\n>> Except that the wording in \"git branch\" is more correct, especially if the\n>> detached HEAD contains new commits.\n>>\n>> In other words, \"at\" is only correct if the detached HEAD matches the ref.\n>> If the HEAD has other commits, it is no longer \"at\" that ref but instead it\n>> has grown \"from\" it.\n> \n> Sure, but that's exactly what git status does. Haven't you tried out?\n> \n> And it's exactly what I suggest for git branch. It conveys more information.\n\nOops, right.  Sorry, I got blinded by the various \"detached at\" examples in\nyour patch's notes.\n\n\t\tM.\n"},{"id":"257163","messageId":"cover.1425653932.git.git@drmicha.warpmail.net","threadId":"38629","inReplyTo":"54EB4579.3000103@xiplink.com","subject":"[PATCHv2 0/2] branch output for detached HEAD","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2015-03-06T15:04:05Z","receivedAt":"2015-03-06T15:04:05Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"So here's a little refactoring of wt-status, to help branch\nuse the same logic regarding from/at for a detached HEAD.\n\nMichael J Gruber (2):\n  wt-status: refactor detached HEAD analysis\n  branch: name detached HEAD analogous to status\n\n builtin/branch.c         | 13 ++++++++++---\n t/t3203-branch-output.sh | 39 ++++++++++++++++++++++++++++++++++++++-\n wt-status.c              |  6 +++---\n wt-status.h              |  1 +\n 4 files changed, 52 insertions(+), 7 deletions(-)\n\n-- \n2.3.1.303.g5174db1\n"},{"id":"257165","messageId":"f431cf3ed2348db4badaac061481ff7d777d4f36.1425653932.git.git@drmicha.warpmail.net","threadId":"38629","inReplyTo":"54EB4579.3000103@xiplink.com","subject":"[PATCHv2 1/2] wt-status: refactor detached HEAD analysis","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2015-03-06T15:04:06Z","receivedAt":"2015-03-06T15:04:06Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"wt_status_print() is the only caller of wt_status_get_detached_from().\nThe latter performs most of the analysis of a detached HEAD, including\nfinding state->detached_from; the caller checks whether the detached\nHEAD is still at state->detached_from or has moved away.\n\nMove that last bit of analysis to wt_status_get_detached_from(), too,\nand store the boolean result in state->detached_at.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n wt-status.c | 6 +++---\n wt-status.h | 1 +\n 2 files changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex 29666d0..e7c1a4b 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1222,6 +1222,8 @@ static void wt_status_get_detached_from(struct wt_status_state *state)\n \t\tstate->detached_from =\n \t\t\txstrdup(find_unique_abbrev(cb.nsha1, DEFAULT_ABBREV));\n \thashcpy(state->detached_sha1, cb.nsha1);\n+\tstate->detached_at = !get_sha1(\"HEAD\", sha1) &&\n+\t\t\t     !hashcmp(sha1, state->detached_sha1);\n \n \tfree(ref);\n \tstrbuf_release(&cb.buf);\n@@ -1310,10 +1312,8 @@ void wt_status_print(struct wt_status *s)\n \t\t\t\ton_what = _(\"rebase in progress; onto \");\n \t\t\t\tbranch_name = state.onto;\n \t\t\t} else if (state.detached_from) {\n-\t\t\t\tunsigned char sha1[20];\n \t\t\t\tbranch_name = state.detached_from;\n-\t\t\t\tif (!get_sha1(\"HEAD\", sha1) &&\n-\t\t\t\t    !hashcmp(sha1, state.detached_sha1))\n+\t\t\t\tif (state.detached_at)\n \t\t\t\t\ton_what = _(\"HEAD detached at \");\n \t\t\t\telse\n \t\t\t\t\ton_what = _(\"HEAD detached from \");\ndiff --git a/wt-status.h b/wt-status.h\nindex 283a9fe..e0a99f7 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -84,6 +84,7 @@ struct wt_status_state {\n \tint cherry_pick_in_progress;\n \tint bisect_in_progress;\n \tint revert_in_progress;\n+\tint detached_at;\n \tchar *branch;\n \tchar *onto;\n \tchar *detached_from;\n-- \n2.3.1.303.g5174db1\n"},{"id":"257164","messageId":"0ece5e04a3fb38bdc1201036d65ed98199758ba5.1425653932.git.git@drmicha.warpmail.net","threadId":"38629","inReplyTo":"54EB4579.3000103@xiplink.com","subject":"[PATCHv2 2/2] branch: name detached HEAD analogous to status","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2015-03-06T15:04:07Z","receivedAt":"2015-03-06T15:04:07Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"\"git status\" carefully names a detached HEAD \"at\" resp. \"from\" a rev or\nref depending on whether the detached HEAD has moved since. \"git branch\"\nalways uses \"from\", which can be confusing, because a status-aware user\nwould interpret this as moved detached HEAD.\n\nMake \"git branch\" use the same logic and wording.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n\nNotes:\n    v2 uses the info from refactored wt-status.\n    \n    In addition, it tries to make sure that branch and status use the same\n    strings:\n    \n    HEAD detached at %s\n    * (HEAD detached at %s)\n    \n    (status first line, branch second line)\n    \n    Unfortunately, status strings are broken into pieces, so this can\n    be achieved by comments only.\n\n builtin/branch.c         | 13 ++++++++++---\n t/t3203-branch-output.sh | 39 ++++++++++++++++++++++++++++++++++++++-\n 2 files changed, 48 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex d8949cb..4c54240 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -589,9 +589,16 @@ static char *get_head_description(void)\n \telse if (state.bisect_in_progress)\n \t\tstrbuf_addf(&desc, _(\"(no branch, bisect started on %s)\"),\n \t\t\t    state.branch);\n-\telse if (state.detached_from)\n-\t\tstrbuf_addf(&desc, _(\"(detached from %s)\"),\n-\t\t\t    state.detached_from);\n+\telse if (state.detached_from) {\n+\t\t/* TRANSLATORS: make sure these match _(\"HEAD detached at \")\n+\t\t   and _(\"HEAD detached from \") in wt-status.c */\n+\t\tif (state.detached_at)\n+\t\t\tstrbuf_addf(&desc, _(\"(HEAD detached at %s)\"),\n+\t\t\t\tstate.detached_from);\n+\t\telse\n+\t\t\tstrbuf_addf(&desc, _(\"(HEAD detached from %s)\"),\n+\t\t\t\tstate.detached_from);\n+\t}\n \telse\n \t\tstrbuf_addstr(&desc, _(\"(no branch)\"));\n \tfree(state.branch);\ndiff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh\nindex ba4f98e..f51d0f3 100755\n--- a/t/t3203-branch-output.sh\n+++ b/t/t3203-branch-output.sh\n@@ -96,7 +96,7 @@ test_expect_success 'git branch -v pattern does not show branch summaries' '\n \n test_expect_success 'git branch shows detached HEAD properly' '\n \tcat >expect <<EOF &&\n-* (detached from $(git rev-parse --short HEAD^0))\n+* (HEAD detached at $(git rev-parse --short HEAD^0))\n   branch-one\n   branch-two\n   master\n@@ -106,4 +106,41 @@ EOF\n \ttest_i18ncmp expect actual\n '\n \n+test_expect_success 'git branch shows detached HEAD properly after moving' '\n+\tcat >expect <<EOF &&\n+* (HEAD detached from $(git rev-parse --short HEAD))\n+  branch-one\n+  branch-two\n+  master\n+EOF\n+\tgit reset --hard HEAD^1 &&\n+\tgit branch >actual &&\n+\ttest_i18ncmp expect actual\n+'\n+\n+test_expect_success 'git branch shows detached HEAD properly from tag' '\n+\tcat >expect <<EOF &&\n+* (HEAD detached at fromtag)\n+  branch-one\n+  branch-two\n+  master\n+EOF\n+\tgit tag fromtag master &&\n+\tgit checkout fromtag &&\n+\tgit branch >actual &&\n+\ttest_i18ncmp expect actual\n+'\n+\n+test_expect_success 'git branch shows detached HEAD properly after moving from tag' '\n+\tcat >expect <<EOF &&\n+* (HEAD detached from fromtag)\n+  branch-one\n+  branch-two\n+  master\n+EOF\n+\tgit reset --hard HEAD^1 &&\n+\tgit branch >actual &&\n+\ttest_i18ncmp expect actual\n+'\n+\n test_done\n-- \n2.3.1.303.g5174db1\n"},{"id":"257192","messageId":"xmqqtwxxyiw4.fsf@gitster.dls.corp.google.com","threadId":"38629","inReplyTo":"0ece5e04a3fb38bdc1201036d65ed98199758ba5.1425653932.git.git@drmicha.warpmail.net","subject":"Re: [PATCHv2 2/2] branch: name detached HEAD analogous to status","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-03-06T20:23:55Z","receivedAt":"2015-03-06T20:23:55Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> \"git status\" carefully names a detached HEAD \"at\" resp. \"from\" a rev or\n> ref depending on whether the detached HEAD has moved since. \"git branch\"\n> always uses \"from\", which can be confusing, because a status-aware user\n> would interpret this as moved detached HEAD.\n>\n> Make \"git branch\" use the same logic and wording.\n>\n> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n> ---\n>\n> Notes:\n>     v2 uses the info from refactored wt-status.\n>     \n>     In addition, it tries to make sure that branch and status use the same\n>     strings:\n>     \n>     HEAD detached at %s\n>     * (HEAD detached at %s)\n>     \n>     (status first line, branch second line)\n>     \n>     Unfortunately, status strings are broken into pieces, so this can\n>     be achieved by comments only.\n\nIt feels somewhat strange to have fields called detached-at and\ndetached-from in wt_status_state.\n\nWith this patch,\n\n    * branch is either a string \"HEAD\" or the name of the branch we\n      are on.\n\n    * detached_from is the name of the branch HEAD detached from,\n      or NULL if HEAD is on a branch.\n\n    * detached_sha1[] is the object name of the commit we last\n      moved to with \"checkout --detach\".\n\n    * detached_at is a boolean that says the tip of detached_from\n      and detached_sha1[] is the same.\n\nThere aren't that many users of these fields, so if we were to\nrename them and clarify what they mean in order to make the code\nmore readable, we may be able to do so without too much churn.\n\nRandom conflicting/incoherent thoughts include:\n\n - perhaps branch can be NULL when detached?\n\n - perhaps branch can always point at the branch or the current\n   detached-from?\n \n - perhaps detached_from can be renamed to make it more clear that\n   it is the name of a branch (detached_sha1[] is fine, because it\n   is clear what it is by having \"sha1\" in its name)?\n\n - perhaps detached_from/detached_at can be made into a single\n   string that is set up by wt-status to hold either \"HEAD detached\n   at %s\" or \"HEAD detached from %s\" to be used by its callers?\n\nbut I cannot yet reach a coherent whole to be called a suggestion\nfor a better organization X-<.\n\nWill replace what was queued with this version.\n\nThanks.  \n"}]}