My Morning With Git and Submodules

I spent this morning moving a project over from svn to git and setting up a git submodule for a library project. I spent far too long doing it and made far too many silly mistakes that cost me lots of times. So I am going to outline below my steps for setting up a new project with git, and then adding an existing submodule. This is a long way from a definitive guide to git, I expect you to already have a basic understanding of git. I wouldn't even call it a complete guide to setting up a new project with git, it's more of a don't forget these steps and do it in this order sort of thing.

If you've not already installed git, you probably wanna do that first. Visit the git website to download the latest version.

Just a warning, you will be using the command line so a little bit of basic command line knowledge is needed, i.e. you should know how to move around directories, move files, delete files, nano/vim etc. I've never found setting up a new git project using a git GUI works very well so I tend to do all my setup with the command line tools and then use gitbox once everything is ready.

So the first thing you're gonna want to do is make a folder for your project... (obviously). Then change to that directory on the command line. Now run the command

git init

This will turn this folder into a git repo. If you have already got a project setup on a server then don't create a new git project, instead clone the repository

git clone username@server:project/path

So if you were me and you wanted to clone my android tools repo from github you would run

git clone git@github.com:fry15/uk.co.jasonfry.android.tools.git

Notice that the username for github is always git@github.com, this is just the way they have there system setup. You can find the url to your github project on your github project page and if you've setup your own git server then you should know the address...

Now add all your files to the folder.

The next step is VERY important and one I always forget to do, there will be certain files you don't want to track, e.g. compiled binary files. Make a new file in your project root called '.gitignore' and add the file and folder names you want to ignore to this file. For more information check out the gitignore documentation or have a look at these templates. Why is this so important to do first? Because if you did this after you had added files then git will continue to track files that have been added even if .gitignore is saying to ignore them.

Now you'll want to let git know what files to watch, the likely scenario is all the files, excluding the ones you've put in the gitignore file. Run this command

git add .

Now you'll want to commit these changes locally

git commit

Note the files haven't been pushed to a server anywhere yet...

If you started by cloning a remote repo rather than initialising a new one then you can skip this step. If you've got your own git server then I expect you to already have made a remote repo, if you're planning on using github then this page is your friend.

The key command is the one to add the remote server to the config

git remote add origin git@github.com:your-username/your-reponame.git

Once you've done that you'll want to push your changes to the server

git push origin master

Now you've got the basic setup done

Now for the submodule part. It's not actually that difficult, just run this command

git submodule add username@server:project/path local/path

So if you were me and you wanted a read write version of my 'android tools' project in a folder called 'sub' you would run

git submodule add git@github.com:fry15/uk.co.jasonfry.android.tools.git sub/uk.co.jasonfry.android.tools

Again, notice that the username for github is always git@github.com, this is just the way they have there system setup, if you've setup your own server then you should know what those details are... If you just wanted a read only version of a project rather than a read write version (this is most likely the case if you are adding an open source library) then use its http url in the command instead, so for example to get a read only version of my 'android tools' project you would run

git submodule add https://github.com/fry15/uk.co.jasonfry.android.tools.git sub/uk.co.jasonfry.android.tools

Now you will want to update your git project, so run

git commit -a -m 'my commit message'

to commit your changes. The command if you want to push to your remote server

git push

The submodule you have added is basically its own git repo, so when you make changes to the submodule, just change directory into its folder and do all the usual git stuff within that folder. If you update or pull in a change on your submodule then you'll need to let your main / master (whatever you want to call it) git project know that the submodule has updated, the master project just holds a reference to the submodule (the url and commit id).

Now say somebody else has checked out your master project repo, they will need to initialise the submodule you have added. This is done using

git submodule update --init submodule/path

If you have any git questions, I am not the person to ask. Google is your friend ;)