Subject: [Bug] branch.*.merge interpreted too strictly by tracking logic

From: Junio C Hamano <[email-masked]>
Date: Tue, 04 Feb 2014 14:49:16 -0800

Start from an empty repository like so:

    : gitster track; git init
    Initialized empty Git repository in /var/tmp/x/track/.git/
    : gitster track/master; git commit --allow-empty -m initial
    [master (root-commit) abdcd1c] initial
    : gitster track/master; git branch foo
    : gitster track/master; git branch bar
    : gitster track/master; git commit --allow-empty -m second
    [master 78e28f4] second

Now, 'master' has two commits, while 'foo' and 'bar' both are one
commit behind, pointing at 'master^1'.

Let's tell these branches that they are both supposed to be building
on top of 'master'.

    : gitster track/master; git config branch.foo.remote .
    : gitster track/master; git config branch.foo.merge refs/heads/master
    : gitster track/master; git config branch.bar.remote .
    : gitster track/master; git config branch.bar.merge master

The difference between the two is that 'foo' spells the @{upstream}
branch in full (which is the recommended practice), while 'bar' is
loose and asks for 'master'.

Let's see what happens on these two branches.  First 'foo':

    : gitster track/master; git checkout foo
    Switched to branch 'foo'
    Your branch is behind 'master' by 1 commit, and can be
    fast-forwarded.
      (use "git pull" to update your local branch)
    : gitster track/foo; git pull
    From .
     * branch            master     -> FETCH_HEAD
    Updating abdcd1c..78e28f4
    Fast-forward

The 'checkout' correctly reports that 'foo' is building on (local)
'master'.  'pull' works as expected, of course.

Now, here is the bug part.  The same thing on 'bar':

    : gitster track/foo; git checkout bar
    Switched to branch 'bar'
    Your branch is based on 'master', but the upstream is gone.
      (use "git branch --unset-upstream" to fixup)

It knows about 'master', but what is "the upstream is gone"?  It is
our local repository and it definitely is not gone.

But 'pull' of course works as expected (this behaviour is older and
stable for a long time since even before @{upstream} was invented).

    : gitster track/bar; git pull
    From .
     * branch            master     -> FETCH_HEAD
    Updating abdcd1c..78e28f4
    Fast-forward

I suspect that the real culprit is somewhere in wt-status.c

    : gitster track/bar; git status
    On branch bar
    Your branch is based on 'master', but the upstream is gone.
      (use "git branch --unset-upstream" to fixup)

    nothing to commit, working directory clean

Resolving @{upstream} works just fine for both.

    : gitster track/bar; git rev-parse --symbolic-full-name foo@{upstream}
    refs/heads/master
    : gitster track/bar; git rev-parse --symbolic-full-name bar@{upstream}
    refs/heads/master

Thanks.