Getting to grips with git - Part 1: The basics
Introduction
I’ve been using the version control system, git (along with github) for a couple of months now, for my open source projects: grrid.js and Taskit. At Swirrl, we recently decided to take the plunge to start using git for our main code repository.
With this series of blog posts, I hope to ease the transition from subversion (or sourcesafe, or whatever) to git. In this article, I’ll just cover the basics. More advanced stuff will come later.
Why switch to git
There are several advantages to using git over other version control systems:- Being a distributed version control system, with git everyone has their own version of the whole repository. The central repository (at github in my case) is just arbitrary. This means that you can do operations such as tagging, branching and diff without having to be connected to the central server. This article by Eric Sink is a good explanation of how git differs from traditional version control.
- Due to the git:// protocol and the way git stores and tracks the data and changes in repositories, it’s really fast and the repositories don’t take up much room on disk.
- Quick, cheap, easy branching.
- The repository and branches are separate from the filesystem.
- Github. Why go to the trouble of hosting a central repository yourself, when you can do it securely, cheaply and quickly with github? There’s Sourceforge for svn, but for me Github does it better. If you can get to grips with Github, it opens up a world of possibilities for publishing or consuming open source code.
A little background about how git works
With git, the whole repository is stored in a (hidden) folder called .git at the top level of your project structure. The working tree (i.e. the actual files in your project) are just the ones you happen to be working with at the time. Git doesn’t track the files themselves, it just tracks their content along with some metadata (read more about this here).
There are a few locations for your content in git- The working tree. This is the file system, where you manually make the changes.
- The staging area, where changes lie until they’re committed.
- The repository itself, where committed changes go (you can have local and remote repositories).
Commits in git are labeled with an SHA-1 hash instead of version numbers. There’s a very small chance of the hashes ever colliding, so they can be assumed to be unique. Git actually generates a 40 character-long hash but normally the first 7 or 8 characters are enough to uniquely identify a commit.
Getting started with git
If you’re on Mac OS X like me, the easiest way to install git is to download the installer from the Google Code project. I used version 1.6.2.2. Alternatively, you can compile it from source or use Macports (see this guide).
If you want to share your code with others, you will need a centrally accessible server. Github provides just that, so go and set up an account and set up an SSH key.
Before doing anything else you should set some global parameters on your computer to tell git what your github username and email address is (you can override these on a repository basis if you like). For example:
git config --global user.name "RicSwirrl"
git config --global user.email my.email@address.comSetting up a repository
Getting code on your computer into a repository in Github
First, just make the repository via the Github web interface.
So, you have a project on your computer that you want to track using git. Initialize it by changing into its directory and running:
git initThis will create the .git folder. Change into that folder, and edit the config file therein:
cd .git
mate configMake the config look like this, using your github username and repository:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = git@github.com:<username>/<repo>.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master(Update: you can also set the config values with git commands, as someone mentioned in the comments).
You then need to add all the files in the directory to the repository as at this point they’re not being tracked by git yet. To do this, run:
git add .This will add all the files in the directory to the staging area I mentioned earlier. You can then commit these to your local repository, with a message:
git commit -m "my initial commit"Now you have a fully fledged repository on your computer. To send it up to Github, just run:
git pushNote that by default git will push to the “origin” remote repository in your config, using the current branch. If you want to push to a different remote repository, using a different branch, you can run something like:
git push github mybranch(Note: for this to work you’d have to define ‘github’ in your config file as another remote repo, and have a ‘mybranch’ branch).
Push is a similar to a subversion commit, in that it allows you to share your changes with your colleagues.
Working with a repository that’s already on Github
What if one of your colleagues has already set up the repository on Github? To get started, you just need to clone the remote repository like this (using the clone url displayed on the github page). For example:
git clone git://github.com/Swirrl/grrid.gitI suppose this is equivalent to a subversion checkout. Watch out, though, because checkout means something a bit different in git.
Working with the repository
Adding files to the staging area
You’re now ready to start making changes to your code. Once you’ve made a few changes, you can see what’s happened by running:
git statusIf you’re ready to commit some of these changes to your local repository, you need to run git add on each file you want to commit. This adds these changes to the staging area.
git add <filename_to_add>What’s the point of the staging area?
The staging area lets you choose which of your changes you want to commit – a bit like checking/unchecking files in the svn commit dialog in TextMate (or your editor of choice). You can change the files in your staging area as many times as you like, before committing.
Committing to the local repository
You can run git status again to check what’s going to be committed. When you’re happy, run:
git commit -m "my message"...and the changes will be committed. If you know you just want to commit all the changes that you’ve made, you can do it all in one go by running this (i.e. skip the staging step):
git commit -a -m "my message"Pushing your changes to the remote repository
At this point, the changes have been committed to your local repository, but the remote Github repository remains unchanged. For your colleagues to be able to see your commits you need to push them up to the remote repository with:
git pushPulling changes from the remote repository
If you want to see what your buddies have been up to, you need to pull their changes from the remote repository.
git pullThis will fetch the remote changes and merge them with your local ones. (It’s a bit like the update command in subversion).
Viewing the log
To see the history of the commits in a repository:
git logGetting Help
Many git commands can take multiple optional arguments which I haven’t covered here. To get help on the usage of any command you can do:
git help <command>Next time…
I think that’s enough information for one blog article. I’ll follow up soon with more advanced topics such as branching, merging, tagging, diff, and undoing changes.
Update: Part2: Branching and Tags is now available.