From CVS to Git, 9 Things I’ve Learned
As frequent readers of my blog know I’ve been transitioning to git lately. I actually think CVS (with the Eclipse Team Support, local history management and Mylyn) makes a solid source control management solution. However, now that I’ve spent a few weeks with Git, I’m having trouble going back.
I don’t like drinking fine wine, because when I return to my home brew I’m always disappointed. For the same reason, I don’t like git.
I decided to record some of things I learned while moving from CVS (a centralized version control system) to git (a distributed version control system).
1. Commit early, commit often
Unlike centralized version control systems, with Git each developer has their own copy of the repository. This means you can commit as often as you want without affecting others. Even if your changes are incomplete, breaks API or causes the build to fail — you can commit. This allows you to structure your commits as logical units of work, as opposed to one monolithic commit that represents the entire new feature.
Once you have your feature completed, you can share your commits with others.
2. May the fork be with you
Services like GitHub are a great way to share projects with others. The service is free for OpenSource projects, and for a fee it can be used for private repositories. Git makes it easy to fork repositories, evolve them independently, and merge the changes back. You can even ‘cherry-pick’ particular commits.
In the past, forks were often frowned upon because of the fragmentation they caused and the challenges related to merging. A distributed version control system changes this. Since git store the relationships between commits, merging forks back together is relatively easy. Encourage forks among you and your team members and don’t worry about the merge step.
3. Check your head
If you end up on the wrong branch, or accidentally reset your head pointer, your source tree may not look as you expect it to. Honestly, take some time to understand how git represents commits. Understanding this was the biggest challenge I faced. There are some good articles here and here.
Once you understand this, make sure you don’t lose your head.
4. RTFL: Read The Frickin (ref)Log
If you get into trouble, lose commits, or find you’ve broken everything, turn to your reflog. The reflog has saved me many times. The reflog will show you all your recent repository activity. From here, you can reset your repository to any recent commit.
5. To pull or to fetch, that is the question
In most centralized version control systems, updating your local source tree (to match the repository) cannot be taken lightly. If you’ve made significant changes, updating from ‘HEAD’ can cause a tremendous headache. This is because you are essentially ‘fetching the new revision’ and ‘merging it with your source tree’. In git, the concept of ‘fetching’ and ‘merging’ can actually be applied separately. If you simply want to update your local copy of a remote branch, you do a fetch. You can defer the actual merging to later date. If you want to combine these two operations (fetch and merge) then you can issue a pull request.
6. Shut-up and just branch
Branching and merging in CVS is a pain. In fact, until the code is properly merged and committed to ‘HEAD’, I don’t consider it complete. Git on the other hand stores the relationship between commits, which enables much better merge support. Merging in git is often an effortless operation. For this reason, I suggest creating a branch whenever you start working on a new feature. At any point you can ‘merge’ or ‘rebase‘ with the master branch, as well as share your branch with others for easy collaboration. Separate branches makes it very easy to move effortlessly between tasks.
7. Stash it, don’t trash it
If you need to switch tasks and you’re not able to commit your current work, checkout the git stash. Git allows you to stash your current changes for easy retrieval at a later date. This means you can stash your current work, reset the branch and work on something else. Then, you can retrieve the stash and continue working right where you left off.
8. Play the blame game
If you need to see when a particular line of code was introduced and who committed it, turn to git blame. Git blame shows the revision and author who last modified each line of a file. It also shows the commit comment for each line.
9. Those who don’t learn from history, are destined to repeat it
The CVS history view is an archaeology tool. That is, it’s used to unearth historical artifacts about your source code. It’s used to see who added a particular line of code, or to read the commit messages that accompanies a code change. While using Git, the history view is a development time tool. It’s used to see what else is happening in the repository, and to better understand the relationship between commits. Get used to having this view open. Understanding your history is an important part of working with git.