Skip to navigation

Setting up a new remote git repository

Published December 05, 2007 - Updated January 09, 2008

To collaborate in a distributed development process you’ll need to push code to remotely accessible repositories.

This is somewhat of a follow-up to the previous article setting up a new rails app with git.

It's good to know how this stuff works, but this is definitely the hard way. For no fuss git repository setup (especially if you want to collaborate with others) check out GitHub.

For the impatient

Set up the new bare repo on the server:

$ ssh myserver.com
Welcome to myserver.com!
$ mkdir /var/git/myapp.git && cd /var/git/myapp.git
$ git --bare init
Initialized empty Git repository in /var/git/myapp.git
$ exit
Bye!

Add the remote repository to your existing local git repo and push:

$ cd ~/Sites/myapp
$ git remote add origin ssh://myserver.com/var/git/myapp.git
$ git push origin master

Set the local master branch to track the remote branch.

Read further for a step-by-step explanation of what’s going on.

Pre-flight sanity check

Setting up a remote repository is fairly simple but somewhat confusing at first. Firstly, let’s check out what remote repositories are being tracked in our git repo:

$ cd ~/Sites/myapp
$ git remote

None. Looking good. Now let’s list all the branches:

$ git branch -a
* master

Just one branch, the master branch. Let’s have a look at .git/config:

$ cat .git/config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true

A pretty bare-minimum config file.

Creating the bare remote repository

Before we can push our local master branch to a remote repository we need to create the remote repository. To do this we’ll ssh in and create it on the server:


$ ssh myserver.com
Welcome to myserver.com!
$ cd /var/git
$ mkdir myapp.git
$ cd myapp.git
$ git --bare init
Initialized empty Git repository in /var/git/myapp.git
$ exit
Bye!

A short aside about what git means by bare: A default git repository assumes that you’ll be using it as your working directory, so git stores the actual bare repository files in a .git directory alongside all the project files. Remote repositories don’t need copies of the files on the filesystem unlike working copies, all they need are the deltas and binary what-nots of the repository itself. This is what “bare” means to git. Just the repository itself.

Adding the remote repository to our local git repository configuration

Now that we’ve created the remote repository we’ll add it to our local repository as a remote server called “origin” using git remote add, which is just a nicer way of updating our config file for us:


$ git remote add origin ssh://myserver.com/var/git/myapp.git

Let’s see what it added to the config file:

[core]
  repositoryformatversion = 0
  filemode = true
  bare = false
  logallrefupdates = true
[remote "origin"]
  url = ssh://myserver.com/var/git/myapp.git
  fetch = +refs/heads/*:refs/remotes/origin/*

We now have a remote repository “origin” that will fetch all of it’s refs/heads/* branches and store them in our local repo in refs/remotes/origin/* when a git fetch is performed.

Pushing to the remote repository

The time has come to push our local master branch to the origin’s master branch. We do that using the git push <target> <local> command.


$ git push origin master
updating 'refs/heads/master'
  from 0000000000000000000000000000000000000000
  to   b379203bc187c2926f44a71eca3f901321ea42c6
 Also local refs/remotes/origin/master
Generating pack...
Done counting 1374 objects.
Deltifying 1374 objects...
 100% (1374/1374) done
Writing 1374 objects...
 100% (1374/1374) done
Total 1374 (delta 89), reused 0 (delta 0)
refs/heads/master: 0000000000000000000000000000000000000000 -> b379203bc187c2926f44a71eca3f901321ea42c6

and that’s all, folks. Further pushes can be done by repeating the git push command.

Now you can tell your co-conspirators to:

$ git clone ssh://myserver.com/var/git/myapp.git

and push and pull to your heart’s content.

Track the remote branch

You can specify the default remote repository for pushing and pulling using git-branch’s track option. You’d normally do this by specifying the --track option when creating your local master branch, but as it already exists we’ll just update the config manually like so:

[branch "master"]
  remote = origin
  merge = refs/heads/master

Now you can simply git push and git pull.

Sharing the remote repository with the world

If you want to set it up as a public repository be sure to check out the Git manual’s chapter on public git repositories.

Working with remote repository branches

git remote show is used to inspect a remote repository. It goes and checks the remote repository to see what branches have been added and removed since the last git fetch.

Doing a git remote show at the moment only shows us the remote repo’s master branch which we pushed earlier:

$ git remote show origin
* remote origin
  URL: ssh://myserver.com/var/git/myapp.git
  Tracked remote branches
    master

Let’s create a new local git repository and push to a new branch on the remote repository. We can then use git remote show to see the new remote branch, git fetch to mirror it into our local repo and git checkout --track -b to create a local branch to do some work on it.

We’ll start by creating a new local repo and pushing some code to a new branch in the remote repository.

$ mkdir /tmp/other-git
$ cd /tmp/other-git
$ git init
Initialized empty Git repository in /tmp/other-git
$ git remote add origin ssh://myserver.com/var/git/myapp.git
$ echo "Rails 2... woo" > afile
$ git add afile
$ git commit -m "Added afile"
Created initial commit 0ac9a74: Added afile
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 something
$ git push origin master:rails-2
updating 'refs/heads/rails-2' using 'refs/heads/master'
  from 0000000000000000000000000000000000000000
  to   0ac9a7457f4b21c9e058d4c54d262584bf35e528
 Also local refs/remotes/origin/rails-2
Generating pack...
Done counting 3 objects.
Deltifying 3 objects...
 100% (3/3) done
Writing 3 objects...
 100% (3/3) done
Total 3 (delta 0), reused 0 (delta 0)
Unpacking 3 objects...
 100% (3/3) done
refs/heads/rails-2: 0000000000000000000000000000000000000000 -> 0ac9a7457f4b21c9e058d4c54d262584bf35e528

Now let’s switch back to our old git repository and see if it detects the new branch on the remote repository:

$ git remote show origin
* remote origin
  URL: ssh://myserver.com/var/git/myapp.git
  New remote branches (next fetch will store in remotes/origin)
    rails-2
  Tracked remote branches
    master

Let’s update our mirror of the remote repository by doing a git fetch:

$ git fetch
* refs/remotes/origin/master: storing branch 'rails-2' of ssh://myserver.com/var/git/myapp.git
  commit: b379203
$ git remote show origin
* remote origin
  URL: ssh://myserver.com/var/git/myapp.git
  Tracked remote branches
    master
    rails-2

We should now be able to see this in a our list of remote branches:

$ git branch -a
* master
origin/rails-2
origin/master

If we then wanted to do some work on this remote rails-2 branch we create a new local tracking branch like so:

$ git checkout --track -b rails-2 origin/rails-2
Branch rails-2 set up to track remote branch refs/remotes/origin/rails-2.
Switched to a new branch "rails-2"

To keep up-to-date and push new changesets we simply use git push and git pull when working in the local rails-2 branch.

Also notice, like we manually changed for master, .git/config has a new entry for this new tracking branch:

[branch "rails-2"]
  remote = origin
  merge = refs/heads/rails-2

Further Reading

Sourcemage’s Git Guide has some very very handy real-life examples of git commands you’ll often need.

So now you know the hard way. For no fuss Git repository setup (especially if you want to collaborate with others) check out GitHub.

Archived comments

Comments were previously allowed on articles. Though no new comments are being accepted you can see the old comments below.

  1. Michael Koukoullis

    Okay now your making this stuff too easy ;) No more guesswork. Thanks for the post dude.

  2. Saimon Moore

    Tim,

    Have you seen gitosis ?

  3. Tim Lucas

    Michael: no problemo! ;)

    Saimon: ah good idea to point out gitosis. It’s a pretty kick-ass way to manage public git repositories. It’s probably a good idea though to know how to set up remote git repositories manually, especially as gitosis is still under heavy development.

  4. Tim Lucas

    Saimon: also I haven’t actually tried gitosis yet, though I know Dr Nic had it up-and-running at railscamp and was yelling drunken praise

  5. Justin

    Super simple. I had no idea. I’m inching ever-closer to trying out git for myself…

  6. Nico

    There’s a minor bug in your instructions, I followed them to the letter and they did not work. You apparently cannot fetch from an empty repository, you have to push something into it first. In other words, your ‘push’ instructions should have come before your ‘fetch’ instructions.

  7. Tim Lucas

    Nico: thanks you’re right. I’ve restructed the entire article so it’s now correct, as well as fleshing out how to interact with remote repositories.

  8. Chris

    Wow, thanks a bunch. This was helpful.

  9. Ben Poweski

    Excellent write up.

    Thanks!

  10. Maruis Marais

    Do you know how to create a bare repo without ssh’ing to the remote server? I’m trying to write a cap task to automate this process…

  11. Sean

    Hey thanks for the article, very useful. Bookmarked for safe keeping! :)

  12. rxKaffee

    M. Marais. Unless your remote shell is setup as the limited git-sh, you should be able to run a remote command over non-interactive ssh from your automation script. Something along the lines of …
    ssh gituser@myserver.com “REP=code.git; mkdir $REP; cd $REP; git —bare init;”

  13. Wladimir

    Thank you very much, using git is still like talking Chinese to me sometimes, but articles like this help a lot if I actually want to get stuff done :)

  14. walter

    any idea how to add the ssh port number during git remote add origin, and, git push origin branchname? Tried -p port : etc

  15. Adam

    walter: you can specify port as usual in the URL;

    ssh://foo.com:9999/foo.git

    Tim: thanks a bunch for this guide, I’m really starting to enjoy using git and this is an invaluable quick reference!

  16. Jagtesh Chadha

    It was very helpful! Thank you Tim :-)

  17. steve c

    Hey, don’t know if you can help with this but when I do the push command I get this: (I have to C-c to stop it, it just “hangs”)

    $ git push origin master
    Counting objects: 3, done.
    Writing objects: 100% (3/3), 208 bytes, done.
    Total 3 (delta 0), reused 0 (delta 0)

    I know it’s connecting fine, if I change the remote origin to something that is not a git repo it errors out, I just don’t know how to change this >.>

  18. Arturs Aboltins

    Very helpful article. Explanation what goes in config files helped me a lot. Thanks! Good luck to you.

  19. Abhijit Bera

    Fantastic tutorial! Definitely the best guide I have come across. Even a first timer can follow this.

  20. sr

    I wrote a bash function to automate the process. http://gist.github.com/7531

  21. Todd Werth

    Many thanks; well written and very helpful.

  22. Graham Ashton

    Cracking post – just what I was looking for, thanks.

  23. Gujjugeek

    Really helpful for a git novice like me. I spent majority of y’day trying to figure out a way to work with branches. didn’t know it was so simple! thanks again.

  24. dekita

    This guide does a great job of covering the essential features of day to day git usage. Thanks!

  25. Mark McBride

    Tim, great article! I cited you in an article I wrote specific moving Rails apps from Subversion. One thing that stumped me when following your guide was how to push back to a remote branch that had been checked out locally and given a different name. I threw up some notes on my blog about how to git push to a remote branch with a name that doesn’t match the local branch name. I how it helps other trying to do the same.

  26. Jamie Hill

    Instead of editing the config file manually to add the origin server, you could run:

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

    I have a fear of manually editing anything in the actual repository :)

  27. Gabriel

    Thanks a lot for the post, it was helpful.

    I was trying to setup a public repo that people could get at via http – and to do that, you need to do two more commands on the remote repo:

    $ git —bare update-server-info
    $ mv hooks/post-update.sample hooks/post-update

    (the second command didn’t work for me – the hook was already in the right place)

    This is from the git documentation:
    http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#public-repositories

  28. Gabriel

    One addendum to my prior comment: you need to mark the post-update hook as executable:

    chmod +x hooks/post-update

Thoughts

toolmantim

I’m Tim Lucas, a user experience developer currently in Sydney Australia.

I occasionally write, snap photos, present on various technical topics, tweet my going-ons, share teh codes and post tidbits to the scrapbook.

Most recently I published Simplifying ticket sales on sydneyoperahouse.com (February 16, 2010)

Work with me via Agency Rainford, or shoot an email to and say hello.

Powered by complication and elaboration