"Atomic" in the context of commits means: one batch of changes, one topic, one goal. Not "fixed a bug + renamed a variable + updated react-router".
Rules
- One logical change, one commit. If the message needs the word "and", you probably have two commits.
- The build passes on every commit.
git bisectdepends on this. - The commit is reversible via revert. No side effects.
- No "WIP", "fix typo", "addresses comments" in the public history. Squash these before a PR using interactive-rebase.
Why it matters
git bisectlocalizes a regression inlog(N)steps. Broken commits in the history confuse bisect.git revert <sha>cleanly undoes one feature. If a commit covers three topics, innocent changes get rolled back too.git blamehelps you understand the context of a change. A commit that "touched everything" provides no context.- Code review is much faster. One atomic commit is one thought to review.
What "atomic" does NOT mean
- Not "small". A large refactor touching 30 files in a single commit is fine, as long as every change belongs to the same topic.
- Not "one file". A file and a logical change are different axes. One topic may touch many files.
- Not "written in one sitting". Atomicity is about the final shape of
the commit, not the writing process. Write freely first, then use
interactive-rebase and
git add -pto compose atomic commits.
How to split an accumulated edit
The fastest approach is git add -p:
git add -p src/auth/
git commit -m "feat(auth): add OAuth provider"
git add -p src/billing/
git commit -m "fix(billing): handle null currency"
git add -p src/utils/
git commit -m "refactor(utils): extract date helpers"
You pick hunks that belong to the current commit. The rest goes into the next ones.
If changes are interleaved within a file, Git splits them into hunks
automatically. When the automatic split is wrong, use s (split) or e
(edit) in patch mode.
Pitfalls
- Perfectionism gets in the way. Atomicity is a convenience, not a religion. If splitting will take an hour for a one-line fix, skip it. Use judgment.
- Atomic does not mean many tiny commits. Ten
pick / squash / fixupentries in reflog is a normal working style. One clean commit lands on main.