Back to Devoured - August 10, 2026
DEVOURED
Commit Message Test Plans

Commit Message Test Plans

DevOps Waleed Khan
Embedding executable test plans directly inside Git commit messages allows developers to automate validation for entire patch stacks during rebases.
What: Developer Waleed Khan shared a workflow using a custom script, 'git-test-message', and the 'scrut' tool to execute test code blocks found within Git commit message bodies. This approach supports ad-hoc validation, differential testing, and bisecting, ensuring test plans remain tightly coupled with the specific code changes they validate.
Why it matters: This approach reduces context switching by keeping validation logic alongside the code history, improving the reliability of stacked diffs in fast-moving development environments.
Takeaway: Integrate 'scrut' into your workflow by adding executable code blocks to your commit messages and configuring 'git test' to trigger validation automatically.
Deep dive
  • Commit messages serve as documentation and executable test suites.
  • Enables re-validation of entire commit stacks after rebase operations.
  • Facilitates easier bisection to identify the exact commit introducing a failure.
  • Supports differential testing by comparing current and previous commit states.
  • Uses 'mise' for JIT tool provisioning to ensure consistent environments.
  • Redirects stdout to stderr for non-deterministic tools like Bazel to prevent assertion errors.
Decoder
  • Patch stack: A series of dependent commits typically managed using tools like 'git-branchless' or 'sapling' to keep logical changes modular.
  • Scrut: A lightweight tool for running code blocks defined within Markdown documentation or commit messages.
  • Differential testing: Comparing the output of a system across two different code versions to verify behavioral consistency or identify regressions.
Original article

Julio Merino recently published A markdown-based test suite, about using Markdown itself as a lightweight test format.

That reminded me of a related workflow I’ve been using for a while with scrut: I put executable test plans directly in commit messages.

Why

  • Makes the commit message’s test plan executable instead of purely descriptive.
    • Great for test-driven development, to ensure that my validation plan actually detects the underlying issue.
    • Great for knowledge sharing and onboarding teammates.
  • Supports re-validating entire commit stacks via git test.
    • Often useful when rebasing on top of upstream changes.
    • On failure, it makes it quick and easy to bisect the first broken commit.
  • Supports ad-hoc and differential testing, where there is no tested correct output, and we just want to document changes.

How

Inside my commit messages, I add scrut code blocks with test commands to run. Example:

fix(tests): fix tests on macOS with Git v2.37

...

Test Plan
---------

```scrut
$ cargo nextest run --workspace --no-fail-fast -- 'submodule'
```

I use a small script called git-test-message to read the commit message and run the scrut tests in the repository working tree:

For individual runs, I invoke it like this:

$ git test-message
🔎 Found 1 test document(s)

Result: 1 document(s) with 1 testcase(s): 1 succeeded, 0 failed and 0 skipped

With git test, I’ve configured it as my default test command, which runs it on the entire stack:

$ git config 'branchless.test.alias.default'
git test-message @

$ git test run
✓ Passed (cached): 624edd2 fix(tests): fix tests on macOS with Git v2.37
Ran command on 1 commit: git test-message @
1 passed, 0 failed, 0 skipped

Patterns

By default, scrut asserts that the command exits successfully and that stdout matches. For some tools, especially bazel, stdout is not interesting or is non-deterministic, so I often redirect it to stderr so that it’s not asserted, but is still logged on failure:

$ bazel test //foo >&2

For ad-hoc validation, when there’s no test case to cover a specific situation, I often pipe to grep or use scrut’s output expectations:

$ bazel run //foo | grep bar
some line with bar

For differential testing, I might record the new behavior, check out the previous commit, record the old behavior, and diff the two:

$ bazel run //foo >after && git checkout HEAD~ && bazel run //bar >before && diff before after
...diff output here...
[1]

The [1] means that exit code 1 is expected from diff.

Script

Here’s my git-test-message script:

#!/bin/bash
set -euo pipefail

mise exec 'cargo:scrut' -- scrut test \
  --work-directory="${PWD}" \
  --match-markdown='*' \
  <(git show --no-patch --format='%B' "${1:-HEAD}")

Notes:

  • My script uses mise to just-in-time provision the scrut binary.
  • By default, scrut works in a temporary directory. I oftentimes run commands that need th repo state, so I added --work-directory=${PWD}.
  • By default, scrut only runs on Markdown input files. I specified --match-markdown='*' to match the process substitution filename (which usually ends up being a path like /dev/fd/63).
  • scrut has features to auto-update the snapshot tests, but I haven’t integrated that (since they’d have to be written back to the Git commit message).
Explore all 68 articles in today's digest

Fresh dev news, AI-digested daily. Never miss a trend at devoured.fyi