Git Resources

Git, though remarkably handy and powerful, is also remarkably hard to use sometimes. Though you can learn the basics easily enough, it can be really tough to dig yourself out of certain corners if you don’t understand what’s going on under the covers.

This page provides links to documents, how-tos, cheat sheets, tips, and tricks related to learning and using git.

How to clone our apps  

$ git clone git[at]dev.37signals.com:[application].git


Tips & Tricks  

Creating a remote repository 11 Jun 2008

First, create a bare remote repository on the remote server:

$ sudo -u git mkdir -m 775 /u/git/plugins/plugin_name.git
$ cd /u/git/plugins/plugin_name.git
$ sudo -u git git --bare init --shared=group

On your machine, cd to where your project is, create a new local repository and track the remote repository:

$ cd /path/to/project
$ git init
$ git remote add origin git@dev.37signals.com:plugins/portfolio.git

Make a change, add it to the index, and commit it:

$ touch .gitignore
$ git add .
$ git commit -m "Initial commit"

Finally, push to the remote repository:

$ git push --all

Anyone will be able to clone and track the remote repository:

$ git clone git@dev.37signals.com:plugins/plugin_name.git

Creating a remote branch 11 Jun 2008

Local branches are fine for small projects, but if you need to collaborate with others, you can create a remote branch. Start by creating a local branch in your repository:

(master)$ git branch peopleflow

At this point, the branch is just in your local repository. To push the branch to the central repository, run:

(master)$ git push origin peopleflow

Now others will see this branch when they run git branch -r.

Switching to a remote branch 28 Apr 2008

$ git checkout -b {local_branch_name} {remote_branch_name}

e.g.

$ git checkout -b v1-stable origin/v1-stable

This will checkout the v1-stable branch in the “origin” remote repository, and will put it in a new local branch called “v1-stable”. By default, git will cause this branch to “track” the remote branch (meaning “push” and “pull” will work as epxected, pushing to or pulling from that remote branch).

Removing a remote branch 28 Apr 2008

Most places on the web will tell you this isn’t possible, but one blog gave this helpful little tip:

$ git branch -d {your_branch_here}
$ git push {repository} :heads/{your_branch_here}

Where {repository} is a full repository spec, or a name for such a repository in .git/config (e.g., origin, etc.)

Converting a Subversion repository to Git 29 May 2008

Assuming we’re converting ExampleApp to git:

  1. mkdir /path/to/exampleapp-git.tmp
  2. cd /path/to/exampleapp-git.tmp
  3. git-svn init file:///u/repos/exampleapp --no-metadata --trunk=trunk --branches=branches --tags=tags
  4. git config svn.authorsFile /path/to/authors.txt
  5. git-svn fetch

The authors.txt file mentioned above is the file attached, below. Note that for large repositories, the ‘fetch’ command here can take quite some time (Basecamp took almost an hour and a half).

Once the fetch finishes, we just need to do some cleanup. First, let’s kill all of the remote tracking branches that we no longer need.

  1. git branch -r
  2. git branch -r -d stale-branch stale-branch …

Where “stale-branch” is the name of a remote-tracking branch that we no longer need.

Next, we can run prune to get rid of any orphaned objects, and gc to clean things up:

  1. git prune
  2. git gc

Then, we can repack everything optimally:

  1. git repack -f -a -d --depth=500 --window=500

Finally, we check out any remote tracking branches, so that when we later push to the final repository location, the branches get remembered:

  1. git checkout -b branch-name branch-name

The branch-name is specified twice because the first one is the name you want to give the local branch, and the second is the name of the remote branch you want to track. Do the above for each branch (“branch-name”) that you want to keep.

Note that if the branch that was checked out upon completion of the fetch was not the master (trunk), then you’ll need to use “git branch -m” to rename the current branch to what was actually checked out, and then checkout trunk as master (git checkout -b master trunk).

Once that is done, we can create our new “bare” repository, where we will all push to and pull from:

  1. cd /u/git
  2. sudo -u app mkdir -m 0770 exampleapp.git
  3. cd exampleapp.git
  4. sudo -u app git --bare init --shared=group

Then, we move back to our converted repository, and push it all to our bare repository:

  1. cd /path/to/exampleapp-git.tmp
  2. git push --all /u/git/exampleapp.git

The “--all” flag tells git that we want to push all branches, not just the current branch. Once that is done, you should be able to clone the new repository from your local machine:

  1. git clone ssh://{repo-server}/u/git/exampleapp.git

Done!

Files  

Git from the Bottom Up is kind of an “anti-How-To”. It walks you through the fundamental concepts and shows you how they fit together. It’s a great compliment to the higher-level, command-oriented git tutorials. (Via http://www.newartisans.com/blog_files/git.from.bottom.up.php)