Have a clean history with git-rebase
When working on a project you may want to have a clean history, this makes identifying problems —which there will be— a little easier at some point in the future.
A possible functional definition of “clean history” in the context a software project could sound somewhat like:
Each unit of change in the public project history brings the system in a working state.
Where a “unit of change” is a patch or a commit and with any given definition of “working state” (e.g. “the code compiles”, “the code runs”, “the code passes the unit tests”, “the code is correct”, etc.)
This may sound trivial to some, but I've often busted myself testing for a working state only after a set of changes and not after each one of the changes in the set; if there is a commit which brings the system in a non-working state —even temporarily— tools like git bisect won't work at their best the one day you will need them.
When using git, commands can be executed after each commit to verify the current state of the code; here are a couple of examples of how this can be accomplished with git rebase, the examples assume you are working in a local branch (hence before you publish your changes) and you based that one off the master branch.
The classic “stop-to-edit-and-continue” way:
-
Invoke
git rebase -i master
-
Mark each commit with
edit
:edit 3f07918 gspca - ov534: Add Saturation control edit 4fedee8 Input: move drivers/input/fixp-arith.h to include/linux edit 799068f gspca - ov534: Add Hue control
-
The rebasing process stops after each commit, then you can run your tests, fix and amend (
git commit --amend
) the commit to bring the system in a working state. -
Advance to the next change with
git rebase --continue
.
-
Invoke
The neat “run-automatic-tests” way, to use in case your tests are non-interactive (not always possible, e.g. when dealing with device drivers which may need interactive testing):
-
Invoke
git rebase -i master
-
Add an
exec
line after each commit to specify the command to run:pick 3f07918 gspca - ov534: Add Saturation control exec ./my_test_script.sh pick 4fedee8 Input: move drivers/input/fixp-arith.h to include/linux exec ./my_test_script.sh pick 799068f gspca - ov534: Add Hue control exec ./my_test_script.sh
with
./my_test_script.sh
returning0
(zero) if everything is OK or another value otherwise.In some cases, depending on your build system and its setup,
./my_test_script.sh
can be just replaced with something likemake test
. -
The rebasing process stops only when the command executed returns a non-zero value, then you can fix and amend (
git commit --amend
) the commit to bring the system in a working state. -
Advance to the next change with
git rebase --continue
.
-
Invoke
The downside of this work-flow is that you need to edit the output of git rebase -i
which can be tedious if not fragile; I read that it is also possible to play with git rev-list to specify the command to run after each commit only once, as suggested in GitPostProduction, but this is kinda hackish.
If the git rebase --exec $CMD I propose gets implemented, there will be even an easier way to test our commits before publishing them.
If you are interested, pitch in the discussion on the git mailing list (you can reply to the web archived message too, just choose “Followup” from the --Action-- drop-down menu on that page).
Comments
Post new comment