Tim
Tim

Reputation: 99418

Does `git branch remotes/origin/foo` create a new branch?

I was under master branch, and run git branch -ra which shows a branch

remotes/origin/deals

The branch isn't shown in the output of git branch. I guess that it is a remote-tracking branch, correct?

I wanted to switch to that branch, but I accidentally ran

$ git branch remotes/origin/deals
$ git branch
* master
  remotes/origin/deals

Is it correct that i should have ran git branch -b remotes/origin/deals instead?

Did I create a new branch whose name is also remotes/origin/deals, and are there now two branches whose names are both remotes/origin/deals and how is that possible?

If I created a new branch remotes/origin/deals, is it a local branch? how can I remove it?

Thanks.

Upvotes: -1

Views: 270

Answers (4)

torek
torek

Reputation: 488103

The answers you have gotten so far are all correct, but are not pointing out a key distinction. As you saw in another question, Git declares that there are two "kinds" of branches, regular (local) branches and remote-tracking branches.

Under the hood, however, Git actually unifies these—and tags, too—by lumping them all together under the general category of references. So this brings up a good question: How does Git decide that B is a local branch and R is a remote-tracking branch?

The obvious answer is actually the wrong answer!

The git branch command, when run with no flags or with -l, shows local branches:

$ git branch
master
test

Or, when run with -r, it shows remote-tracking branches:

$ git branch -r
origin/master
origin/test

You might say to yourself: Aha, origin means "remote-tracking". But this isn't true, and in fact, when you run git branch -a to see both local and remote-tracking branches, the output changes:

$ git branch -a
master
test
remotes/origin/master
remotes/origin/test

Now it's a bit more mysterious. Maybe remotes/origin means remote-tracking? Well, that's closer, but still not right.

How Git distinguishes local and remote-tracking branches

In fact, git branch is lying to you, with a good excuse: it's trying to shorten things. The full name of each reference starts with refs/. If git branch did not do this shortening, you would see:

refs/heads/master
refs/heads/test
refs/remotes/origin/master
refs/remotes/origin/test

Now the obvious answer is the correct answer: A local branch starts with refs/heads/ and a remote-tracking branch starts with refs/remotes/. (For completeness, let's also note that a tag starts with refs/tags/.) The git branch command shortens these, with the idea that you know what kind of branch you're looking for because you either asked for local branches or for remote-tracking branches.

The same goes for branch creation

The git branch command applies the same rules to branch creation. If you use -l or no flag at all, it creates a regular (local) branch: it puts refs/heads/ in front of whatever you typed in. If you use -r, it creates a remote-tracking branch: it puts refs/remotes/ in front. Then, as usual, it strips those off again when it shows them to you.

What this means is that git branch remotes/origin/deals creates refs/heads/remotes/origin/deals: a local branch, not a remote-tracking branch. It then shows up as remotes/origin/deals after stripping off refs/heads/. It's sometimes impossible to tell this apart from an actual remote-tracking branch refs/remotes/origin/deals, so if you actually had both the name would be somewhat ambiguous.1 Since you don't, though, it's not ambiguous: it's just a local branch, with a very misleading name.

Diagnostic tools

The "plumbing" command git for-each-ref will, as its default action, print every reference—branches, remote-tracking branches, tags, "notes", the "stash": in short, everything under refs/—by full name. If you're in this ambiguous-reference situation, you can get a full dump of everything using git for-each-ref.

For a nicer (higher level) view, git branch with appropriate flags, and/or with various color options set, will split up the names. If git branch -l (or git branch with no flags) shows a branch name, it's local, even if it starts with origin/ or remotes/origin/. If git branch -r shows a branch name, it's a remote-tracking branch. With color mode turned on, local branches default to plain, except for the current branch which is printed in green; and remote-tracking branches are printed in red. Adding multiple v flags (e.g., git branch -avv), you get additional information, with "upstream" names printed in blue. (Upstreams are most often remote-tracking branches, since these are the ones Git creates automatically, but you can set one local branch as the upstream for another local branch.)


1Git deals with this by choosing one according to Git's internal rules. These rules are described in the gitrevisions documentation, but there is an important caveat: the git checkout command uses its own, different, rules. So git diff or git log will show one thing, while git checkout will do another, in some ambiguous-name cases. It's best just to avoid the situation entirely.

Upvotes: 1

Charles Duffy
Charles Duffy

Reputation: 295373

When you ran

$ git branch remotes/origin/deals

...you created a new file:

# file describing local branch created by the above command
.git/logs/refs/heads/remotes/origin/deals

...which, indeed, you should probably delete (either by hand, or with git branch -d remotes/origin/deals).

This is as opposed to the file pointing to the remote branch head:

# file created by fetching from the remote branch
.git/logs/refs/remotes/origin/deals

To check out a remote branch, you should use:

$ git checkout remotes/origin/deals

...or, to create and checkout a local branch which tracks that remote branch:

$ git checkout -b deals --track origin/deals

Upvotes: 1

pioardi
pioardi

Reputation: 181

If you want switch on a remote branch you need : git checkout branchname .

Now you has created a branch with same name of remote branch . A simple solution could be to clone your project on a different local folder . After this you can run : git checkout remotes/origin/deals .

Upvotes: 1

Hanmaslah
Hanmaslah

Reputation: 746

git branch remotes/origin/deals creates a new branch called remotes/origin/deals

git checkout -b remotes/origin/deals creates a new branch called remotes/origin/deals and points to that branch

git checkout remotes/origin/deals points to an existing branch called remotes/origin/deals

git branch -d remotes/origin/deals safely deletes the branch making sure there is no uncommitted work

git branch -D remotes/origin/deals forcefully deletes the branch

git push origin --delete {the_remote_branch} deletes the remote branch

Upvotes: 1

Related Questions