452

I'm apparently terrible at using git, despite my best attempts to understand it.

From kernel.org for git push:

-u

--set-upstream

For every branch that is up to date or successfully pushed, add upstream (tracking) reference, used by argument-less git-pull(1) and other commands. For more information, see branch.<name>.merge in git-config(1).

Here's branch.<name>.merge from git config:

branch.<name>.merge

Defines, together with branch.<name>.remote, the upstream branch for the given branch. It tells git fetch/git pull which branch to merge and can also affect git push (see push.default). When in branch <name>, it tells git fetch the default refspec to be marked for merging in FETCH_HEAD. The value is handled like the remote part of a refspec, and must match a ref which is fetched from the remote given by "branch.<name>.remote". The merge information is used by git pull (which at first calls git fetch) to lookup the default branch for merging. Without this option, git pull defaults to merge the first refspec fetched. Specify multiple values to get an octopus merge. If you wish to setup git pull so that it merges into <name> from another branch in the local repository, you can point branch.<name>.merge to the desired branch, and use the special setting . (a period) for branch.<name>.remote.

I successfully set up a remote repository with github, and I successfully pushed my first commit to it with:

git push -u origin master

Then, I unwittingly successfully pushed my second commit to my remote repository using:

git commit -m '[...]'

However, incorrectly thinking I would have to push again to origin from master, I ran:

# note: no -u
git push origin master

What did that do? It didn't seem to have any effect at all. Did I "undo" git push -u origin master?

ClosureCowboy
  • 20,825
  • 13
  • 57
  • 71
  • 87
    `I'm apparently terrible at using git, despite my best attempts to understand it.` - I've never had somebody recreate me so well. – dgo Apr 30 '16 at 19:06
  • 2
    It's fair to say that `git` defies any kind of (pattern based) unified understanding, simply because it's user facing interfaces are not "designed" in any coherent way. So you only "know" it by rote learning as opposed to being able to extrapolate in many cases. Here I am on SO, checking on things which should be obvious, and I've been using git since 0.x – ocodo Sep 29 '22 at 03:06

3 Answers3

429

The key is "argument-less git-pull". When you do a git pull from a branch, without specifying a source remote or branch, git looks at the branch.<name>.merge setting to know where to pull from. git push -u sets this information for the branch you're pushing.

To see the difference, let's use a new empty branch:

$ git checkout -b test

First, we push without -u:

$ git push origin test
$ git pull
You asked me to pull without telling me which branch you
want to merge with, and 'branch.test.merge' in
your configuration file does not tell me, either. Please
specify which branch you want to use on the command line and
try again (e.g. 'git pull <repository> <refspec>').
See git-pull(1) for details.

If you often merge with the same branch, you may want to
use something like the following in your configuration file:

    [branch "test"]
    remote = <nickname>
    merge = <remote-ref>

    [remote "<nickname>"]
    url = <url>
    fetch = <refspec>

See git-config(1) for details.

Now if we add -u:

$ git push -u origin test
Branch test set up to track remote branch test from origin.
Everything up-to-date
$ git pull
Already up-to-date.

Note that tracking information has been set up so that git pull works as expected without specifying the remote or branch.

Update: Bonus tips:

  • As Mark mentions in a comment, in addition to git pull this setting also affects default behavior of git push. If you get in the habit of using -u to capture the remote branch you intend to track, I recommend setting your push.default config value to upstream.
  • git push -u <remote> HEAD will push the current branch to a branch of the same name on <remote> (and also set up tracking so you can do git push after that).
dahlbyk
  • 75,175
  • 8
  • 100
  • 122
  • @dahlbyk +1 Thank you! So when I ran `git push origin master`, I simply made things ambiguous for `git pull` if I had multiple branches? – ClosureCowboy Apr 18 '11 at 02:08
  • 12
    `git push ` makes things _unambiguous_. If you leave off the remote or branch git falls back on the branch config settings, which are set for you with `git push -u`. – dahlbyk Apr 18 '11 at 02:12
  • 4
    @dahlbyk I've gone ahead and marked you as the answer, but that comment somewhat confuses me. In your answer, you demonstrated that git **was** confused after `git push origin test` (which doesn't have `-u`). You then showed that `git push -u origin test` **removes** the ambiguity. Is there a typo, or am I just being dense again? – ClosureCowboy Apr 18 '11 at 02:30
  • 2
    I think we're talking past each other. :) When I say `git push ` is unambiguous, I mean that relative to `git push` which relies on the branch config. Similarly, `git pull ` is unambiguous and `git pull` relies on the branch config. Once you've pushed with `-u`, both `git push` and `git pull` will work as expected. – dahlbyk Apr 18 '11 at 02:37
  • @daylbyk Thank you for taking the time to explain this! – ClosureCowboy Apr 18 '11 at 02:49
  • 12
    @dahlbyk: Your answer is fine, but in your comments above you repeat a [common misconception](http://longair.net/blog/2011/02/27/an-asymmetry-between-git-pull-and-git-push/) about `git push` - unless you set `push.default` yourself, `git push` only uses the upstream branch configuration to decide which remote to push to, not the remote branch to update. – Mark Longair Apr 18 '11 at 05:20
  • @Closure: The pull is completely separate from the push. It uses remote tracking configuration, which is not set up for locally created branches. `push -u` is simply one way to set that configuration. It's not that `git push origin master` confuses anything, it's that it just doesn't have anything to do with the subsequent pull. – Cascabel Apr 18 '11 at 05:25
  • 2
    The best practice for git is `git push origin master` and the same to other side IE. `git pull origin master` .. So If suppose branch change then you can `git push origin branch_name` and the same to other side IE. `git pull origin branch_name` – Arpit Vaishnav Dec 03 '12 at 11:33
  • Does that mean -u says git pull to pull from the same remote branch which is currently active locally? – Umair A. Mar 24 '13 at 08:41
  • 1
    @UmairAshraf the local branch that was pushed will track the remote branch it was pushed to, even if they don't match (e.g. `git push -f origin my-local:my-remote` will set up `my-local` to track `origin/my-remote`). – dahlbyk Mar 25 '13 at 21:38
  • Oops, just noticed I meant `git push -u origin my-local:my-remote` in the most recent comment. – dahlbyk Nov 23 '21 at 17:14
119
git push -u origin master

… is the same as:

git push origin master ; git branch --set-upstream master origin/master

Do the last statement, if you forget the -u!

Or you could force it:

git config branch.master.remote origin
git config branch.master.merge refs/heads/master

If you let the command do it for you, it will pick your mistakes like if you typed a non-existent branch or you didn't git remote add; though that might be what you want. :)

George
  • 25,988
  • 10
  • 79
  • 133
sabgenton
  • 1,823
  • 1
  • 12
  • 20
86

In more simple terms:

Technically, the -u flag adds a tracking reference to the upstream server you are pushing to.

What is important here is that this lets you do a git pull without supplying any more arguments. For example, once you do a git push -u origin master, you can later call git pull and git will know that you actually meant git pull origin master.

Otherwise, you'd have to type in the whole command.

Felipe Augusto
  • 7,733
  • 10
  • 39
  • 73
Adépòjù Olúwáségun
  • 3,297
  • 1
  • 18
  • 27
  • 3
    So if I set `-u` flag to `orgin master` every next pull will refer to it. And if I want to change the `git pull` behavior I should run `git push -u origin some_other_branch` and `git pull` now will refer to `some_other_branch` ? Thank you! – Toma Tomov Sep 28 '18 at 08:26
  • 3
    can we also use "git push" instead of using "git push origin master"? – cegprakash Apr 16 '19 at 14:25
  • 2
    Yes, you can @cegprakash. However, you would have initially done a `git push -u origin master` – Adépòjù Olúwáségun Apr 16 '19 at 16:24
  • 8
    I wanted a simple answer.. I feel this is the best one here!!! Others sounds too technical to understand anything for me – Mac Nov 05 '20 at 06:42