10 Ways Git Version Control Can Streamline Your Writing Projects

December 19, 2010

Establishing a rigorous version control process is a standard part of any software project, and Git is a powerful system for enabling such version control. But Git's advantages extend beyond just software development. For instance, I use Git to manage all of my writing projects, including books and my articles published on Developer.com (including this one). Git offers writers a fantastic set of features for producing material in an impressively fast, efficient and organized manner. In this article I'll introduce you to 10 Git tips and tricks I regularly apply within my own writing projects! Even if you're using Git solely for software development, you'll still be able to apply these tips to your projects!

1. Stashing Incomplete Changes

Distractions are a standard part of any writing projects, and I often need to switch gears and work on another part of the project before completing the current task. For instance, suppose you were in the midst of working on a new section of documentation, and suddenly notice a rather misleading statement in the installation section. It would be a good idea to fix the error immediately and make those changes available to users, but you're not yet finished with the new section. What to do?

You can stash the section you're currently working on, fix and commit the error, and then apply the stash back to your working version. First, stash your changes:

$ git stash save

Next, fix the error and commit the changes. Then list your stashes:

$ git stash liststash@{0}: WIP on master: c29f8cb Second commit

The {0} identifies the stash you'd like to apply. Incidentally, you can simultaneously maintain multiple stashes, each of which would be listed here if they existed. To apply the stash so you can continue working on the new section, use this command:

$ git stash apply stash@{0}

2. Tagging Releases

One of the really great advantages to managing large writing projects in Git is the ability to differentiate between developmental versions of the book using unique tags (of course, the same inherent advantages apply to software). For instance, if I want to designate a version of a book as alpha and make that version available to a set of reviewers, I can tag that version like this:

$ git tag -a v1.0a -m 'first alpha release'

You can then list tags using the tag command:

$ git tagv1.0a

Cloning a certain tagged version of the project is also easy:

$ git clone /path/to/project/ /destination/path v1.0a

3. Working on Blue-Sky Chapters

Because I spend a good deal of time writing and revising books, ideas for new material are always percolating. Sometimes I know that I won't be able to incorporate a new chapter idea into a book for some time, maybe because the technology hasn't sufficiently matured. Yet I nonetheless want to create a chapter skeleton and occasionally add to that material as time arises, without incorporating this chapter to the ongoing set of general additions and improvements I'm making to the book. I can create a branch, which allows me to work on this chapter within the confines of my current project, while simultaneously not affecting the main development line (also known as the "master").

Suppose I considered eventually adding a new chapter about continuous integration to an existing book. I would start by creating a branch:

At this point I can create a new chapter and work on it, committing changes until you want to turn my attention back to the main branch:

$ git checkout masterSwitched to branch 'master'

If you're not familiar with development branches, try experimenting with them and listing the repository contents as you move from one branch to another. You'll see that it appears as if you're working on two separate projects, with the added luxury of managing them within one repository!

4. Merging Branches

When the time does come to incorporate an experimental chapter into the book's main development line, I'll want to merge the branches. For instance, to merge the continuous-integration branch into the master branch, I check out the master branch and then execute the following command:

$ git merge continuous-integration

5. Searching for Terms

When writing a large document over a period of several months it can be difficult to recall whether I formally introduced a particular topic. In order to avoid such redundancies, you can use Git's grep command to easily find all of the instances where a particular keyword appears within the repository:

$ git grep Phingintroduction.docbook:In Chapter 4 I'll introduce Phingchapter04.docbook:Phing is an open source build toolchapter07.docbook:Recall in Chapter 4 you were introduced to Phing

Based on the results, I apparently introduced Phing in Chapter 4. I need only a cursory glance at that chapter to ensure the introduction is indeed sufficient.

6. Ignoring Project Notes

When working on writing projects I'll often maintain various files, which contain research notes that are really only useful during the course of the project. Because I'm not interested in maintaining these files within the repository, I'll use Git's .gitignore file to prevent them from being included. For instance, I'll use the file extension .notes for these files, and prevent them from being tracked by adding the following line to .gitignore:

*.notes

7. Searching the Commit Log

Writing large documents such as books is very much a marathon, with the finish line being the culmination of thousands of smaller victories. I tend to measure productivity in terms of my chapter-specific milestones, and so when committing changes will prefix the commit message using a string, which looks like CHAPTER04. I can then use Git's log search capabilities to review the timeline of changes for that chapter:

$ git log --grep="CHAPTER04"

8. Backing Up Your Work with GitHub

There are few situations more sickening than realizing your laptop hard drive has decided to retire early, taking with it several projects that haven't been backed up since you last pulled out the USB key a few weeks prior. Save yourself the hassle and back up your Git repositories using an online service such as GitHub. For just a few dollars per month, you can maintain several repositories that allow you to easily backup your projects with just a few keystrokes. For instance, after configuring a new GitHub-hosted project, my daily workflow looks like this:

That last command results in all of the changes made since my last "backup" being sent to my project's GitHub repository, eliminating the need for manual backups with a USB drive or similar media.

9. Building Books with Postcommit

Using hooks it's possible to automate the execution of tasks in accordance with significant repository-related events, such as following commit. These hooks are stored in your project's .git/hooks directory, and can be written in any language supported by your operating system, for instance bash, Ruby or Python. For instance, because I like to produce PDF-based snapshots of books, which can be passed around to reviewers, my post-commit hook is a shell script that converts book chapters (written in Docbook format) into PDFs using an XSL-style sheet.

While this conversion process is out of the scope of this article, you can nonetheless experiment with post-commit hooks by renaming the file post-commit.sample to post-commit (again, found in your project's .git/hooks directory), and then modifying the file to look like this:

#!/bin/bash

echo "post-commit task executed!"

Of course, this assumes you're running an operating system which supports the Bash shell. The next time you initiate a commit, this statement will be output to the screen!

10. Coloring Your Commits with Flashbake

The flashbake project is a really interesting Git-oriented project that supports a series of plugins capable of incorporating information from the outside world into your commit messages. For instance, flashbake can retrieve a list of recently posted Twitter updates, your current geographical coordinates, and current weather conditions, adding all of this information to your commit message. This certainly has the potential of providing readers with not only additional insights into the author's writing environment, but actually tying the changing environment to specific parts of a writer's work.