Search code examples
gitgit-configgit-rev-parse

How do Git's @{upstream} and @{push} differ?


What's the difference between a Git branch's @{upstream} and the newer @{push}?

As I understand it @{upstream} is the branch's upstream tracking ref, and @{push} is the ref a push will push to. To my intuition those are the same thing. Checking several handy branches git rev-parse @{upstream} is the same as git rev-parse @{push}, and (I thought possibly one would not resolve in the same way) git rev-parse --abbrev-ref @{upstream} is the same as git rev-parse --abbrev-ref @{push}.


Solution

  • @{upstream} and @{push} indeed point to the same thing... when they do.

    Jokes aside, I mean this is only coincidentally true, it's a consequence of two config entries pointing to the same remote, but they could be different.

    There's an excellent example on this page.

    Specifically, this part :

    The suffix @{push} reports the branch "where we would push to" if git push were run while branchname was checked out (or the current HEAD if no branchname is specified). Since our push destination is in a remote repository, of course, we report the local tracking branch that corresponds to that branch (i.e., something in refs/remotes/).

    $ git config push.default current
    $ git config remote.pushdefault myfork
    $ git switch -c mybranch origin/master
    
    $ git rev-parse --symbolic-full-name @{upstream}
    refs/remotes/origin/master
    
    $ git rev-parse --symbolic-full-name @{push}
    refs/remotes/myfork/mybranch
    

    Note in the example that we set up a triangular workflow, where we pull from one location and push to another. In a non-triangular workflow, @{push} is the same as @{upstream}, and there is no need for it.