94

The man page for git-config lists these options for push.default:

nothing - do not push anything.
matching - push all matching branches. All branches having the same name in both ends are considered to be matching. This is the default.
upstream - push the current branch to its upstream branch.
tracking - deprecated synonym for upstream.
current - push the current branch to a branch of the same name.

In most cases I would assume that pushing to a branch's upstream branch would be the same as pushing to a branch of the same name, since the upstream branch would normally have the same name, and since the branch of the same name ("current") would normally (or always, by definition?) be upstream. So what's the difference?

UPDATE: The man page for git-config has been updated (as one would expect), so the distinctions made there may be a lot clearer now.

iconoclast
  • 21,213
  • 15
  • 102
  • 138
  • 2
    for developers it's indeed annoying to differ these, so 'simple' is introduced, and will be the default bahavior for git-push. actually it's appeared in [git 1.7.11](https://raw.github.com/git/git/master/Documentation/RelNotes/1.7.11.txt) – xhlwill Dec 27 '12 at 09:21
  • 15
    For more on the recent git warning `push.default is unset; its implicit value is changing in Git 2.0` and about `matching` vs `simple` see http://stackoverflow.com/questions/13148066/warning-push-default-is-unset-its-implicit-value-is-changing-in-git-2-0 – Nate Feb 11 '13 at 17:30
  • iconoclaust: I don't think my edit changed the integrity of the question at all, and out-of-date information just needs to be fixed. Why make the user do the extra work of clicking the link? – Flimm Nov 22 '13 at 15:50

2 Answers2

77

You've summarized the difference in your question. upstream pushes to the configured upstream branch, while current assumes the upstream branch has the same name as the current local branch, and pushes to that specific name. In reality, there's no reason to assume a local branch's upstream tracking branch has the same name as the local branch itself.

For example, if you work in multiple repositories or across many shared developer remotes, you often end up tracking different forks of the same branch, such as allen-master or susan-master, both of which track the master branch in Allen and Susan's repos, respectively. In this case, current would be the incorrect setting, because those branch names don't exist on their remotes. upstream, however, would work just fine.

A more practical example might be tracking both a development and production repository. Your workflow might use a different mainline branch for each, but that might get confusing. Suppose you were a code integrator and wanted to track both repositories' master branches separately.

git checkout -b production --track production/master
git checkout -b development --track development/master

Now you've got two branches that track their respective repositories, neither of which use the master naming convention at all. There's little confusion about the branch names: They explicitly describe what they track. Nevertheless, push.default = current wouldn't make any sense as neither remote contains a development or production branch.

iconoclast
  • 21,213
  • 15
  • 102
  • 138
Christopher
  • 42,720
  • 11
  • 81
  • 99
  • 6
    You're giving two examples for when `upstream` is preferred over `current`. I think it is pretty obvious, so you should rather give an example for the opposite case. – AndreKR Aug 02 '13 at 00:49
  • 2
    @AndreKR AFAIK `current` is better in the case that you're a new-ish developer because you don't need to `git config` much especially if you've cloned from somewhere. `current` pushes to or creates-then-pushes-to homonymous branches on the remote repo *for you* if they don't exist already, whereas `simple` will refuse to do this outright when a same-named branch does not exist already. `upstream` has the same behavior in this case unless an upstream branch has been explicitly set or otherwise set as mentioned in [Yawar](http://stackoverflow.com/users/20371)'s answer. – Seldom 'Where's Monica' Needy Jul 23 '15 at 18:27
  • "In reality, there's no reason to assume a local branch's upstream tracking branch has the same name as the local branch itself." -> It's up to your team's git policy. I know some large firm prevents forking due to company policy, even they have a large dev team. In this case just use `current`. – superarts.org Oct 26 '22 at 14:07
7

current will push the current branch to a branch with the same name on the remote repo.

upstream will push the current branch to the upstream branch.

The upstream branch is a branch which has been explicitly or implicitly defined as being upstream from your current branch. That means that push and pull by default will sync with this branch. The upstream branch may be in the same repo as the current branch itself. You can do interesting things like set up your local master branch as upstream from your local feature (topic) branch, and push and pull between them.

Implicit upstream setup is done through the branch.autosetupmerge config value. You can find documentation in the git config help page. Explicit upstream setup is done with the -u option to the git branch command. See the help page for details.

Yawar
  • 11,272
  • 4
  • 48
  • 80
  • I don't think `branch.autoSetupMerge` does the same think as `-u`/`--set-upstream`. At least, I see nothing in [the documentation](https://git-scm.com/docs/git-config#Documentation/git-config.txt-branchautoSetupMerge) implying that it makes git push behave as if it was called with `-u` by default, which it what it seems to me you are saying. Can you clarify what you meant? – waldyrious Mar 15 '19 at 13:50
  • @waldyrious sure; when you are checking out a remote tracking branch, the `branch.autoSetupMerge` config by default creates a new local branch and sets its upstream as the remote tracking branch. This implicit action can be explicitly done by using either the `-t` (`--track`) or `-u ...` (`--set-upstream-to=...`) flags, which do the same thing with slightly different syntaxes. – Yawar Mar 16 '19 at 02:55
  • 2
    I see what happened here — since this question is about `git push`, I (mistakenly) assumed you were speaking about the `-u` option of `git push`, rather than the `-u` option of `git branch`. Sorry for the confusion :) – waldyrious Mar 16 '19 at 20:55