57

I'm still relatively new to Git and I have made a bit of a mess of my repository. I'm hoping there is a way to fix it without re-cloning.

I have a repository which I have cloned from Github. The repository has several branches. I worked on the master branch for a while but then needed to switch to one of the other branches.

So, I had:

$ git branch --all
* master
  remotes/origin/abc
  remotes/origin/def
  remotes/origin/HEAD -> origin/master
  remotes/origin/ghi

Problem: I wanted to switch to the 'abc' branch but instead of doing git checkout remotes/origin/abc I accidentally did git branch remotes/origin/abc which leaves me with the following:

$ git branch --all
* master
  remotes/origin/abc
  remotes/origin/abc
  remotes/origin/def
  remotes/origin/HEAD -> origin/master
  remotes/origin/ghi

My questions are:

  • Why on Earth does Git allow you to create two branches with the same name?
  • How do I identify which is the real remotes/origin/abc branch?
  • How do I remove the unwanted remotes/origin/abc that I created by accident?

Any help much appreciated.

5 Answers 5

32

You can't create two local branches or two distant branches with the same name.

  • Here you have a local branch named remotes/origin/abc and a distant branch named abc on the remote origin. They have not the same name, but it seems to when you use the git branch --all command.

  • To identify which branch is which, you can show local branches with git branch, or show remote branches with git branch --remote. You could also easily differentiate them even while using git branch --all with the branch syntax coloration (git config --global color.branch auto).

  • To remove the accidentally created local branch abc, you have to do git branch -d abc (or git branch -D abc to force deletion, see man git-branch).

2
  • 14
    In case anyone's wondering, two local or two remote branches can have the same name as long as they don't exist simultaneously. So if you used a topic branch with a general name and want to reuse that branch name in the future, you can, as long as a branch with that name doesn't already exist. I wasn't sure if this would be possible with GitHub since they allow you to restore deleted branches, but I guess they create a branch with a unique name for restoration purposes before deleting the actual branch.
    – Dennis
    Jan 29, 2014 at 21:53
  • All true and well said. I think you are talking about the context of a single clone. If there are multiple clones, then you can have the same named local branch in each -- created locally in each. What I want to know is what happens if you try to push both to the same remote. Does the 2nd clobber the first or is there identity of a branch other than name so that the remote can reject the 2nd push.
    – steve
    Sep 16, 2022 at 11:27
8

The true story is that Git has a simplification scheme for its "refs" (a Git lingo for "references", which is the term used to refer to branches, tags etc). In fact, references live in their namespaces, which, with the reference Git implementation, are just directories under .git. For instance, your local branch "master" is really "refs/heads/master" — a file named "master" located in the .git/refs/heads directory. There are also "refs/tags" namespace and "refs/remotes" namespace — for tags and remote branches (those created by the git fetch command).

Now when you tell Git to create a branch remotes/origin/abc it really creates refs/heads/remotes/origin/abc which does not clash with refs/remotes/origin/abc because the rules to deal with that simplification scheme make the former trump the latter. At any time you can use the full form of ref naming to remove any disambiguation.

The gory detals of how Git interprets ref names are described in the section "Specifying Revisions" of the git-rev-parse manual:

<refname>, e.g. master, heads/master, refs/heads/master

A symbolic ref name. E.g. master typically means the commit object referenced by refs/heads/master. If you happen to have both heads/master and tags/master, you can explicitly say heads/master to tell git which one you mean. When ambiguous, a <refname> is disambiguated by taking the first match in the following rules:

If $GIT_DIR/<refname> exists, that is what you mean (this is usually useful only for HEAD, FETCH_HEAD, ORIG_HEAD, MERGE_HEAD and CHERRY_PICK_HEAD);

otherwise, refs/<refname> if it exists;

otherwise, refs/tags/<refname> if it exists;

otherwise, refs/heads/<refname> if it exists;

otherwise, refs/remotes/<refname> if it exists;

otherwise, refs/remotes/<refname>/HEAD if it exists.

2

Git places very little restriction on branch names and e.g. slashes in branch names are perfectly fine. Also deleting a branch on the remote is done with e.g.

$ git push origin :abc

while deleting a local branch is e.g.

$ git branch -d remotes/origin/abc

where there is no ambiguity because these two entities live in different namespaces.

1

I made a similar mistake (creating a local branch named origin/...) a couple of times.

To protect against this sort of mistakes (and assuming you will never want a local branch whose name actually starts with origin/) you can run the following commands in repo/.git/refs/heads:

mklink /d remotes nul
mklink /d origin nul
mklink /d upstream nul

They create symlinks to nul that would prevent creating subdirectories under those names. Now accidental mistakes like git branch origin/feature will give an error:

unable to create directory for .git/refs/heads/origin/feature
-1

Use gitk or gitk --all to inspect branches. There you can see local and remote branches with different color. And create, checkout, delete local branches with ease and without ambiguity just right-clicking on them.

For remote tracking branches you can use git gui, create branch menu, just pick the remote branch and the proper local naming idea. That way it is pretty hard to mess up.

As for the first question: you can't really create branches with same name, but similar-looking synthetized name can happen if you fight for it. With proper tools they are not confused, so there's no reason to forbid the scenario.

5
  • 1
    There is no need to use a GUI here. Jun 28, 2013 at 8:24
  • 1
    you obviously did not pay attention to OP, if he used the GUI instead of command line, would not sit in the situation in the first place.
    – Balog Pal
    Jun 28, 2013 at 8:31
  • I don't share your opinion, git GUI may be useful but first it's important to learn how it really works under the hood. He had to understand what he really did and what was his mistake to not do it again. Jun 28, 2013 at 8:35
  • 1
    you're welcome to whatever opinion but that does not change facts that using refined visual tools just prevent the simple mess-ups. And learning all the plumbing git does may be interesting for geeks but is not at all necessary for everyday use cases. Including but not limited to navigating branches.
    – Balog Pal
    Jun 28, 2013 at 8:38
  • 3
    For sure a one doesn't have to learn every git plumbing to use it, but it's better to learn basics, even if you use a GUI. It avoids a lot of mistakes. Jun 28, 2013 at 8:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.