So, you’re working on a project for longer than a couple of days. Maybe you will even have to write up a report on the progress at the end (and don’t always remember to document what you’re doing). One thing you will strive to avoid is losing your data – because, let’s face it: even a week’s worth of work can put you at risk if you’re working on a deadline (if you don’t, it will still be annoying). Maybe you also want to experiment a little. You can always undo your changes manually but if you experiment takes longer than a day, you may not even remember all details.
My favourite solution to these problems is using remote version management. There are a couple of different systems I have had the pleasure (and displeasure) to work with over the past couple of years and so far, git has been my weapon of choice in the battle against data loss and chaos. My usual setup is to have a server where I store a so-called “bare” repository (i.e. a repository that does not contain a checked-out version of my files). This repository is usually placed on a server I can reach from anywhere I want. Setting it up is pretty easy:
$ mkdir myRepo.git $ cd myRepo.git $ git --bare init Initialized empty Git repository in path/to/myRepo.git/
Now, I can clone the repository to any other computer I want.
$ git clone user@server:path/to/myRepo.git Cloning into 'myRepo'... [password prompt] warning: You appear to have cloned an empty repository.
If you have never used git on your computer, you need to set your name and email address. The easiest way to do this is to write the following into ~/.gitconfig:
[user] name = Your Name email = Your Email
Now, you may add files into the repository. As a rule of thumb, you add everything that is raw data and omit generated files (pdf, executables, compilation byproducts, most hidden files). Below are some examples I use a lot.
$ git add *.h *.c *.hpp *.cpp # C(++) source files $ git add CMakeLists.txt # build file $ git add *.tex *.bib pics/* # tex source files, pictures
Now it’s time to commit your first controlled version (imagine a commit as a snapshot of your files). This is mostly straightforward, but there’s one little trap: in later commits, you will have files that are already tracked which you have modified. To include them (if you simply want to commit all changes), make sure not to forget the little “-a”!
$ git commit # will open an editor for your commit message $ git commit -m "..." # give the first commit message directly $ git commit -a # commit all changes, including modified files !!!
You can also choose to commit specific changed files by adding these files to the commit explicitly (even if they are already tracked), and then committing without the “-a” option:
$ git add thisFile thatFile $ git commit
Now you have a local version. However, if you work on more than one machine (or simply want to have a backup), you will have to “push” the changes to the server. Other systems (e.g. svn) do not need this extra step, however, their committing process requires an internet connection if you have a remote repository. With a commit+push system, you will be able to store versions on your computer while working on a train and simply push them to the server once you arrive at your destination.
On the first push, you will have to specify a branch to work in. Here, it’s called master, but you can also call it Uncle Scrooge, your name, a specific feature you’re working on, etc. Later, you automatically commit to the branch you’re currently checked into.
$ git push origin master # first time pushing $ git push # later
If you’ve been working from one computer and now want to get the most recent version on a different one, you will have to “pull” it from the server. (Before you do this, commit your changes.)
$ git pull
Congratulations, you can now use the basic functions of git!
Here are a couple of useful tools:
$ git help # guess what $ git status # gives you a list of all files and their tracking status $ git stash # lets you temporarily stash away your changes (e.g. when you pull but don't want to commit yet) $ git branch # lets you work with several branches in parallel (recommended if you're not working alone!!) $ git checkout # lets you switch (or reset) to a specific commit or branch $ git diff # lets you view differences $ git mv/rm # same as mv/rm, just with repository support
Then, there is the .gitignore, a file that lets you keep certain files from being tracked. Why is this cool? If you have a bunch of new files, you can simply add all of them by writing
git add *
instead of adding each of them manually! You simply put a file called .gitignore in your myRepo folder and fill it. Here’s an example:
# compiled files *.o *.exe *.pdf # compressed files *.tar *.zip # hidden files *~ *.tmp .* # cmake byproducts CMakeFiles CMakeCache.txt cmake_install.cmake Makefile
It makes sense to track the .gitignore if you use more than one computer. Since we just told git that we want to ignore .* files, you will have to force the adding process:
git add -f .gitignore
And that’s it! You have your git all set up. Have fun and don’t forget to commit regularly and push every once in a while. :)