Git Developer Guide

Git says “Your branch is up to date” but the remote has new commits

The short answer: fetch first

git status never talks to the remote. Your branch is up to date with 'origin/main' means your branch matches origin/main, which is your local copy of the remote branch as of your last fetch. If someone pushed since then, Git has no way of knowing until you fetch:

git fetch
git status

Here is the same clone before and after, with one new commit on the remote:

$ git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean
$ git fetch
From github.com:acme/app
   d58a663..48aa249  main       -> origin/main
$ git status
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

git fetch only downloads commits and moves origin/main. It never changes your files or your local branches, so it is always safe to run, even with uncommitted work.

Why git status can be wrong

origin/main is a remote-tracking branch, an ordinary ref stored in your repository under refs/remotes/origin/main. In everyday use only git fetch, git pull (which fetches first) and git push move it. git status just compares your branch with that ref locally, without any network access, which is why it is instant and works offline.

So “up to date” really means “up to date with what this clone last heard from the remote”. The same is true of the ahead and behind counts it prints; see what ahead and behind mean.

It is also why git pull can bring in new commits right after git status said there was nothing to get: pull does the fetch that status never does.

git status -uno does not fetch either

A widely copied answer says to run git remote update and then git status -uno. The fetching is done entirely by git remote update. -uno is short for --untracked-files=no, which only hides untracked files from the output. On its own it gives the same stale answer:

$ git status -uno
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit (use -u to show untracked files)

git remote update fetches all your remotes, much like git fetch --all. Either one, or a plain git fetch, followed by git status works.

Check the remote without updating anything

If you want to know whether the remote has moved without touching origin/main, there are three read-only ways. All of them contact the server, so they need the network and the same credentials as a fetch.

A dry-run fetch shows what a real fetch would update, then leaves your refs alone:

$ git fetch --dry-run
From github.com:acme/app
   3ac87df..c9601d0  main       -> origin/main

No output means there is nothing new. Compare hashes: your idea of the upstream against what the server reports for that branch. Different hashes mean the remote has moved since your last fetch:

$ git rev-parse '@{u}'
3ac87dfd7ca2cbb98dd1c0b5f8abadfe38c8452e
$ git ls-remote origin refs/heads/main
c9601d08e9dd88a4c688d8383d8f0c5051aeff81	refs/heads/main

Replace main with your branch name; git rev-parse --symbolic-full-name '@{u}' prints the upstream if you are not sure what it is. git remote show origin asks the server too, and marks a branch that is behind:

$ git remote show origin
...
  Local ref configured for 'git push':
    main pushes to main (local out of date)

Stop being surprised by it

Where GitMon fits

GitMon has the same blind spot as git status, by design: it is read-only, never runs git and never fetches, and it reads the remote-tracking refs your last fetch left behind. What it adds is a view of every repository at once. Run a fetch loop, and the menu bar shows which repos are behind (↓), ahead (↑), or diverged, without visiting each one.

Download GitMon Free Trial Learn more

Related Guides