Search code examples
gitgit-fetch

Having a hard time understanding git-fetch


I am having a hard time understanding the nuances of git-fetch. I understand that doing a fetch, fetches the remote refs into a local tracking branch.

I have a few questions though:

  1. Can it be possible that a local tracking branch does not exist? If so, will it then be created automatically?

  2. What will happen if I do a fetch and specify a non tracking branch as the destination?

  3. The man page for git-fetch specifies:

    git-fetch <options> <repository> <refspec>
    

How would I use the refspec to fetch contents from my remote master into its remote tracking branch? I believe this may be possible if my current HEAD is on master and I run

git fetch origin master

However, can I use the <+?src:dest> refspec to achieve the same thing? I think this will help me understand the concepts better.

And one more question:

My .git/config file has the following line for fetching (showing only relevant lines):

fetch = +refs/heads/*:refs/remotes/origin/*

Can someone please explain what this line exactly means?


Solution

  • First, there's no such concept of "local tracking" branches, only "remote tracking" branches. So origin/master is a remote tracking branch for master in the origin repo.

    Typically you do git fetch $remote which updates all your remote tracking branches, and creates new ones if needed.

    However, you can also specify a refspec, but that will not touch your remote tracking branches, instead, it will fetch the branch you specified and save it on FETCH_HEAD, unless you specify a destination. In general you don't want to mess with this.

    Finally:

    fetch = +refs/heads/*:refs/remotes/origin/*
    

    That means if you do

    git fetch origin
    

    It will actually do:

    git fetch origin +refs/heads/*:refs/remotes/origin/*
    

    Which means a remote heads/foobar will be the local remotes/origin/foobar, and the plus sign means they'll be updated even if it's non-fast-forward.

    So your local origin/foobar will always be the same as foobar on the origin remote (after running git fetch). And origin/master will obviously be the same as master on the origin remote. So will all the other remote tracking branches.