Releases: gmr/drift
Release list
v1.1.0
Added
- Commits whose message carries a
Drift: ignoretrailer are no longer reported as drift, letting an author explicitly vouch for a change instead of having it show up as unexplained (#4) - New
ignored_commits_skippedfield in the JSON report, counted separately fromcommits_scannedandmerge_commits_skipped - In
--treemode, a path changed only by ignored commits is now reported as unattributed
The trailer's token and value are matched ASCII case-insensitively.
v1.0.0
First release of drift.
.driftignore lists the paths whose changes do not matter. Everything else does.
drift compares two git refs, drops the noise, and reports what is left: the
changes worth acting on, who made them, and how long they have been waiting.
$ drift --tree 1.1.0 main --pretty
{
"drift_detected": true,
"mode": "tree",
"drift_commits": ["0f1e2d3..."],
"drift_authors": ["Ann Author <ann@example.com>"],
"drift_paths": ["src/app.py", "uv.lock"],
"oldest_drift": { "sha": "9a8b7c6...", "age_seconds": 1209600 },
"newest_drift": { "sha": "0f1e2d3...", "age_seconds": 91800 }
}Features
- Accepts any two committish refs: a full or short sha, a tag, a branch,
origin/main,HEAD~3. .driftignore, in gitignore pattern syntax, read from the tree of the newer
ref rather than from disk, so a run never depends on the worktree and always
repeats the same answer.- Two modes.
--log, the default, counts every path the range touched, so work
that was later reverted still reports.--treecounts only the paths whose
content actually differs between the two refs, then attributes each back to the
commits that touched it, which is the honest answer to "is a release worth
cutting". - JSON on stdout: the drift flag, the mode, commit shas, authors, paths, and the
ages of the oldest and newest drift commit. - Flags diverged refs, and lists separately any drifting path that no commit in
the range explains. --fail-on-driftfor CI gates. Exit 0 when the analysis ran, 1 for drift with
that flag, 2 on failure.- Runs entirely in-process through gix.
Nogitbinary is invoked and none needs to be installed.
Defined behavior
Documented in the README and covered by 30 tests:
- The range is
from..to, exactly whatgit log from..tolists. - Merge commits are traversed but never classified; the walk already reaches the
commits on their sides. - Renames are two literal paths, since rename detection is off. Moving a file into
an ignored directory still reports drift at the source path. - Ages come from the committer timestamp against a single clock reading, so the two
ends of the window are always consistent. - Output is newest-first with sorted path lists, byte for byte stable across runs.
Install
Homebrew:
brew install gmr/utils/driftInstall script:
curl -fsSL https://raw.githubusercontent.com/gmr/drift/main/install.sh | shDocker, multi-arch (linux/amd64, linux/arm64):
docker pull ghcr.io/gmr/drift:1.0.0
docker run --rm -v "$PWD:/repo:ro" -w /repo ghcr.io/gmr/drift:1.0.0 --tree 1.1.0 mainThe binary is statically linked against musl, so it can be lifted into any base
image, glibc or musl:
COPY --from=ghcr.io/gmr/drift:1.0.0 /usr/local/bin/drift /usr/local/bin/driftFrom source:
cargo install --git https://github.com/gmr/driftPre-built binaries for x86_64/aarch64 on Linux and macOS are attached below.
Notes
Not published to crates.io: the name drift there belongs to an unrelated
project. Use the Homebrew tap, the install script, the container image, or
cargo install --git.