The final piece of Git I’ll be covering is using shared remote branches. This can be helpful if you have a team working on a development and a release branch, among other scenarios.

I’ll start by setting up a central repository and two working repositories based off it. I’ll be supplying an extra argument to the clone command to make things less confusing, this gives the name of the directory in which to check out the branch. For example, “git checkout first.git” (no argument) checks out into a directory called “first”. Using “git checkout first.git second” will check out into a directory called “second”.

Kleinschs-Macbook:tmp nick$ mkdir first.git && cd first.git
Kleinschs-Macbook:first.git nick$ git --bare init --shared
Initialized empty shared Git repository in /Users/nick/tmp/first.git/
Kleinschs-Macbook:first.git nick$ cd ..
Kleinschs-Macbook:tmp nick$ git clone first.git second
Initialized empty Git repository in /Users/nick/tmp/second/.git/
warning: You appear to have cloned an empty repository.
Kleinschs-Macbook:tmp nick$ cd second
Kleinschs-Macbook:second nick$ echo 'First file contents' > file1
Kleinschs-Macbook:second nick$ git add file1
Kleinschs-Macbook:second nick$ git commit -am'added first file'
[master (root-commit) 19b39e3] added first file
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file1
Kleinschs-Macbook:second nick$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 243 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /Users/nick/tmp/first.git
 * [new branch]      master -> master
Kleinschs-Macbook:second nick$ cd ..
Kleinschs-Macbook:tmp nick$ git clone first.git third
Initialized empty Git repository in /Users/nick/tmp/third/.git/

Now that I have two working repositories, I’ll go create a release branch on the second repository.

Kleinschs-Macbook:tmp nick$ cd second
Kleinschs-Macbook:second nick$ git checkout -b release
Switched to a new branch 'release'
Kleinschs-Macbook:second nick$ echo 'Second file contents' > file2
Kleinschs-Macbook:second nick$ git add file2
Kleinschs-Macbook:second nick$ git commit -am'added file2'
[release 48a00ee] added file2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file2

Since I have this release branch, I’d like to expose it to the rest of the team so that everyone is looking at the same version. Adding a branch is as simple as doing a push with the name of the new branch. In this example, I’m telling Git to push to a remote branch that doesn’t exist, so it creates it.

Kleinschs-Macbook:second nick$ git push origin release:release
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 292 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /Users/nick/tmp/first.git
 * [new branch]      release -> release

Listing the branches will show that the branch was created on the remote repository as well.

Kleinschs-Macbook:second nick$ git branch -a
  master
* release
  remotes/origin/master
  remotes/origin/release

Now let’s go over to the third repository and make sure we can access the release branch. First we do a pull to make sure we have the latest data from the remote server.

Kleinschs-Macbook:second nick$ cd ../third/
Kleinschs-Macbook:third nick$ git pull
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /Users/nick/tmp/first
 * [new branch]      release    -> origin/release
Already up-to-date.
Kleinschs-Macbook:third nick$ ls
file1

We’re still not seeing the second file that was checked in on the release branch. This is because we’re still on the master branch at this point. In order to access the remote release branch, we need to create a local tracking branch for our changes. A tracking branch is a local branch that’s set up with a remote branch so that pushes and pulls go to the corresponding remote branch. In order to set up a tracking branch, just supply the “–track” flag to the branch command.

Kleinschs-Macbook:third nick$ git branch --track release origin/release
Branch release set up to track remote branch release from origin.
Kleinschs-Macbook:third nick$ git checkout release
Switched to branch 'release'
Kleinschs-Macbook:third nick$ ls
file1	file2

As you can see, we received the second file that was checked in on the release branch, so we should be ready to go. There’s one more thing I’d like to clear up. What if you have an existing branch that you’d like to have track a remote branch? The easiest way to do this is to edit your Git config file. Outputting the config from the the third repository will make this a little more clear.

Kleinschs-Macbook:third nick$ cat .git/config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
[remote "origin"]
	fetch = +refs/heads/*:refs/remotes/origin/*
	url = /Users/nick/tmp/first.git
[branch "master"]
	remote = origin
	merge = refs/heads/master
[branch "release"]
	remote = origin
	merge = refs/heads/release

The section for branch “release” has the relevant information. If you wanted to set up the second repository so its release branch was tracking the remote release branch, you just need to add these three lines to second/.git/config.

This concludes my series on Git. There’s a lot more to it than these four articles describe, but this should be a good jumping off point.