Three Things I Love About Git
git-commit --amend
One of the benefits of using version control is organization. When you commit a set of changes, you are implicitly marking that set as defining a certain feature set, or otherwise having something in common.
Have you ever committed something, then realized you forgot to include something with it? Maybe it's a new file, or maybe it's an extra small change you forgot to make.
Enter git-commit --amend
. The amend option adds to
the tip of the current branch, and actually replaces the last
commit with the combined change! It even seeds the message
editor with the last commit's description, so you don't have to type
it in again.
git-checkout -b
I often like to work in branches, even if what I'm implementing is not large enough to make a branch-commits-merge cycle really necessary. I find that making frequent small commits, without needing to think about whether the product is fully stable each commit, helps me focus and develop more quickly and cleanly.
In most VCSs, branching is something that takes a bit of effort, and for maximum ease, you want to plan it ahead of time. Sometimes I start developing, and suddenly decide what I'm working on is going to be big enough that I want to use a branch. I'm now forced to decide whether I want to make the effort to "backport" the work done so far.
With git-checkout -b
, it becomes a very easy decision.
This command says "create a new branch, based off the last commit, and
transfer my working copy to this branch in-place, so I can commit to
the branch as I please." I just execute git-checkout -b
new_branch_name
and keep going, with no interruption to my
train of thought or work flow.
(Bonus: merging is relatively painless in git, especially compared to most centralized version control systems. Which just makes the ease of branching even more valuable.)
Fine-grained commits
Like I mentioned, one valuable benefit of using version control is organization: by making intelligent commits, code content diffs are automatically organized by feature set.
Sometimes, when I'm ready to commit, I have changes I want to include mixed in with some I do not. Or, I decide it would make more sense to split the current set of changes across several commits.
An example from this week: I was editing a Makefile, and realized it contained three sets of changes that really had nothing to do with each other.Had the make file been split up into several physical files, perhaps it would have been trivial to put into separate commits, but it in reality it was just one physical file.
Most VC tools I know of can resolve commit changes only down to the individual file level - they don't get fine grained enough that you can tell them, "commit this part of this file, and that part of that file, but not these other parts". You can always hack around it, by manually editing and reverting, etc. But that's often not easy nor quick.
But lo! I have a friend in git-commit --interactive
.
This starts up a shell that allows you to selectively add individual
changes, what git calls "hunks", to the staging area for committing.
In this case, the Makefile had three of these hunks. You can split up
any hunk into smaller hunks, if you want to control what you're
committing with even finer granularity. You can review the change set
as you build it, adding, deleting or refining changes as you like.
When satisfied, I exit, and the change set is automatically
committed.
That's for the simple case of one file. It can be an even more powerful tool with a larger change set.
(By the way, if you don't want the automatic commit, just use
git-add --interactive
instead. It otherwise works the
same way.)