Home > Software engineering >  why "git fetch origin bugfix" does not work?
why "git fetch origin bugfix" does not work?

Time:11-05

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 for refs/heads/main;
  • your remote-tracking name origin/main is short for refs/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.

  •  Tags:  
  • git
  • Related