A recent conversation with a colleague about svn took me down to the memory lane of version control. I decided to write this for the future me, to update again when git becomes obsolete — a brief history of how I have been versioning my code in the last decade.

  1. The dumb version
  2. SVN
  3. GIT
  4. Summary

The dumb version

Back in 2007 to 2008 summer (yes, summer, I was in New Zealand at the time) I took an 8-week long summer project in computational mathematics and focused on floating point arithmetic. It was not the first time that I wrote lots of code on one project, but it was the first time I decided to put more structure to the code and started versioning.

In the first a few weeks, I laterally made a new copy of the entire project at the end of the week, name the folder with date. My supervisor told me to keep a reseat diary (a neat skill that l learned, and still use it until this very day), which I also use it to keep log of the changes. The code started growing quite rapidly and structure started to look messy, I paused the work and started to use soft links to take care of the repeated part. At the end of the 8th week, this project directory was no where near where I planned it to be. My first versioning project was a total disaster. Luckily the course was only assessed based on the report and presentation, so it wasn’t a total failure.

A valuable lesson that I have learned from this is that how important is to keep a clear log of major changes and assumptions. Small change logs are not very useful.

In the following years, I started to do more research work and postgrad studies, when I started doing proper version controls with svn, this was when google code was still a thing.

SVN

svn is a centralized version control system. What does this mean? Suppose that that I am collaborating with person B and C. We must have a central server to host all the files and change logs. Person B, C and I have to commit and submit our changes to the central server in order for the version control to work. svn adapts a tree structure: stuff on the central server is known as the trunk. Developers work on their own branches, which is a local copy of the trunk. So how does it work in practice?

Assuming a remote repo has been set up, we can copy the remote version of REV to make a local copy by checkouout


svn checkout URL_OF_A_REV LOCAL_DIR

Note: svn co is short for svn checkout.

Saving changes

Suppose you have created an R script, namely SOME_FILE.R, and you want to start tracking changes in this file. You can add this file to your svn records by:


svn add SOME_FILE.R

Note: you can always use svn status to check the current status before you commit. A newly added a file will have status A, otherwise can be M for modifications and D for deletion.

One important thing before you commit, always pull the remote changes first before you commit and publish your changes:


svn update

This will avoid conflict and overwriting each other’s code.

Once changes have been made, and you want to save all the changes into the history / log.


svn commit -m `I just made some changes`

Type svn log, then you will be able to see this message

GIT

Working with local repository.

Since 2013, I switched to git. Git is much more powerful than svn. Firstly, it decentralizes the repository, i.e. you don’t need to have internet to use git, whereas svn relies on communication with the remote master.

To start a local git repo, you can simply do the following:


mkdir MY_LOCAL_REPO
cd MY_LOCAL_REPO
git init

Once we have done this, we can use git remote set-url origin REMOTE_URL to link the repo, where REMOTE_URL is an uninitialized git repo url (on github or gitlab). If you have github repo initialized by github already. Instead of git init, you should


mkdir MY_LOCAL_GIT_REPO
cd MY_LOCAL_GIT_REPO
git clone REMOTE_URL

The normal work flow with git and svn are very similar, new files need to be added then can be committed. Difference is that in git, once tracking has started, you can make further changes to the file, however these changes are not staged, unless you do git add again. For simplicity, you can do git add -u, which will help you stage multiple files that are tracked already.

For svn, one should always ‘update’ then ‘commit’. For git, one should always commit and pull or stash, pull, stash pop depends on the team workflow.

Branching and merging

Branches are effective pointers of your changes. From time to time, it is easier to implement new features or fixing bugs on the branch, without affecting the rest of the core code. For svn, branching will require copy the trunk, it is very time consuming. It is much simpler and clearer in git.

Suppose the main branch is called the Master branch. From left to right, each circle is a commit entry, after two commits (white circles), the first branch is created by


git branch -c Feature

This will allow you to make changes independently on both Master and Feature branches. To switch between branches, you can use git checkout BRANCH_NAME. Suppose you have finished implementing new features, and there are two commits on the master branch, you can use git merge ONTO_BRANCH FROM_BRANCH to merge changes from Master to Feature, i.e. git merge Feature Master.

A good exercise of branching can be found at learngitbranching.

Rebase and squash

Rebasing allows you to move your HEAD node around the tree, which makes git very powerful when modifying changes. Take the previous example, Instead of merges from the Master branch on to the end of the Feature branch. A rebase step on branch Feature will allow you to detach the branch Feature and add to the end of branch Master. This will then allow to maintain much cleaner working records. Suppose you are rebasing Feature to Master:


git checkout Master
git pull
git checkout Feature
git rebase -i Master

Try to squash all commits into one: in the editor, leave pick in the first line and enter s for the rest. Go through the rebase process by resolving any conflicts, then git add . and git rebase –continue. Once all conflicts are done, do git push origin Feature -f.

After this you can create a pull request on GitHub and ask someone to approve the merge into Master.

After rebasing, git will allow you to revise the changes (commits) on the branch. At this stage, you can choose option squash to squash multiple commit records into one. And keep the log smaller.

Submodules

Another powerful advantage of git compare to svn is submodule, which can be used to link multiple git repositories. Each repository can be developed independently.

To initialize a submodule, can simply use the following:


git submodule init
git submodule add REPO_PATH_OR_URL

If a git repo (with submodule) is freshly cloned. One would need to use git submodule update –init --recursive to make sure all submodules are also checked out and updated.

Also refer to the Github git cheatsheet.

Summary

To summarize:

Operation svn git
To create a repo svnadmin create git init
To clone repo svn checkout git clone
Update from remote svn update git pull
Stage a change/commit svn add git add
Check repo status svn status git status
Make a commit svn commit git commit
Diff svn diff git diff
Stop tracking / Remove svn delete git rm
Make a branch svn copy git branch -c
Revert changes svn revert git checkout
To view the log svn log git log

Git has so many more features compare to svn: submodule, rebase, pre-commit settings. So … use git.

Migrate from svn to git.

If you ever fancy to move from svn to git. This blog gives a very clear and simple instruction.