At some point it hits everyone. Your precious work of several hours is vanished because of a hardware failure. For that the industry came up with several solutions like the idea of version control systems. But recently I was dumb enough to not do any commit for several hours - just to leave the history clean. Big mistake… But did you think about automating that? How about committing every couple of minutes automatically? In this post I’ll explain this - on the first sight - weird workflow.
So, the idea is, to have a script that commits every couple of minutes as long as you’re working on a project. As soon as you are finished with your feature branch you use interactive rebasing to get rid of all the temporary commits.
The following one-liner is the command we want to automate:
Basically you add all files to the index, commit with a default message and push the new commit to origin with one go.
The next step is to write a script which executes this command regular when there are changes in the given repository. The simplest script that does that looks like so:
But obviously you should optimize the script a bit. You should get some better feedback what the script is currently doing and you should add a safety net that the script aborts as soon as you switch the branch. So a nicer solution is the following:
When you’re finished with the feature branch you probably want to have a nicer history without all the WIP commits. For that you can use interactive rebasing. This git function allows you to rewrite the history of a branch. To start the process you type:
git rebase -i master
When you branched of from another branch then master you need to exchange that in the rebase command of course.
The command will open your configured editor with a file like the following:
pick 1778493 WIP pick ce1ee68 WIP pick 282cdee WIP
In order to combine all the commits you exchange the all
pick keywords but the first with
pick 1778493 WIP s ce1ee68 WIP s 282cdee WIP
When we save and exit the file we get to edit the commit message for the squashed commits.
And that’s it. We can now run the above script as soon as we start to work on a feature branch and we’re sure that the changes will get pushed regular on remote.
After playing a bit more with the workflow I did a couple of improvements to the script which result in a nicer output.
These improvements result in an output like that:
You might also notice that I changed the commit interval to 5 seconds because I noticed that I prefer to persist changes as soon as possible. I actually adapted my workflows to work with many commits. For example I avoid triggering CI builds when “WIP” is part of the commit message. Furthermore I use the git-squash alias to squash all commits when I finished working.
In some cases you’d like to mark specific states of your history. For that I create an empty commit with
git commit --allow-empty -m "Some message".