2021-01-02-Every-commit-should-be-perfect.gmi (5339B)
- Good commit discipline with git pays dividends in many respects, most of which are difficult to achieve with other version control systems. Each commit to your repository’s main branch should be exactly the correct size, be it large or small, such that it introduces one atomic unit of change. It should fix one bug, introduce one feature, refactor one system, and do so completely, rather than spreading the change out across several commits.
- Don’t invoke reductio ad absurdum here — the right size is not necessarily the smallest possible size. If you’re making a lot of similar changes in a refactoring effort, one large commit is better than a hundred commits, one for every affected function. On the other hand, avoid introducing several logically unrelated changes in a single commit. There’s a balance you must seek: seek the correct size for your change.
- There are numerous advantages to taking this approach. Some of the strongest are that every commit in your repository can be expected to be relatively sane and useful, such that you can check out any version of your code and expect all features which are present to be in approximately good working order. This is nice for an individual digging through the history, but it’s especially nice when you consider how well this composes with tools like git bisect to do things like automatically search through thousands of commits to identify which one introduced a bug.
- => https://git-scm.com/docs/git-bisect git bisect manual
- If you have good commit message discipline as well, another advantage of this approach is free changelogs via git shortlog. Linus Torvalds uses this for Linux (example: Linux 5.10 announcement). He’ll do a short write-up about the release in prose, followed by the detailed changes generated by git shortlog.
- => https://git-scm.com/docs/git-shortlog git shortlog manual
- => https://lore.kernel.org/lkml/CAHk-=whCKhxNyKn1Arut8xUDKTwp3fWcCj_jbL5dbzkUmo45gQ@mail.gmail.com/T/#u Linux 5.10 release notes
- To do something similar with your own commit messages, consider using the following style:
- ```
- subsystem: change foo to bar
- foo has long been a point of technical debt for subsystem, causing problems A,
- B, and C. Following discussions on how to address this[0], bar was settled on as
- the solution.
- This changes foo to bar throughout subsystem. Follow-up work will consider if a
- similar change is appropriate for othersystem.
- [0] https://example.org/archive/foo-to-bar-proposal
- ```
- Keep your subject line short, starting with a prefix (“subsystem:") indicating the affected part of the software, then a sentence which completes the following phrase: “when applied, this commit shall…”. Instant changelogs! Following up with additional details, explaining the context, rationale, trade-offs, and follow-up work incurred by the change, is a good way to elaborate for anyone who wants to learn more, today or tomorrow.
- It is, of course, difficult to maintain the necessary level of discipline to produce perfect, atomic units of change. Knowing exactly how large your change needs to be, and ensuring that it is free of bugs on the first try, is an unreasonable ask for most. You may prefer to take an incremental approach to your change, making several small commits over time. Git comes to our rescue again, providing several tools to aid in this effort, chief among them being git rebase.
- => https://git-rebase.io/ Read my git rebase tutorial
- When you’re ready to bring your changes upstream, you can use git rebase to cut, paste, merge, split, reorder, and rewrite commits as necessary to form a more perfect (and useful!) commit history, such that this principle of atomic change is upheld. The record of your incremental progress is not lost — see git reflog — and you will earn all of the advantages of a clear, concise, and correct commit log. As you receive feedback on your patch and make updates, continue to rebase and improve your original commit, or commits.
- => https://git-scm.com/docs/git-reflog git reflog manual
- Another great tool to make this easier is git add -p or git commit -p, which breaks down your uncommitted changes into smaller hunks, asking you which changes to include in your commit on a line-by-line basis. This is helpful when you’re working on entangled problems and it’s not clear how to split them until you finish working, or if you make minor, unrelated fixes here and there as you work on a problem.
- => https://git-rebase.io/#edit git commit -p details on git-rebase.io
- When you get good at these tools, you’re able to treat the state of your git repository as an extension of your normal thought process. You can come up with novel solutions and workflows on the fly, freely composing tools in such a way that you can work on many problems at once and make frequent mistakes, and still emerge with a tidy commit log. Learning git like the back of your hand, studying its deep features, and grokking its internals, are investments which will pay off massively for you in the future. If you strive to become git literate, and exercise good git discipline, then you will be rewarded with convenience, flexibility, and robustness.
- => https://drewdevault.com/2020/04/06/My-weird-branchless-git-workflow.html Recommended reading: My unorthodox, branchless git workflow