In a December 2017 blog post, my friend Jack wrote about the Purposeful First Commit
A first commit helps define what the project intent is. Why are you committing this code? What do you aim to achieve?
It really resonated with me. The first commit on any project is the first time you say, “Here I am and here’s what I’ve done.” But we usually say that with code and the human readable announcement is always “Initial commit” or some bland version of the same.
So in creating a new project I made sure my first commit was purposeful. But when I mixed in Git Flow and Atomic Commits I made a couple of mis-steps and had to nuke my
.git directory a couple of times. This article records the steps I went through for a successful “purposeful first commit” combined with Git Flow.
Julian, a developer on my previous team introduced me to the concept of Atomic Commits.
An atomic commit is an operation that applies a set of distinct changes as a single operation
In revision control systems, this means you commit all the code that’s related to a change and only the code that’s related to that change. If you altered four files to re-style a phone number input field then all four files are committed together. If you also updated the styling on headers, then that’s a separate commit — even if it’s in the same file you altered for the phone number field.
Doing this results in really clear information in a
git blame or whatever your IDE does to show the annotation on a line of code.
Once you grok the concept of Atomic Commits its easy to see why a first commit message should be purposeful.
Using Git Flow
I’m a big fan of Git Flow (this was introduced to me by Luke, also a developer my previous team). I find it organises version management so much neater than just branching and merging into master. When you start a new Git Flow project, it creates a ‘develop’ branch from your ‘master’ and then feature branches come from ‘develop’.
Setting up Git Flow is easy, but if you want a purposeful first commit and want atomic commits, you need to be careful. Otherwise you’ll end up with the dreaded “Initial Commit”.
So we want a Purposeful First Commit, that is atomic, and uses Git Flow. Let’s mix all three together and get our new project set up in GitHub (or BitBucket)
I’m going to assume you have existing code. If you don’t, then just create a
.gitignore. (If you’re creating a README.md, and don’t want to write a full document, at least put the same message in there as your planned first commit message.)
Create a new repository
Create a new repository in GitHub but do not take up their offer of creating a README.md or anything else. The following steps are very similar to GitHub’s instructions for existing code via the command line.
- Initialise git in your working directory
- Add your README.md file (or .gitignore, but not your code)
git add README.md
- A Purposeful First Commit
git commit -m "Foo::Bar is a perl module that implements Bar for Foo using Zap. It is designed to be lightweight and fast with very few dependencies beyond Foo and Zap"
- Get this into GitHub right now
git remote add origin http://github/you/project git push -u origin master
Normally, you’d have committed all you code in the above step, but we’re wanting to use Git Flow here. And I believe that the concept of Atomic Commits should extend to branches, so even the first batch of code should be created in a feature branch. It lets you (or a colleague) review a pull request right from the start.
- Initialise Git Flow
git flow init
- Push the new
developbranch into GitHub (no need to check it out, Git Flow did that for you)
git push --set-upstream origin develop
Note that we still haven’t pushed any code. At this stage, the develop branch is the same as ‘master’: it only has our
- Start our first feature. I name the first branch the same as the repository, but you can call it anything you want.
git flow feature start foo-bar
- Add the rest of the code we’ve written
git add .
- Atomic Commit message should indicate that it was your first bit of code so when you look at
blameyou can see there wont be a previous version of the line.
git commit -m 'Inital effort to implement Bar for Foo using Zap'
- Push it to GitHub
git push --set-upstream origin feature/foo-bar
And you’re done. You have a purposeful first commit. You’re using Git Flow. And you have an atomic branch with an atomic commit in it.
Now, if you created a rudimentary README.md, create a new feature branch, get it fixed, and merged into develop.