'git pull origin mybranch' leaves local mybranch N commits ahead of origin. Why?

git, git-pull, version-control

Solution

`git pull` calls `git fetch` with the appropriate parameters before merging the explicitly fetched heads (or if none the remote branch configured for merge) into the current branch.

The syntax: `git fetch <repository> <ref>` where `<ref>` is just a branch name with no colon is a 'one shot' fetch that doesn't do a standard fetch of all the tracked branches of the specified remote but instead fetches just the named branch into `FETCH_HEAD`.

Update: for Git versions since 1.8.4, if there is a remote tracking branch which tracks the ref that you asked to fetch then the tracking branch will now be updated by `fetch`. This change has been made specifically to avoid the confusion that the previous behaviour caused.

When you perform `git pull <repository> <ref>`, `FETCH_HEAD` is updated as above, then merged into your checked out `HEAD` but none of the standard tracking branches for the remote repository will be updated (Git <1.8.4). This means that locally it looks like you are ahead of of the remote branch, whereas in fact you are up to date with it.

Personally I always do `git fetch` followed by `git merge <remote>/<branch>` because I get to see any warnings about forced updates before I merge, and I can preview what I'm merging in. If I used `git pull` a bit more than I do, I would do a plain `git pull` with no parameters most of the time, relying on `branch.<branch>.remote` and `branch.<branch>.merge` to 'do the right thing'.

Problem

I just observed something odd about `git pull`, which I don't understand. On Friday, I worked on a local branch. let's call it `mybranch`. Before leaving the office I pushed it to origin (which is my github repo): `git push origin mybranch`. Yesterday at home, I `pull`ed mybranch to my laptop, did some more coding, and then pushed my changes back to github (origin). Now I'm at work again, and tried to pull the changes from yesterday to my work machine (I didn't change anything in my work place's local repo over the weekend): ``` git pull origin mybranch ``` that caused a fast forward merge, which is fine. I then did a `git status`, and it said: ``` # On branch mybranch # Your branch is ahead of 'origin/mybranch' by 6 commits. # nothing to commit (working directory clean) ``` Huh? How can it be 6 commits ahead when I didn't even touch it over the weekend, AND just pulled from origin? So I ran a `git diff origin/mybranch` and the diffs were exactly the 6 changes I just pulled from remote. I could only "fix" this by running `git fetch origin`: ``` From git@github.com:me/project af8be00..88b0738 mybranch -> origin/mybranch ``` Apparently, my local repo was missing some reference objects, but how can that be? I mean, a pull does a fetch already, and I didn't work on anything except that branch, so a `git fetch origin` and `git fetch origin mybranch` should have the same result? Should I always use `git pull origin` instead of `git pull origin branchname`? I'm confused.

Original source