Wednesday, August 29, 2007

Git Revisited

To my consternation, the cogito package disappeared from Debian a few updates ago. I soon discovered the reason. Contrary to Linus Torvald's prognostications, raw Git is now (verson 1.5) a user-friendly version control system and does not need wrappers.

Still, I had to learn some new syntax. Luckily I was interested in learning about Git's more advanced features so I didn't mind. I was only previously using Git via Cogito in the same way one would use CVS or Subversion, except that it was faster, more robust and easier to use.

Now I finally understand why Git can do so much more. Better late than never!

101 Ways To Use Git

Git is the duct tape of version control. When I first started using it, I only cared about a very specific problem and ignored Git's design and internals. I focused only on remembering the Cogito commands I needed to type to do what I want, oblivious to how it worked its magic. Relatively poor documentation is partly to blame, but in truth, it is extremely difficult to convey Git's extraordinary versatility.

The book "Design Patterns" showcases the diverse problems that object-oriented design can elegantly solve. I wish there were an analgous Git book, instead of explaining Git fundamentals and leaving the reader to derive the implications, gave a set of recipes to accomplish a variety of tasks.

Below are a few examples of Git recipes such a book might contain.

Instant Backup

Just as in a computer game, when I'm about to attempt something drastic I like to save the current state, so I can go back and try again should things go awry.

git-init
git-add .
git-commit -m "Initial commit"

to take a snapshot of all files in the current directory.
Then if something goes wrong type

git-reset --hard

to go back to where you were. To save the state again, type git-commit -a. You'll have to type in a description of the current state.

One benefit to doing this instead of simply copying files is that with Git's hash chaining, you can tell if a backup gets corrupted.

Undo/Redo History

More generally, you can do the above, and every so often "save the game" by typing

git-commit -a -m "description of current state"

Note if you want to keep track of newly added files or forget about deleted files you'll need to first run "git-add" or "git-delete" accordingly.

Typing git-log shows you a list of recent commits, and their SHA1 hashes. Then typing

git-commit -a
git-revert SHA1_HASH

will restore the state to the commit with the given hash. You might like to use something like the following instead:

git-revert "@{10 minutes ago}"

You can undo the undo: type git-log and you'll see that the other commits you made are still there.

To take the computer game analogy again, git-revert is like loading a game and recording this fact as another saved game, and git-reset --hard is like loading an old save and deleting all saved games newer than the one just loaded.

Sync Files Between Computers

This is the reason I first used Git. I can make tarballs or use rsync to do backups. The problem was sometimes I'd edit on my laptop, other times on my desktop, and they may not have talked to each other in between.

Initialize a Git repository and commit your files as above on one machine. Then on the other:

git-clone git+ssh://other.computer/directory

to get a second copy. From now on,

git-commit -a
git-pull git+ssh://other.computer/directory

will pull in the state of the files on the other computer into the one you're working on. If you've recently made conflicting edits in the same file, Git will let you know and you should resolve them with another edit and commit.

If you have not committed any changes on the other computer, you may type

git-push git+ssh://other.computer/directory

to push the current state to the other computer. Next time you're there, run git-reset --hard or git-checkout HEAD . to update the files.

That Git does not do the last step automatically is good in case you were in the middle of some uncommitted changes.

Tune in next time...

I've barely scratched the surface, and so far haven't shown anything you can't do with older version control systems. Next time I'll show off problems that only the new generation of version control can solve.