---
url: https://docs.w3id.org/rules/git/minimal-commits.md
---

# `git/minimal-commits`

**Severity:** warning · **Status:** enforced · **Applies to:** `ids/**`

## What

A change to an identifier should be a short series of commits — ideally one.
In particular, one file should not be changed by several commits in a row.

Only commits that touch an identifier are counted. Work elsewhere in the
repository — the documentation, the tooling — is not what this rule is about,
and a branch that touches no identifier is never reported however many commits
it has.

## Why

Adding an identifier is one change. Split across six commits it is six things
to read, and the reviewer has to reconstruct what the final state is before
they can judge it.

Maintaining the rest of the repository is a different activity. There the
history is the useful artifact — what changed, and why, in order — and
flattening it loses something worth keeping.

The usual cause is the GitHub web editor, which commits once per save. Adding
a directory through the browser typically produces something like "Create
README.md", "Create .htaccess", "Update README.md", "Update README.md again" —
four commits for one small change, three of which are corrections to the
first.

Squashing is not about tidiness. It is about the reviewer being able to see
what you are actually asking for.

## Wrong

```
$ git log --oneline upstream/master..HEAD
87738437 Update README.md again
ee4102a0 Update README.md
d3389e3a Create .htaccess
c885985a Create README.md
```

## Right

```
$ git log --oneline upstream/master..HEAD
a1b2c3d4 Add redirect for my-project
```

## How to fix

The simplest way is to tick **Please squash my commits when merging** in the
pull request description, and a maintainer will squash them when merging. Your
fork then needs [resyncing](/faq#do-i-have-to-squash-my-commits) before your
next change.

To squash them yourself:

```sh
git branch backup-my-change   # a copy to go back to if this goes wrong
git rebase -i upstream/master
```

Mark every commit after the first as `squash`, save, and write one message for
the combined change. Check the result with `git show` before you force-push
your branch:

```sh
git push --force-with-lease
```

Partway through, `git rebase --abort` returns to where you started. Afterwards,
your original commits are still on `backup-my-change`; delete it with
`git branch -D backup-my-change` once the pull request is merged.

## How to check

Run `w3id-check` with `--rule git/minimal-commits` to check this rule on its
own; without it the tool runs every rule, as the pull request checks do. This
rule looks at your commits rather than your files, so it needs a base to
compare against; narrowing it to a path would not change what it reports.

```sh
node tools/check/bin/w3id-check.js --rule git/minimal-commits
```

[Testing your changes](/guides/testing) covers installing the tool, and what
else is worth checking by hand.

## See also

* [`git/no-merge-commits`](./no-merge-commits)
* [`git/descriptive-commit-message`](./descriptive-commit-message)
* [Report a false positive or a missing check](https://github.com/perma-id/w3id.org/issues)
