How to test && commit || revert

test && commit || revert is a programming workflow where all code that passes your tests gets committed, but if the tests fail all the code written since the last commit will be gone.

Have you ever made a big pull request and spent days waiting for code review and fixing errors? This workflow is a way to encourage you to make smaller commits, that again will get out into production faster. Try to only change one thing at a time. That again encourages you to learn or create good refactoring tools for your language.

Another benefit we experienced is that tackling complex problems is a lot simpler if you do it in small steps. Only focusing on the next little thing actually made us faster than trying to fix a big thing in one go.

When you get used to it, it is a great relief that the broken code is automatically gone. You still have to figure out what went wrong or attack it from a different angle, but the cost of trying out something that might not work is small. In fact, the cost is so small that I wrote tests I knew wouldn’t work, just to see them disappear.

We made two scripts to make test && commit || revert work for us. We called them the run script and the sync script.

The run script can be as simple as expanding test && commit || revert to use your existing tools. We use git and have a test script that compiles our code and run the tests. So an expanded test && commit || revert will look like this for us:

./test && git commit -am working || git reset --hard

If ./test exits with an exit code 0 or 1 depending on success or failure, it should work out of the box on any unix terminal. It will trigger a commit when it succeeds and revert on failure.

git commit -am working creates a commit with all changed files (-a) and a commit message (-m) that is “working”. To add untracked files automatically, include git add .

git reset --hard reverts all the changes you have done to all the files.

The sync script automatically pulls and pushes git commits to a remote server so that they will propagate to everybody working in the repository. We created an infinite while loop where we do git pull --rebase and git push.

while(true); do git pull --rebase; git push;done;

There are still numerous possibilities that we want to explore further. At the most, we had three people working on separate machines on the same codebase. That worked surprisingly well, but how will it scale further? Have you tried it? How did it work for you?

One of the challenges we are facing is support for more people working on the same file. When one person was in the flow changing one file, it was near impossible to get work in because it was constantly changed by our sync script.

In Iterate we have a saying: To become the best, we have to learn from the best. In our code camps with Kent Beck, three developers team up with Kent for a “geek week” where they explore ideas, learn new skills, and have fun together.