Skip to content

Repository files navigation

Make every character count, so git log -p clearly and concisely explains changes to an expert programmer. Never waste time as Captain Obvious.

Write self-documenting code as simply as possible. Functional, rule-of-three style is often simplest:

  • Define before use, close to use
  • Inline single-use literals
  • For twice-used literals:
    • Rendered templates, tests, and migrations do not count as usages
    • Reuse single definition when diverging values would cause critical failure
    • Duplicate and inline otherwise, commenting in both places, e.g. same file # dup :12 tasks.uv-pip-compile or # dup other/file.py:345 favorite_function()
    • Search for duplicates when adjusting
  • Choose good names for classes, functions, and variables:
    • Use whole words like index and --long-command-line-arguments
    • Verbs over nouns
    • Avoid abbreviations like i
    • Four Letter AbbreviatioNs (FLANs):
      • COdeNAme (CONA)
      • ENVIronment (ENVI)
      • Fully Qualified Domain Name (FQDN)
      • GIt HAsH (GIHA)
      • ORGanizatioN (ORGN)
      • ROLE (ROLE)
      • TAg/BRanch (TABR)
    • Avoid substring matches
  • Chain function calls
  • Use the ternary operator
  • Use comprehensions and generator expressions
  • Splat/unpack and slice
  • Use for and while loops sparingly
    • Avoid the 1 + N query problem
    • For loops may be needed to append to collections under complex conditions
  • Unless requested, never add new comments:
    • Except to cite or summarize surprising context
    • Keep existing comments
  • Explicitly specify units: preferably in code and data; fall back to comments
  • Approximate autoformatting and linting with
    • 4 space indentations
    • Simplest quotes and minimal escapes
      • Where equivalent, use 'single quotes' instead/outside of "double quotes"
      • """Triple double quote docstrings."""
      • Prefer '{f}-strings' until curly braces show up, then minimize escapes with percent
    • 100 character lines
    • Add fewer than 500 lines per commit/pull request
    • Split files around 500 lines
  • Alphabetize, sometimes within sections (header worth a comment)
  • Order command arguments: positional arguments, alphabetized --flags, then alphabetized --keyword=arguments
  • Use Python 3.12+ idioms like:
    • from pytest import mark; @mark.parametrize()
    • from pathlib import Path; Path('a') / 'b'
    • from subprocess import check_call, check_output; check_call(...); check_output(...)
    • Usually easiest to not re.compile at all than worry about aliasing the builtin
    • Omit #! shebang and explicit encoding lines
  • Write prose like Strunk, White, and Zinsser. Join sentences and sentence fragments with appropriate punctuation; leave freestanding fragments unpunctuated. Use comma, colon, and semicolon frequently. Use parenthesis occasionally. Use em dash rarely, typeset as -- two regular dashes or —.
  • git well:
    • Avoid committing unrelated files by avoiding git add -a, git add --all, git add ., etc.
    • Generally treat removing lint, autogenerating and cleanups as relevant; include them beside features and fixes
    • If asked to clobber uncommitted changes, copy to /tmp/ first
    • Avoid train-of-thought and bisect-breaking commits
    • Be ready to read the (appropriately filtered) git log:
      • Requests to go back or restore usually need the git log to find the previous state
      • Answer authorship and timing questions with evidence from the git log
    • Always track origin/main:
      • This flow combines convention and configuration for efficient everyday commands
      • git switch --create my-feature-or-fix origin/main (old misconfigured branches: git branch --set-upstream-to=origin/main)
      • git pull discovers new commits and rebases because pull.rebase=true
      • git push publishes to the current branch name because push.default=current
    • Slashless branches explicitly permitted. Characters like slash break reuse in contexts like subdomains. Omit any $BRAND/ prefix from branch names. Branding wastes space that should describe the changes.
    • Expect concurrent edits to Pull Request title and description (top comment); always read before revising
    • Use git commit --all --amend --no-edit and squash/fixup to iterate on commits
    • GIT_SEQUENCE_EDITOR=: or similar to avoid interactive commands; stdin is unreliable
    • Follow .github/pull_request_template.md for commit messages / top Pull Request comments
      • Write only highlights and surprises for changes. The details must stay in the Files changed tab / git diff.
      • Report testing as one of:
        • Existing automated tests only
        • Added automated test...
        • A procedure future contributors can reproduce:
          # Manual test procedure
          commands
          to_reproduce
          
      • Never waste space counting or automating existing automated tests
      • Remove headers for empty Pull Request sections
    • Given a stack of local commits
      • Fan each local commit out to its own remote branch
      • Base each Pull Request on the previous branch
  • Favorite tools:
curl
diffstat
gh
git grep
git log
git ls-files
git restore
git switch
host
mise pre-commit-all
mise test
npm
tree
uv
  • Avoid accidentally including .venv, node_modules, full git history; filter appropriately when intentionally searching them for source code and documentation

About

Autoformat the Rule of Three and more

Topics

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages