0

I have a non-tracking branch named "master".

I have a remote branch on Github named "master".

Creating a tracking branch for tracking the remote branch is recommended because it allows you to do push/fetch much more easily, because it saves you from explicitly specifying the "remote repo name" and the "local-branch-to-push" on your next push/fetch.

So there are two ways to do it:

1st way

"master" branch -> origin/master" -> "remote master branch"

This is done using "git push -u"

Why do I need to explicitly push a new branch?

2nd way

"master" branch can directly track "remote master branch"

Make an existing Git branch track a remote branch?

Is one way better than the other, or it`s just a matter of style?

Community
  • 1
  • 1
Qwerty
  • 748
  • 1
  • 9
  • 25

1 Answers1

2

Functionally, they both result in the same thing. When I try both styles, they result in the same configuration.

$ git push -u origin 1st:master
Counting objects: 3, done.
Writing objects: 100% (3/3), 261 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /Users/schwern/tmp/test-repo
   71f7d8f..6729320  1st -> master
Branch 1st set up to track remote branch master from origin.

$ git branch -u origin/master
Branch 2nd set up to track remote branch master from origin.

$ cat .git/config
...
[remote "origin"]
    url = /Users/schwern/tmp/test-repo
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master
[branch "2nd"]
    remote = origin
    merge = refs/heads/master
[branch "1st"]
    remote = origin
    merge = refs/heads/master

There is no "direct" tracking of remote branches. Git remote branches are regular branches in your repository that happen to be updated from a remote repository. "Tracking" tells one branch to push and pull from another.

git push sends changes to the remote. git branch -u tells a branch what to track. git push -u is basically git push plus git branch -u.

From an interface perspective, git branch -u remote/branch is a bit safer. It's more explicit, less magical. Case in point, when I was setting up this example I tried this...

$ git branch
* 1st
  2nd
  master
$ git push -u origin master
Branch master set up to track remote branch master from origin.
Everything up-to-date

1st was ahead of master and origin/master and should have pushed changes, but it didn't. It took me awhile to realize that git push -u origin master was pushing master and not 1st. Whoa, it wasn't pushing the current branch! This is because the master part refers to the remote destination branch, and Git guessed the local source branch was also master, not my current branch. This behavior will change depending on what version of Git you have and how you have it configured.

This is why I did the more explict git push -u remote local_source_branch:remote_destination_branch syntax. git push -u origin 1st:master.

In general, recent versions of Git should take care of this for you IF you branch directly from a remote. This is controlled by branch.autosetupmerge which defaults to true.

$ git co -b 3rd origin/master
Branch 3rd set up to track remote branch master from origin.
Switched to a new branch '3rd'

IMO that is the safest way to set up remote tracking branch.

PS You can play around with remotes without needing a new server. A remote doesn't have to be a URL, it can be a directory. It just has to be a bare repository (ie. no checked out files). git init --bare /path/to/somedir and then git clone /path/to/somedir.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Hi. If I turned the non-tracking branch to be a TRACKING branch, does this mean that a new "origin/master" branch has been created, and this branch does the tracking? I thought that there are two ways to do it. Based on your input, only the 1st way exist. The 2nd way does not exist at all. Correct? – Qwerty May 16 '15 at 18:27
  • @Qwerty Rather than turning a non-tracking branch into a tracking branch, it's better to think of it as telling one branch to track another. If the branch you want to track doesn't exist, you cannot track it. Git will explain that if you run `git branch -u origin/does_not_exist`. You have to first create the remote branch. `git push remote src:dest` will make the remote branch. If you add `-u` it also adds tracking. You can think of `git push -u` as `git push` (send changes to the remote) plus `git branch -u` (add tracking). – Schwern May 16 '15 at 18:57
  • Thanks. However, I still don`t understand one thing. If I use "git branch -u" for local master branch, will this cause a new "origin/master" branch to be created? who is doing the tracking: the LOCAL master branch or the "origin/master" branch which was created? – Qwerty May 16 '15 at 19:06
  • Actually `master` refers to the local branch on `push` (it's the refspec part of `git push `). For fetch, a refspec is parsed as `:` and if the local part is omitted it defaults to empty, but for push, it's parsed as `:` and if the remote part is omitted it defaults to ... well, an overly-complex algorithm described vaguely in the push documentation, bless git's gitty little heart. :-) – torek May 16 '15 at 19:56
  • @Qwerty: (re latest comment) this is where git's naming leaves something to be desired. A (local) branch is said to be "tracking" something if it has both a `remote` and a `merge` in the config as Schwern showed. At the same time, your branches that are named `refs/remotes/origin/*` are called "remote-tracking branches". So "tracking" is overloaded—as is "branch" as well! Also, `git branch -u` or `git branch --set-upstream-to` won't create any names, it only updates the `remote` and `merge` values for an existing (local) branch. – torek May 16 '15 at 20:02