Hi,
the man page of git checkout does not describe the behavior of
git-checkout when asked to create empty branches. E.g.:
$ git init myrepo
$ cd myrepo
$ git checkout -b newbranch
the last command actually changes only the HEAD. It displays no output
telling the user that no switch to a new branch is done. Moreover, it
can be entered again without receiving any error message (unlike the
creation ot non-empty branches, which is instead rejected).
I would suggest to add to the DESCRIPTION, after the paragraph: "If -b
is given ...":
"If the repository does not contain any branch, no new branch is
created, but the HEAD is set to refer to it."
Moreover, it is often reported (e.g. in the progit book) that git
checkout -b is equivalent to git branch; git checkout, and this is
true when nonempty branches are created, but it is not when the
repository is empty:
$ git init myrepo
$ cd myrepo
$ git branch master
fatal: Not a valid object name: 'master'.
however:
$ git checkout -b master
.... no error
This seems quite strange and difficult to understand: why should git
branch master issue an error while git checkout does not? I have the
impression that also git branch should not issue an error in this
case.
-Angelo Borsotti
On 14 November 2012 21:10, Angelo Borsotti [off-list ref] wrote:
... why should git
branch master issue an error while git checkout does not? I have the
impression that also git branch should not issue an error in this
case.
Just to help a little, let's first define:
- An empty file in refs/heads is a broken head.
- A non-existent file in refs/heads is an empty branch. Most
references to empty branches are probably mistakes.
- If HEAD points to an empty branch it is in 'root commit' or 'orphan'
mode. A commit made in such a mode first creates the root or orphan
commit object, and then creates the branch head in refs/heads pointing
to that object.
As I understand it, git branch and git checkout without a start point
defined are both intended to create a new branch and point it to the
current HEAD. Checkout will additionally reset HEAD to point to the
new branch, rather than whatever it was pointing to before (which will
normally be either a direct or indirect reference to a commit object).
The problem is that the behaviour when HEAD points to empty branch is
undefined, and this situation is seen to occur when there are no
commit objects at all, in an empty repository. This will also happen
when a branch has been checked out in orphan mode.
Since git branch has the default behaviour to create a branch 'in the
background' it makes sense to fail when trying to create a new branch
this way from an empty branch. The error message should be improved to
handle this edge case in a nicer way. If we allow for renaming empty
branches (described below) then the message can be even more helpful.
Instead of
fatal: Not a valid object name: 'master'.
perhaps
fatal: Cannot create branch 'foo' from empty branch 'master'. To
rename 'master' use 'git branch -m master foo'.
git checkout -b changes the current branch, and so it does make sense
to allow renaming an empty branch, which is the current behaviour.
However, note that currently when HEAD points to an empty branch, 'git
checkout -b foo HEAD' fails because HEAD is an invalid reference.
Obviously some special logic has been added or a very odd bug has
appeared. Perhaps it is most useful to continue to error out on any
reference explicitly listed on the command line as the start point
that points to an empty branch, unless it is pointed to by HEAD. Thus
we would only make HEAD point to a new empty branch when the start
point is omitted or when it matches the current empty branch HEAD
points to.
It would be useful to extend this renaming of empty branches to the
branch commands, and 'git branch -m' is a perfect fit for this from a
user perspective.
So explicitly, I am proposing the following behaviour changes:
When trying to create a new branch without specifying a start point,
if HEAD points to an empty branch, error with a more useful message
that assumes the user might want to rename the empty branch.
When trying to create a new branch whilst specifying an empty branch
as the start point,
if HEAD points to the same empty branch that is listed as the start
point, error with a more useful message that assumes the user might
want to rename the empty branch.
otherwise error due to invalid ref
When checking out a new branch without specifying a start point,
if HEAD points to an empty branch then HEAD should be pointed to the
new branch, which will also be empty.
When checking out a new branch whilst specifying an empty branch as
the start point,
if HEAD points to the same empty branch that is listed as the start
point, HEAD should be pointed to the new, empty branch
otherwise error due to invalid ref
When moving to a new branch without specifying an old branch,
if HEAD points to an empty branch then HEAD should be pointed to the
new branch, which will also be empty.
When moving to a new branch whilst specifying an empty branch as the old branch,
if HEAD points to the same empty branch that is listed as the old
branch, HEAD should be pointed to the new, empty branch
otherwise error due to invalid ref
Note that since HEAD points to an empty branch there should be no
conflicts with the working directory or the index, so leave them
unchanged.
Some examples that might help:
~$ git init test
~$ cd test
~/test (master)$ git branch foo
fatal: Cannot create branch 'foo' from empty branch 'master'. To
rename 'master' use 'git branch -m master foo'.
~/test (master)$ git checkout -b foo
~/test (foo)$ git checkout -b bar fo
fatal: Not a valid object name: 'fo'.
~/test (foo)$ git checkout -b bar foo
~/test (bar)$ git branch -m foo
~/test (foo)$ git branch -m fo bar
error: refname refs/heads/fo not found
fatal: Branch rename failed
~/test (foo)$ git branch -m foo bar
~/test (bar)$
I wouldn't mind trying to code this up at the moment, but as I don't
have heaps of time if someone else feels like it go ahead (assuming
it's a good suggestion of course!).
Regards,
Andrew Ardill