Have a clean history with git-rebase

in

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:

    1. Invoke git rebase -i master
    2. 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
          
    3. 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.
    4. Advance to the next change with git rebase --continue.
  • 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):

    1. Invoke git rebase -i master
    2. 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 returning 0 (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 like make test.

    3. 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.
    4. Advance to the next change with git rebase --continue.

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).


CommentiCondividi contenuti

Invia nuovo commento

Il contenuto di questo campo è privato e non verrà mostrato pubblicamente. If you have a Gravatar account associated with the e-mail address you provide, it will be used to display your avatar.
  • Indirizzi web o e-mail vengono trasformati in link automaticamente
  • Elementi HTML permessi: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Linee e paragrafi vanno a capo automaticamente.

Ulteriori informazioni sulle opzioni di formattazione

CAPTCHA
Questa domanda serve a verificare che il form non venga inviato da procedure automatizzate
R
a
6
s
S
h
Enter the code without spaces.