Ensure atomic commits in the CI

The idea of atomic commits has been considered best practice by many people. It essentially means that every commit on the master branch should at least be able to be built successfully. Some also include that it can “start” successfully, some also include that all tests have to be able to be run successful.

If you just want a shell command to ensure that, you can do it with the following command:

git rebase --exec "<atomic commit check command>" <base commit>

This command will check out¹ every commit between the base commit and the current commit (not including the base commit itself) and execute the given check command after each checkout. The command only returns successfully if all commands executed successfully.

In most cases you want to use it together with merge-base and your main/master branch like this:

git rebase --exec "<atomic commit check command>" $(git merge-base HEAD main)

This will find the “best common ancestor for a merge” aka the most recent common ancestor² and execute the command for each commit from there. This ensures that if your branch isn’t up to date with main, we don’t just rebase on top of main and change the actual branch.

Depending on your technology stack and definition of atomic commits, you can use different check commands with it. For example you could use gradle check or npm run build.

¹You might call it “switching” instead now, since the never command switch is now recommended over the old checkout

²If you keep a clean history. With criss-cross merges, there could be more than one “best common ancestor”.