My work day doesn’t naturally divide itself cleanly into commits. I’m often interrupted to work on something new when I’m half-way done with my current task, or I just need to head home in the evening without quite having finished that few feature. This post talks about one technique I use in those situations.
To rewind a bit though, when I’m starting a new piece of work (whether a new feature, bug fix, etc.), I first check out the source branch (almost always master), and run:
> git pull --rebase
This grabs the latest changes from the origin without adding an unnecessary merge commit. I then create myself a new branch which shows my username along with a brief reminder of what the change is for:
> git checkout -b aminer/performance-tuning
At this point, I’m ready to start working. So, I’ll crack open my favorite editor and make my changes. As I’m going along, I’ll often find that I need to stop mid-thought and move on to a different task (e.g., fix something else, go home for the day, etc.). It may also be that I’ve arrived at a point where I’ve just figured out something tricky, but I’m not through with the overall change yet. So, I’ll create a work-in-progress commit:
> git add -A
> git commit -n -m wip
This is really more of a “checkpoint” than an actual commit since I very likely haven’t fully finished anything, probably don’t have tests, etc. The -n here tells git not to run tests or linters. This is fine for now because this isn’t a “finished” commit, and I’m going to get rid of it later. For the time-being, though, I keep on working. If I reach another checkpoint before I’m ready to make a real commit, I’ll just add on to the checkpoint commit:
> git add -A
> git commit -n --amend
The first command pulls all my new work into the index while the second removes the prior work-in-progress commit, and replaces it with a new one which contains both the already-committed changes along with my new ones.
When I’ve actually finished a complete unit of work, I remove the work-in-progress commit:
> git reset HEAD~1
This will take all the changes which were in the prior commit, and add them back to my working directory as though they were there all along. The commit history on my branch looks just as though the commit had never been there.