I tried this to fetch a remote branch:
% git fetch origin bugfix
And the console tells me:
From github.com:*****/sdn-prjkt
* branch bugfix -> FETCH_HEAD
Looks like it's fetched. But when I try to list all branches but it's not fetched to local:
% git branch
* main
Still in remote:
% git branch -a
* main
remotes/origin/HEAD -> origin/main
remotes/origin/bugfix
remotes/origin/main
May I know why?
CodePudding user response:
Your branches are yours. The git fetch
command obtains commits: you and they1 share the commits, which are all always, completely read-only, so they can't change yours and you can't change theirs and therefore it's completely safe to share them. But git fetch
does not get any branches.
Instead, your Git remembers their branches using your remote-tracking names. You can list these with git branch -r
, or with git branch -a
as you just did. The remote-tracking names for the remote named origin
are spelled with origin/
in front of them: origin/main
, origin/bugfix
, and so on.
For no good reason, git branch -r
shows these as origin/bugfix
but git branch -a
shows them as remotes/origin/bugfix
. The fact is that each of these names is shortened:
- your branch name
main
is short forrefs/heads/main
; - your remote-tracking name
origin/main
is short forrefs/remotes/origin/main
;
and so on. Git drops refs/heads/
from branch names when shortening them, drops refs/tags/
from tag names when shortening tag names, and drops refs/remotes/
, or sometimes just refs/
, from remote-tracking names when shortening those.
If you would like to have your own branch name, you simply tell Git: Create, for me, a new branch name bugfix
, using the same commit I just saw on their Git that they call bugfix
, which I call origin/bugfix
.
The long form of this command is:
git branch --track bugfix origin/bugfix
after which git checkout bugfix
or git switch bugfix
finds that you have a branch named bugfix
, and switches to that branch and extracts that branch's tip commit as the current commit. (Remember, each commit holds a full snapshot of every file—though in a special, read-only, Git-only, compressed and de-duplicated form—so for you to use a commit, Git has to extract its files.)
There's a shortcut, though:
git checkout bugfix
or:
git switch bugfix
starts out ready to complain that, hey, there's no branch named bugfix
, we can't possibly do that—but then, because you didn't say --no-guess
, they use what Git used to call DWIM mode to guess whether they should create a branch named bugfix
.
To guess, they look at all your remote-tracking names, as if you'd run git branch -r
. If there's exactly one that looks right—such as origin/bugfix
—they'll automatically do that git branch
command for you.2 Then, now that you have a bugfix
, they can switch to it successfully. You'll get a message about having switched to a newly created branch.
1You here means your Git software, running on your computer, operating on your repository. They means their Git software, running on their computer, operating on their repository. Note that there are two independent Git repositories here. The git fetch
operation means Call up their Git and get any commits they have, that I don't, that they are willing to hand over. Then, based on what you saw for their branch names, create or update my remote-tracking names to match their branch names.
2Whether they use git branch --track
or git branch --no-track
is actually configurable, but the default is to use --track
. Be careful with this verb track: Git overuses it a lot, so when you see it elsewhere in Git, it might refer to this, but it might refer to something else.