What you want is just git checkout branch_B
even though branch_B
does not exist. In fact, it's critical that it not exist, otherwise git checkout
can't create it.
Before you just use that, though, take a moment to consider this: you're not really "creating a branch from a central repo" at all. You can't: you can only operate on your own repository.
This might seem like a distinction without a difference, but it's critical to making any sense out of numerous bits of Git weirdness. Everything you do, you do to, or in, your own repository.
(The one thing that's sort of an exception—but not really—is git push
. Here, you take things you have already done to/in your own repository, and offer them to another Git, which has its own repository, and then request that it do things to its repository based on what you have offered. It's up to that Git to do those things, to its own repository.)
Centralized repositories
When dealing with a central repository, the way you get stuff from them is to use git fetch
. The fetch
command calls up their Git and requests, from them, a list of their branch-names and other such references, which gives your Git their branch tip commit IDs (SHA-1 hashes). Your Git then requests any commit objects, by hash ID, and any other objects (files, or technically "blobs", tree objects, earlier commits and their trees and blobs, and annotated-tag objects) needed to complete the fetch. Your Git then squirrels all those objects away in your repository, and as a last step, renames all their branch-names to new names that your Git guarantees will not conflict with any of your branch names.
The new names your Git synthesizes from their names are your remote-tracking branches (origin/master
and so on). These are created and updated by git fetch
. If you use --prune
, or set up pruning as the default, your git fetch
operations will remove from your repository any remote-tracking branch names you have that no longer have a corresponding regular branch in that other Git. (This is sometimes useful, but is not the default, probably for historical reasons plus the "only useful if there's a lot of branch creation and deletion in the other repo" aspect.)
The origin
part of origin/master
is just the name of the remote. A remote is just a name—usually origin
, in fact, since that's the default created by git clone
—under which your Git stores the URL used for git fetch
. The name for these remote-tracking branches is constructed by putting the name of the remote in front of the remote's branch-name: hence master
becomes origin/master
, branch_A
becomes origin/branch_A
, and so on.
Why git checkout
creates branches
The long form of the command you want is:
git checkout -b branch_B --track origin/branch_B
(assuming your other, central, repository is filed away under origin
). The -b
here means "create a branch", and the --track
means: "I'm going to supply another name that I want you, my Git, to look up in my repository to find a commit hash ID. When I do that, I also want you to do the equivalent of git branch --set-upstream-to
once the branch is made." Last, of course, origin/branch_B
is the name of the (already-existing) remote-tracking branch.
This gets used a lot, so the Git folks decided to have git checkout
be extra clever: if you ask Git to check out a branch by name, and it doesn't exist, git checkout
looks to see if there's some remote-tracking branch with the same name, after stripping the remote off the remote-tracking branch name. (Whew!) That is, if you git checkout sneeze
, your Git looks to see if there's an origin/sneeze
or maybe an upstream/sneeze
or whatever.
If there's exactly one such remote-tracking branch, then git checkout
is instructed to create a local branch, using the remote-tracking branch's current hash ID as its starting point.
But the shortcut really has to be spelled exactly that way
Note that git checkout -b branch_B
doesn't make a new branch_B
starting from origin/branch_B
. It just creates a new branch_B
starting from the current commit. The new branch is also not set up to track any remote-tracking branch. This is because -b
tells git checkout
to create the branch immediately, so that it never triggers the "hey, wait, I don't have an existing branch_B
... maybe I should run some automatic special-case code instead?" code.
Of course, for the special case code to work, you must have origin/branch_B
in your repository. It won't reach out and find it on the centralized repository. Only git fetch
will do that—it's just git fetch
and git push
that actually call up another Git, using the URL stashed under the remote's name.
(In fact, git remote
will also sometimes call up another Git, but that's for other SO questions.)