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.

12 Responses to “From CVS to Git, 9 Things I’ve Learned”

  1. I completely agree with #6 and to expand a bit on that point, you should also familiarize yourself with git-reflog which shows you what you have been up to. We hope to add a reflog view in EGit 1.1 so you don’t have to drop to the CLI to use this useful feature.

  2. David Carver says:

    Git blame is a great tool as well. Glad to see we’ve converted you over to the Good Side of the Force,

  3. Ian Bull says:

    @Chris

    Good call. The reflog has saved my bacon several times. I’ve added it to the post.

    @David

    Thanks. Blame is a great tool. I’ve added it as well as the git stash.

  4. Alex Blewitt says:

    Readers might also be interested in my Git Tip of the Week series – I covered stash and reflogs a few weeks back.

    http://alblue.bandlem.com/search/label/gtotw

    Alex (@alblue)

  5. Ian Bull says:

    @Alex,

    I actually linked to your gtotw when I talked about stashes ;)

  6. Raphas says:

    For number 6, I don’t CVS that much, but for SVN, I can just branch and merge every new functionnality I’m building right ? What would be the advantage of Git and “relationships with commit” ? Can you illustrate how this is creating issues in CVS ? Much thanks !!

    Raphaël.

  7. Lee Doolan says:

    I would mention that my usual Modus Operendi is to do all of my work on local branches.

    I do not merge into remote branches until I am almost ready to push. I keep up to date by doing frequent pull’s on remote branches and then rebasing my work forward to the new (remote) branch HEAD.

  8. Guy says:

    I still have one thing that bothers me about Git.
    Continuous integration – once developers start forking/branching it encourage them to push to the main branch very late in the process which means their new code is not continuously integrated and tested.
    In our team we encourage developers to commit their changes twice a day and make sure the Continuous integration and Automatic tests will give them full feedback in less than a hour.

  9. icebrain says:

    @Guy: that’s a problem with your lack of integration between the VCS and the CI system. The CI system should test all the branches, not just the main one. Jenkins/Hudson does this, for example

    Also see https://github.com/blog/471-continuous-integration-spring-cleaning

  10. Alex Blewitt says:

    Guy,

    Mulitple branches can still be tested automatically. See my article at InfoQ at http://www.InfoQ.com/articles/Gerrit-jenkins-hudson – in particular, follow the first couple of links to the vimeo screencasts of how you can have automated build and test across multiple branches.

  11. Bob says:

    How does a commit get loose?

  12. Ian Bull says:

    I’m not sure if you were correcting my poor spelling or asking a serious question. I’ll assume this was a real question. A commit can “get loose” or you can “lose” your commits if it’s unreachable by any branch. This can happen by resetting the tip of your branch to another commit on the branch. If this happens, then all the commits after the point where you reset will not be reachable. You can also ‘misplace” commits if you are working with a detached head. See some of the referenced articles for more information.

12 responses so far

Written by . Published in Categories: EclipseSource News, Planet Eclipse