{"thread":{"id":"32112","subject":"creation of empty branches","startedAt":"2012-11-14T10:10:07Z","lastAt":"2012-11-15T17:12:33Z","messageCount":5,"participants":["Angelo Borsotti","Andrew Ardill","Junio C Hamano","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"203179","messageId":"CAB9Jk9CaBECT7c_M9HvCbB8mFYGvdsmq_jFW4DF4NCO8Narnmw@mail.gmail.com","threadId":"32112","inReplyTo":null,"subject":"creation of empty branches","fromName":"Angelo Borsotti","fromEmail":"angelo.borsotti@gmail.com","sentAt":"2012-11-14T10:10:07Z","receivedAt":"2012-11-14T10:10:07Z","isPatch":false,"sender":{"key":"angelo.borsotti@gmail.com","avatar":null},"body":"Hi,\n\nthe man page of git checkout does not describe the behavior of\ngit-checkout when asked to create empty branches. E.g.:\n\n$ git init myrepo\n$ cd myrepo\n$ git checkout -b newbranch\n\nthe last command actually changes only the HEAD. It displays no output\ntelling the user that no switch to a new branch is done. Moreover, it\ncan be entered again without receiving any error message (unlike the\ncreation ot non-empty branches, which is instead rejected).\nI would suggest to add to the DESCRIPTION, after the paragraph: \"If -b\nis given ...\":\n\n    \"If the repository does not contain any branch, no new branch is\ncreated, but the HEAD is set to refer to it.\"\n\nMoreover, it is often reported (e.g. in the progit book) that git\ncheckout -b is equivalent to git branch; git checkout, and this is\ntrue when nonempty branches are created, but it is not when the\nrepository is empty:\n\n$ git init myrepo\n$ cd myrepo\n$ git branch master\nfatal: Not a valid object name: 'master'.\n\nhowever:\n$ git checkout -b master\n.... no error\n\nThis seems quite strange and difficult to understand: why should git\nbranch master issue an error while git checkout does not? I have the\nimpression that also git branch should not issue an error in this\ncase.\n\n-Angelo Borsotti\n"},{"id":"203184","messageId":"CAH5451mkcszgJxziKn3q3OwSDM-qQ71PtT5+UWb=PG7VYAcFyQ@mail.gmail.com","threadId":"32112","inReplyTo":"CAB9Jk9CaBECT7c_M9HvCbB8mFYGvdsmq_jFW4DF4NCO8Narnmw@mail.gmail.com","subject":"Re: creation of empty branches","fromName":"Andrew Ardill","fromEmail":"andrew.ardill@gmail.com","sentAt":"2012-11-14T12:54:44Z","receivedAt":"2012-11-14T12:54:44Z","isPatch":false,"sender":{"key":"andrew.ardill@gmail.com","avatar":"https://gravatar.com/avatar/da14cb7c091dd44dc6c63a4d3361b149acaf25226dc78eb4131a17b93d9b0993?d=mp&s=160"},"body":"On 14 November 2012 21:10, Angelo Borsotti <angelo.borsotti@gmail.com> wrote:\n> ... why should git\n> branch master issue an error while git checkout does not? I have the\n> impression that also git branch should not issue an error in this\n> case.\n>\n\nJust to help a little, let's first define:\n- An empty file in refs/heads is a broken head.\n- A non-existent file in refs/heads is an empty branch. Most\nreferences to empty branches are probably mistakes.\n- If HEAD points to an empty branch it is in 'root commit' or 'orphan'\nmode. A commit made in such a mode first creates the root or orphan\ncommit object, and then creates the branch head in refs/heads pointing\nto that object.\n\nAs I understand it, git branch and git checkout without a start point\ndefined are both intended to create a new branch and point it to the\ncurrent HEAD. Checkout will additionally reset HEAD to point to the\nnew branch, rather than whatever it was pointing to before (which will\nnormally be either a direct or indirect reference to a commit object).\nThe problem is that the behaviour when HEAD points to empty branch is\nundefined, and this situation is seen to occur when there are no\ncommit objects at all, in an empty repository. This will also happen\nwhen a branch has been checked out in orphan mode.\n\nSince git branch has the default behaviour to create a branch 'in the\nbackground' it makes sense to fail when trying to create a new branch\nthis way from an empty branch. The error message should be improved to\nhandle this edge case in a nicer way. If we allow for renaming empty\nbranches (described below) then the message can be even more helpful.\nInstead of\n    fatal: Not a valid object name: 'master'.\nperhaps\n    fatal: Cannot create branch 'foo' from empty branch 'master'. To\nrename 'master' use 'git branch -m master foo'.\n\ngit checkout -b changes the current branch, and so it does make sense\nto allow renaming an empty branch, which is the current behaviour.\nHowever, note that currently when HEAD points to an empty branch, 'git\ncheckout -b foo HEAD' fails because HEAD is an invalid reference.\nObviously some special logic has been added or a very odd bug has\nappeared. Perhaps it is most useful to continue to error out on any\nreference explicitly listed on the command line as the start point\nthat points to an empty branch, unless it is pointed to by HEAD. Thus\nwe would only make HEAD point to a new empty branch when the start\npoint is omitted or when it matches the current empty branch HEAD\npoints to.\n\nIt would be useful to extend this renaming of empty branches to the\nbranch commands, and 'git branch -m' is a perfect fit for this from a\nuser perspective.\n\n\nSo explicitly, I am proposing the following behaviour changes:\n\nWhen trying to create a new branch without specifying a start point,\n  if HEAD points to an empty branch, error with a more useful message\nthat assumes the user might want to rename the empty branch.\nWhen trying to create a new branch whilst specifying an empty branch\nas the start point,\n  if HEAD points to the same empty branch that is listed as the start\npoint, error with a more useful message that assumes the user might\nwant to rename the empty branch.\n  otherwise error due to invalid ref\n\nWhen checking out a new branch without specifying a start point,\n  if HEAD points to an empty branch then HEAD should be pointed to the\nnew branch, which will also be empty.\nWhen checking out a new branch whilst specifying an empty branch as\nthe start point,\n  if HEAD points to the same empty branch that is listed as the start\npoint, HEAD should be pointed to the new, empty branch\n  otherwise error due to invalid ref\n\nWhen moving to a new branch without specifying an old branch,\n  if HEAD points to an empty branch then HEAD should be pointed to the\nnew branch, which will also be empty.\nWhen moving to a new branch whilst specifying an empty branch as the old branch,\n  if HEAD points to the same empty branch that is listed as the old\nbranch, HEAD should be pointed to the new, empty branch\n  otherwise error due to invalid ref\n\nNote that since HEAD points to an empty branch there should be no\nconflicts with the working directory or the index, so leave them\nunchanged.\n\nSome examples that might help:\n\n~$ git init test\n~$ cd test\n~/test (master)$ git branch foo\nfatal: Cannot create branch 'foo' from empty branch 'master'. To\nrename 'master' use 'git branch -m master foo'.\n~/test (master)$ git checkout -b foo\n~/test (foo)$ git checkout -b bar fo\nfatal: Not a valid object name: 'fo'.\n~/test (foo)$ git checkout -b bar foo\n~/test (bar)$ git branch -m foo\n~/test (foo)$ git branch -m fo bar\nerror: refname refs/heads/fo not found\nfatal: Branch rename failed\n~/test (foo)$ git branch -m foo bar\n~/test (bar)$\n\n\n\nI wouldn't mind trying to code this up at the moment, but as I don't\nhave heaps of time if someone else feels like it go ahead (assuming\nit's a good suggestion of course!).\n\nRegards,\n\nAndrew Ardill\n"},{"id":"203224","messageId":"7vmwyjan96.fsf@alter.siamese.dyndns.org","threadId":"32112","inReplyTo":"CAH5451mkcszgJxziKn3q3OwSDM-qQ71PtT5+UWb=PG7VYAcFyQ@mail.gmail.com","subject":"Re: creation of empty branches","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-11-14T21:27:33Z","receivedAt":"2012-11-14T21:27:33Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andrew Ardill <andrew.ardill@gmail.com> writes:\n\n> Since git branch has the default behaviour to create a branch 'in the\n> background' it makes sense to fail when trying to create a new branch\n> this way from an empty branch. The error message should be improved to\n> handle this edge case in a nicer way. If we allow for renaming empty\n> branches (described below) then the message can be even more helpful.\n> Instead of\n>     fatal: Not a valid object name: 'master'.\n> perhaps\n>     fatal: Cannot create branch 'foo' from empty branch 'master'. To\n> rename 'master' use 'git branch -m master foo'.\n\nThe first new sentence is a definite improvement, but I do not think\nthe advice in the second sentence is necessarily a good idea,\nbecause it is dubious that the user is likely to have wanted to\nrename 'master' to something else.  \"git branch foo master\" (or its\nmoral equivalent \"git checkout -b foo\" while on master) is a wish to\nhave a history that ends in 'foo' *forked* from history of 'master',\nbut because you do not even have anything on 'master' yet, you\ncannot fork the history, as you explained earlier (snipped).  In\nthat sense, 'empty branch' is a slight misnomer---as far as \"git\nbranch foo master\" is concerned, the 'master' branch does not yet\nexist (and that is why we often call it an \"unborn branch\", not\n\"empty\").\n\n    fatal: cannot fork master's history that does not exist yet.\n\nwould be more accurate description of the situation.\n\n> So explicitly, I am proposing the following behaviour changes:\n>\n> When trying to create a new branch without specifying a start point,\n> if HEAD points to an empty branch, error with a more useful message\n> that assumes the user might want to rename the empty branch.\n\nI do not think that is the right assumption in the first place.  It\nis very likely that the user does not yet know how Git works when\nshe attempts to fork from a history that does not exist.  It is also\nvery likely that she is expecting, after \"git branch foo master\"\nsucceeds when 'master' is yet to be born, have two branches 'foo'\nand 'master', so that \"git checkout foo\" and \"git checkout master\"\ncan be done subsequently.\n\nBut that expectation is wrong, and it would help the user in the\nlonger run to correct that expectation.  \"We assume you wanted to\nrename 'master' to 'foo'\" is a logical consequence that changing\nHEAD that points at an unborn 'master' to point at an unborn 'foo'\nis the best (or closest) thing the user can do, *if* the user\nunderstands that the current branch being unborn is a special state\nand there can only be one such unborn branch (that is, the current\none).  The user who gets this error message, however, clearly does\nnot understand that, so it is not a logical consequence to her at\nall.  The advice does not help her, but instead invites \"No, I did\nnot want to rename it, I wanted to have 'foo' without losing\n'master'\", leading to even more confusion.\n\n> When trying to create a new branch whilst specifying an empty branch\n> as the start point,\n>   if HEAD points to the same empty branch that is listed as the start\n> point, error with a more useful message that assumes the user might\n> want to rename the empty branch.\n>   otherwise error due to invalid ref\n\nSee above (for all the other cases, too).\n"},{"id":"203230","messageId":"CAH5451=NkodCMZZ3eBnhewZBfv2h3NwEuEi7df_FGhWfovR4Jg@mail.gmail.com","threadId":"32112","inReplyTo":"7vmwyjan96.fsf@alter.siamese.dyndns.org","subject":"Re: creation of empty branches","fromName":"Andrew Ardill","fromEmail":"andrew.ardill@gmail.com","sentAt":"2012-11-15T00:04:24Z","receivedAt":"2012-11-15T00:04:24Z","isPatch":false,"sender":{"key":"andrew.ardill@gmail.com","avatar":"https://gravatar.com/avatar/da14cb7c091dd44dc6c63a4d3361b149acaf25226dc78eb4131a17b93d9b0993?d=mp&s=160"},"body":"On 15 November 2012 08:27, Junio C Hamano <gitster@pobox.com> wrote:\n> ... \"git branch foo master\" (or its\n> moral equivalent \"git checkout -b foo\" while on master) is a wish to\n> have a history that ends in 'foo' *forked* from history of 'master',\n> but because you do not even have anything on 'master' yet, you\n> cannot fork the history, as you explained earlier (snipped).  In\n> that sense, 'empty branch' is a slight misnomer---as far as \"git\n> branch foo master\" is concerned, the 'master' branch does not yet\n> exist (and that is why we often call it an \"unborn branch\", not\n> \"empty\").\n>\n>     fatal: cannot fork master's history that does not exist yet.\n>\n> would be more accurate description of the situation.\n\nSo in the situation where a start-point is an unborn branch (ie it is\nreferenced in HEAD) we should modify the error to show that the unborn\nbranch is in fact unborn. This is a good improvement I think, as it\ncatches this edge case and improves understanding of what an unborn\nbranch is. The term 'fork' is not used at all in branch's man page, so\nperhaps a more consistent error message is something like\n\n    fatal: 'master' has no history, so we cannot create a new branch from it\n\nAlso, currently 'git checkout -b' *will* rename an unborn branch which\nis different from the 'git branch' behaviour. Not sure how this\nbehaviour can be corrected without causing a regression or introducing\npotentially confusing error messages for the git branch case.\n\n>> So explicitly, I am proposing the following behaviour changes:\n>>\n>> When trying to create a new branch without specifying a start point,\n>> if HEAD points to an empty branch, error with a more useful message\n>> that assumes the user might want to rename the empty branch.\n>\n> I do not think that is the right assumption in the first place.  It\n> is very likely that the user does not yet know how Git works when\n> she attempts to fork from a history that does not exist.  It is also\n> very likely that she is expecting, after \"git branch foo master\"\n> succeeds when 'master' is yet to be born, have two branches 'foo'\n> and 'master', so that \"git checkout foo\" and \"git checkout master\"\n> can be done subsequently.\n>\n> But that expectation is wrong, and it would help the user in the\n> longer run to correct that expectation.  \"We assume you wanted to\n> rename 'master' to 'foo'\" is a logical consequence that changing\n> HEAD that points at an unborn 'master' to point at an unborn 'foo'\n> is the best (or closest) thing the user can do, *if* the user\n> understands that the current branch being unborn is a special state\n> and there can only be one such unborn branch (that is, the current\n> one).  The user who gets this error message, however, clearly does\n> not understand that, so it is not a logical consequence to her at\n> all.  The advice does not help her, but instead invites \"No, I did\n> not want to rename it, I wanted to have 'foo' without losing\n> 'master'\", leading to even more confusion.\n\nI can't speak for others, but I think it is more likely that a new\nuser who doesn't understand git and tries to use the branch command on\na brand new repository is not trying to fork master's history, but is\nrather trying to switch to a different branch. A subversion user might\nwant to switch from 'master' to 'trunk' as a (somewhat?) common use\ncase. That is the reasoning behind my recommendation to show how to\nrename the branch. Furthermore, we can educate the user about unborn\nbranches and suggest a possible solution at the same time.\n\nWith the new error message from above, something like the following\nmight be nice.\n\n    fatal: 'master' has no history, so we cannot create a new branch from it\n    hint: A repository can only contain one unborn branch at a time.\n    hint: To rename a branch use 'git branch -m [<old-branch>] <new-branch>'\n\nI'm not sure about the intended syntax of hint messages but this seems\nconsistent.\n\n>\n>> When trying to create a new branch whilst specifying an empty branch\n>> as the start point,\n>>   if HEAD points to the same empty branch that is listed as the start\n>> point, error with a more useful message that assumes the user might\n>> want to rename the empty branch.\n>>   otherwise error due to invalid ref\n>\n> See above (for all the other cases, too).\n>\n\nYou didn't address the branch rename command 'git branch -m\n[<old-branch>] <new-branch>' (or you included it with the others). I\nthink it is a significantly different action to creating a new branch,\nand should handle unborn branches in the expected way, which is to\nrename them. What are your thoughts on that?\n\nRegards,\n\nAndrew Ardill\n"},{"id":"203300","messageId":"20121115171230.GB18108@sigill.intra.peff.net","threadId":"32112","inReplyTo":"7vmwyjan96.fsf@alter.siamese.dyndns.org","subject":"Re: creation of empty branches","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2012-11-15T17:12:33Z","receivedAt":"2012-11-15T17:12:33Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Nov 14, 2012 at 01:27:33PM -0800, Junio C Hamano wrote:\n\n> > Instead of\n> >     fatal: Not a valid object name: 'master'.\n> > perhaps\n> >     fatal: Cannot create branch 'foo' from empty branch 'master'. To\n> > rename 'master' use 'git branch -m master foo'.\n> \n> The first new sentence is a definite improvement, but I do not think\n> the advice in the second sentence is necessarily a good idea,\n> because it is dubious that the user is likely to have wanted to\n> rename 'master' to something else.  \"git branch foo master\" (or its\n> moral equivalent \"git checkout -b foo\" while on master) is a wish to\n> have a history that ends in 'foo' *forked* from history of 'master',\n> but because you do not even have anything on 'master' yet, you\n> cannot fork the history, as you explained earlier (snipped).  In\n> that sense, 'empty branch' is a slight misnomer---as far as \"git\n> branch foo master\" is concerned, the 'master' branch does not yet\n> exist (and that is why we often call it an \"unborn branch\", not\n> \"empty\").\n> \n>     fatal: cannot fork master's history that does not exist yet.\n> \n> would be more accurate description of the situation.\n\nI agree with most of your reasoning. I think simply using Andrew's first\nsentence is a little more clear to a new user, even though it may be\nless technically precise, but I don't have a strong opinion.\n\nThat still leaves \"checkout -b\". I do not see it as a problem that \"git\nbranch foo\" does not work whereas \"git checkout -b foo\" does; we\nspecial-case the latter because it can do something sensible, whereas\nthere is nothing sensible for \"git branch foo\" to do. However, I think\nit is missing one piece:\n\n-- >8 --\nSubject: checkout: print a message when switching unborn branches\n\nWhen we switch to a new branch using checkout, we usually output a\nmessage indicating what happened. However, when we switch from an unborn\nbranch to a new branch, we do not print anything, which may leave the\nuser wondering what happened.\n\nThe reason is that the unborn branch is a special case (see abe1998),\nand does not follow the usual switch_branches code path. Let's add a\nsimilar informational message to the special case to match the usual\ncode path.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nTwo possible tweaks:\n\n  1. The message is the same as \"git checkout -b\" when we are actually\n     moving to a new branch. We could optionally mention that the branch\n     is empty or unborn.\n\n  2. We do not check whether the old unborn branch has the same name as\n     the new one. So you get \"Switched to a new branch...\" if you try to\n     checkout the same branch. We'd have to pass more information into\n     the special case to detect this. I don't know if we care.\n\n builtin/checkout.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 781295b..a9c1b5a 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -951,6 +951,9 @@ static int switch_unborn_to_new_branch(const struct checkout_opts *opts)\n \tstrbuf_addf(&branch_ref, \"refs/heads/%s\", opts->new_branch);\n \tstatus = create_symref(\"HEAD\", branch_ref.buf, \"checkout -b\");\n \tstrbuf_release(&branch_ref);\n+\tif (!opts->quiet)\n+\t\tfprintf(stderr, _(\"Switched to a new branch '%s'\\n\"),\n+\t\t\topts->new_branch);\n \treturn status;\n }\n \n"}]}