What you always wanted to know about Git tracking branches but were too afraid to ask

What you always wanted to know about Git tracking branches but were too afraid to ask

The first in a series of “What you always wanted to know…” posts exploring lesser known discoveries uncovered by Clearvision’s newest Technical Consultant on his journey of onboarding and continuous improvement.

git tracking-branches-blog

The first in a series of “What you always wanted to know…” posts exploring lesser known discoveries uncovered by Clearvision’s newest Technical Consultant on his journey of onboarding and continuous improvement.

I started thinking about this topic when I was considering the differences between git pull and git fetch.

In a recent Gitminutes episode, it was suggested that git fetch is better than git pull if you are getting on a flight and will be working offline for a while, and this piqued my interest. There is a very lengthy discussion about the differences between the two commands on Stack Overflow – although arguably it is hard to read that page and come to a completely clear conclusion! I will share my conclusions regarding git fetch versus git pull later in this post.

Some of the difficulty of understanding Git questions like these has to do with terminology. I have found a really good blog post which tackles Git terminology head on, and a good example of confusing terminology in Git is the two contexts in which we talk about a tracking branch.

Context 1. The Remote Tracking Branch

It does not help that a ‘remote tracking branch’ is not really remote – it exists in your local git repo under .git/refs/remotes (e.g. .git/refs/remotes/origin/fix22)

It is also not the kind of branch we usually deal with in Git – since we cannot work on it. But it is a branch in the Git sense: a thing which points to a commit.

So just imagine there is a branch called fix22 for the repo on the remote machine (our origin) and we have not created or ever edited this branch locally.

When we communicate with the remote machine (e.g. via git fetch origin), then a local file called .git/refs/remotes/origin/fix22 will be updated (or created if not already existing). The file contains the latest commit of this branch on the remote repo.

So a remote tracking branch records the state of a branch in a remote repo, but it cannot be worked on.

Context 2. The Local Tracking Branch

Unlike the case above we can work on this branch!

It is a local branch which appears when you look at the files under .git/refs/heads

Again, imagine there is a branch called fix22 on the remote repo (our origin). If we want to work on this branch we can create a local tracking branch as follows:

git checkout --track -b fix22 origin/fix22

Or in recent versions of Git you can alternatively just type in:

git checkout fix22

and Git knows what you mean.

When we communicate with the remote machine (e.g. via git fetch origin), Git will know that this local tracking branch is associated with the branch on the remote machine, and will do the right thing when we push and pull changes.

To see what local tracking branches are configured in a repo and how they map to branches on the remote machine, you can execute:

git branch -vv

So now we have a better understanding of tracking branches, let’s go back to the similarities and differences between git pull and git fetch.

Similarities of ‘git pull origin’ and ‘git fetch origin’

Both commands update the remote tracking branches (see 1 above). That means the files under .git/refs/remotes/origin in your local repo get updated. If new branches have appeared on the remote machine, then new files appear.

Both commands will bring all the latest commits from the remote machine which I do not already have in my repo. I can later, at a convenient time decide to update my local tracking branches with this new content. In this context, the behaviour of fetch and pull is identical for branches which are not currently the active branch (checked out).

Differences between ‘git pull origin’ and ‘git fetch origin’

For git pull origin to work, a local tracking branch must be active (checked out).

git pull origin will (in addition to the git fetch operations) do an automatic merge or fast-forward of the active (local tracking) branch.

So given that git pull does everything that git fetch does – plus a little more on your active branch – I’m yet to be convinced that git fetch is a better option before you get on that long flight. If I do go for git fetch, it’s more likely to be because I would like to see what new commits are on the remote machine before merging with my local changes.

That being said, before my next flight I plan to deliberately do a git pull and see what happens…

Share on facebook
Share
Share on google
Share
Share on twitter
Share
Share on linkedin
Share

Reader Interactions