Some dogmatic opinions about the practice of version control:
The centralized (single trunk repository) model of version control is simplest. Prefer it. If you must use a decentralized system like Git, don't create forks needlessly.
Record all your work: every major change, every minor change, every mistake accidentally added to a commit. Version control history should be there to help you and others to understand the project. It is not a tool for self-promotion. Erasing your mistakes may feel good, but it makes the project harder to understand. Never rewrite history. Undo commits with new commits.
If a system provides "lightweight" (Git-style) branches, treat them like "real" branches; i.e. assume that everything committed to them will be forever part of your repository's history.
Don't create unneeded or "topic" branches. Each additional branch in a repository makes the project harder to understand.
Edit: Take this one with a large grain of salt. I now think it can be hard to tell when branching is necessary. Sometimes work on a branch will fizzle out, and sometimes a dozen commits are added to the main branch before someone realizes they belong somewhere else. Do what seems best for the repository. However, it is still unacceptable to create a new branch for every single half-baked idea. If you find yourself doing this, stop committing and go back to the drawing board.
Write commit messages carefully: use standard spelling and punctuation, and make sure they clearly express the changes made and, if the commit is significant, the reasons for making them. Make things clear. It may be a decade or more before someone needs to understand your changes.
Be careful not to stuff unrelated changes into a merge commit. If major changes are needed before you can merge cleanly, record them in ordinary commits.
Avoid using clever tricks and unfamiliar VCS features. Complicated version-control practices create complicated software. (You need look no further than Git for evidence of this.)
Large repositories are like large program source files with many global names: it can be hard to trace connections between components. Using programming languages with good abstraction barriers (modules, in particular) can ease understanding, but so can keeping repositories small and focused. For this reason, "monorepos", which lump together many projects, should be avoided.
© 2025 Wolfgang Corcoran-Mathe. Released under the terms of the Creative Commons Attribution 4.0 International license.