Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

md-track

In a large project .md files get forgotten: the code moves on, the docs stay put. md-track lists every .md in the repository with how many commits the code has had since that doc was last touched.

Plain Bash, git and column. No dependencies, no install, no config.

C_BEHIND is measured in commits, not days. An old doc sitting on frozen code is fine; a recent doc on code that moved 100 commits is not.

Copy-paste commands: RUN.md.

$ md-track
FILE                C_BEHIND  COMMIT   SUBJECT             N_UPDATES
docs/draft.md       NEW       —        never committed     0
src/auth/README.md  105 !     c2950da  docs: login flow    2
docs/deploy.md      102 !     e0a797c  chore: move deploy  1

C_BEHIND, the metric

A modification date on its own says little: a doc from 2019 may be perfectly accurate if its code hasn't changed since. The useful signal is the distance between the two.

The baseline is the last commit that touched the .md. From there, md-track counts code commits. C_BEHIND 3: probably current. 155: almost certainly lying.

The scope is always the whole repository, with one exclusion: commits that only touch *.md don't count as new code. Editing another doc doesn't age this one.

git rev-list --count <md_sha>..HEAD -- . ':(exclude)*.md'

One rule for every file, so all rows are comparable to each other. The price is that the number is an upper bound: a doc may rank high because the project moved a lot, not because its subject changed. Read the table as a relative ranking, not as a verdict per file.

N_UPDATES

How many commits have ever touched that .md:

git rev-list --count HEAD -- <file.md>

It gives C_BEHIND its context. N_UPDATES 1 means the file was written once and never revised — a high C_BEHIND there is an abandoned doc. N_UPDATES 30 with a high C_BEHIND is a different story: someone maintains that doc, the project is simply moving fast.

The other columns

COMMIT is the hash of the .md's last commit. There is no date column: mtime becomes the time of git clone and would lie in CI, and the commit date is noise when the metric's unit is commits. When you need it, git show <hash>.

NEW is a trackable .md that was never committed. No baseline, so no C_BEHIND, and N_UPDATES is 0. It sorts to the top because it's the most actionable: just commit it.

SUBJECT is the title of the .md's last commit, cut at 40 characters, with | replaced by / (a | in the title would shift every column on that row).

N_UPDATES comes last. On a narrow terminal the trailing truncation (below) can now clip it instead of SUBJECT — a tradeoff against having the update count easy to grep/awk for as the final field on the line.

It never breaks the build

Past 99 commits the row gets a !, and that's all. md-track always exits 0.

A built-in limit that fails the pipeline on its own becomes md-track || true in the .yml within a week, and then it may as well not exist. React however you like:

- run: md-track | grep -q ' ! ' && echo "::warning::stale docs" || true

When the output isn't a terminal, lines aren't clipped to the width — you can grep and awk over it without losing columns.

What gets listed

Every .md tracked by git, plus uncommitted ones that .gitignore doesn't hide. Since the list comes from git, node_modules and vendor disappear without a blocklist. A file still in the index but gone from the worktree — deleted, or a dead symlink — is left out: there is no doc there to bring up to date, so a lag number for it would be noise. The script anchors itself at the repo root, so it works from any subdirectory. Outside a git repo: error and exit 1, no degraded mode.

Test

./test.sh builds a temporary repository with a known lag and checks C_BEHIND with the *.md exclusion, N_UPDATES, the NEW case, the 99 mark, a | in the commit subject, and the behaviour outside a git repo. No framework, ~4s (it creates 100 commits).

Known ceiling

Three git calls per file, serially: instant up to a few hundred docs. In a monorepo with thousands, parallelise with xargs -P or switch to a single git log --name-only pass. Marked in the code as ponytail:.

About

Automated Bash audit tool to track git commit drift in Markdown documentation.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages