Advanced Git concepts; the upstream tracking branch

Probably one of most powerful and under-utilized concepts of Git is the upstream tracking branch, and to be honest it probably was too difficult to use properly in the past, but not so much any more.

Here I’ll try to explain what it is, and how you can take the most advantage out of it.

Remote tracking branches

Before trying to understand what the upstream tracking branch is, you need to be familiar with remote branches (e.g. origin/master). If you are not, you probably want to read the section about them in the Pro Git book here.

To see all your remote tracking branches, you can use ‘git branch –remotes’.

The upstream tracking branch

Even if you have never heard of the concept, you probably already have at least one upstream tracking branch: master -> origin/master. When you clone a repository the current HEAD (usually ‘master’) is checked out for you, but also, it’s setup to track ‘origin/master’, and thus ‘origin/master’ is the “upstream” of ‘master’.

This has some implications on some Git tools, for example, when you run ‘git status‘ you might see a message like this:

# Your branch is behind 'origin/master' by 1 commit.

Also, if you run ‘git branch -vv‘:

* master 549ca22 [origin/master: behind 1] Add bash_profile

This is useful in order to keep your local branches synchronized with the remote ones, but it’s only scratching the surface.

Once you have realized that your local branch has diverged from the remote one, you will probably want to either rebase or merge, so you might want to do something like:

git rebase origin/master

However, ‘origin/master’ is already configured as the upstream tracking branch of ‘master’, so you can do:

git rebase master@{upstream}

Maybe you think @{upstream} is too much to type, so you can do @{u} instead, and since we are already on ‘master’ we can do HEAD@{u}, or even simpler:

git rebase @{u}

But Git is smarter than that, by default both ‘git merge’ and ‘git rebase’ will use the upstream tracking branch, so:

git rebase

Configuring the upstream branch

So now you know that upstream tracking branches are incredibly useful, but how to configure them? There’s many ways.

By default, when you checkout a new branch, and you are using a remote branch as the starting point, the upstream tracking branch will be setup automatically.

git checkout -b dev origin/dev


git checkout dev

If the starting point is a local branch, you can force the tracking by specifying the –track option:

git checkout --track -b dev master

If you already created the branch, you can update only the tracking info:

git branch --set-upstream-to master dev

There’s a very similar option called –set-upstream, however, it’s not intuitive, and it’s now deprecated in favor of –set-upstream-to, to be sure and avoid confusion, simply use -u.

You can also set it up at the same time as you are pushing:

git push --set-upstream origin dev

Finally, you can configure Git so they are always created, even if you don’t specify the –track option:

git config --global branch.autosetupmerge always


So there you have it, go nuts and configure the upstream branch for all your branches 😉

git branch --vv with upstream


8 thoughts on “Advanced Git concepts; the upstream tracking branch

  1. Neat. However, now I’m pondering on what git branch –track does, and what’s the difference?

  2. @stan It sets up the upstream tracking branch, as I explained. However if the starting point is a remote, –track is done automatically, so you only need it explicitly for local branches. I explained that.

  3. Pingback: Using Git with triangular workflows; tips, tricks, and more | Felipe Contreras

  4. I’m trying to setup a generic bugfix workflow with bash scripts and stumbled on this blog post as a result.

    Each of our team members fork an upstream repo and work on branches in our forks, submitting pull requests when we’re ready to integrate. Naturally, I thought it made sense to branch directly off the upstream master, but I have an uneasy feeling about automating this for some reason. Can you identify anything stupid happening here?

    1. git checkout -b bug upstream/master
    2. work work work
    3. git pull
    4. git push my-fork
    5. open pull request on upstream
    6. git rev-list –count –left-right upstream/master…HEAD
    7. wait until N behind and 0 ahead
    8. git checkout master
    9. git branch -d bug
    10. git push my-fork :bug

    I’ve read that #3 is lame, so I assume that should be replaced with a fetch and a rebase? Is that right? Anything else you’d recommend?


  5. Pingback: Setup a MEAN.JS project. Learn some advanced git. – 热前端

  6. @Denny You are right `git pull` has too many issues, it’s better to fetch and rebase. Also, you need to fetch before `git rev-list`, and I think there are better options, like `git merge-base –is-ancestor`, or even simply `git log upstream/master…`. Also, if you followed my blog post, you now know you can use `@{upstream}..` instead.

  7. Pingback: 为什么我需要做’设置上游’所有的时间? – CodingBlog

  8. Hi, i’d like to ask you what are the cases when and when not to set upstream remote branch for local branch or to leave master upstream for local branches… what is the correct workflow?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s