git - push current vs. push upstream (tracking)

The question is what are you pushing, and to where:

  • current:

    • "what" is only your current branch (no other branches),
    • "to where" is a branch of the same name (created if it doesn't exist) in the upstream repo.
  • upstream:

    • "what" is also only the current branch,
    • "to where" is to whatever branch (not necessarily of the same name) on the upstream repo has been assigned as an upstream branch for the local branch you are pushing.

As explained here, Git2.0 will additionally introduce a new default for push.default: simple

simple is like upstream, but the upstream has to have the same name as well or the push will fail.


Pushing only one branch (with the mode "simple", "current" or "upstream") avoids the scenario where all matching branches are pushed (mode "matching", which was the default for a long time), even though some of your branches might not be ready to be pushed.

(master)> git push
...
To [email protected]:jkubicek/my_proj.git
   21b430d..dd378ca  master -> master
 ! [rejected]        release -> release (non-fast-forward)
error: failed to push some refs to '[email protected]:jkubicek/my_proj.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. 
hint: If you did not intend to push that branch, you may want to
hint: specify branches to push or set the 'push.default' configuration
hint: variable to 'current' or 'upstream' to push only the current branch.

The difference between the two (current and upstream) is in the pull (what to pull from the remote to your branch?):

  • pushing "current" doesn't mean that your current branch B has remote/B has its upstream branch.
    Ie: branch.B.merge isn't set, when your are pushing the "current" branch.
    Ie: when pulling to B, git won't know what branch to pull.

  • pushing "upstream" means that your current branch B has remote/B has its upstream branch.
    Ie: branch.B.merge is set, when your are pushing the "upstream" branch.
    Ie: when pulling to B, git knows what branch to pull (as well as which remote repo: branch.B.remote)


push.default is best covered in the man page of git config (man git-config).

To understand the difference between “upstream” and “current” for push.default, you should know the term upstream:

Upstream is a local pointer from a normal local branch to a local remote-tracking branch. (Yes, these are all local.) Examples:

  • branch blabla has origin/blabla configured as upstream (very common)
  • branch blabla has origin/foo as upstream (branch has a different local name; not so common)
  • branch blabla has origin2/foo as upstream

Note that origin/* branches are local and (re-)set on each fetch from origin. These are called “local remote-tracking branches”. They represent the state of the branches on the remote “origin” at the time of the last fetch.

Each (normal) local branch can have an upstream configured, but this is no must: the configuration of an upstream relationship is only for convenience for some git commands!

If you do a git status for example, git tells you “x commits behind/ahead” if it knows the upstream (so git can compare to it).

A normal initial git checkout blabla usually sets up the upstream configuration for you (if origin/blabla exists, it is checked out and setup as upstream – otherwise the checkout fails).

git push can also use the upstream configuration of a branch, i.e. to copy your new commits over to the remote branch which represents upstream. (This is push.default = upstream.)

push.default = current lets a git push copy the new commits over to the remote under the same name. It completely ignores the upstream configuration. – If your local branch name is always the same as the remote one, both configurations have the same effect, except that git push with push.default = upstream will fail, if upstream is not configured yet.

PD: Yes, * in the output of git branch shows the current branch.

Tags:

Git