Git housekeeping

The trivia that separates git-comfortable from git-fluent, all in the “boring but load-bearing” category:

Three ignore files, not one

Nelson Figueroa (capture: clippings/nelson-cloud-gitignore-isnt-the-only-way-to-ignore-files-in-git.md):

  • .gitignore — checked in, shared with everyone (project rules)
  • .git/info/exclude — personal, per-clone, never leaves the machine (your editor scratch files)
  • ~/.config/git/ignore — global personal ignores across ALL repos

The rule: personal patterns never belong in the project’s .gitignore — that’s what the other two are for.

Don’t create .gitkeep — use .gitignore

Adam Johnson (capture: clippings/adamj-eu-tech-2023-09-18-git-dont-create-gitkeep.md): git doesn’t track directories, only files — the .gitkeep convention adds a junk file to fake it. The cleaner trick is a .gitignore in the empty dir ignoring everything except itself (* + !/.gitignore): the dir exists because a tracked file lives in it, and the ignore patterns do real work instead of a placeholder doing none.

Related: Git hooks · Git recovery · Golden repo (what belongs in version control at all)

The GitButler tips series (captured 2026-10-07)

gitbutler.com “There’s a git config for that” (8.5 KB, captured):

  • Conditional configs — the “secret fourth” config source: includeIf in ~/.gitconfig with filters gitdir: (per-directory work/oss identities, signing keys), onbranch: (per-branch values), and hasconfig:remote.*.url (per-remote/org keys). Work/OSS identity split without wrapper scripts.
  • git blame -L — blame a line range, or -L :'/class LocalFile' to blame a whole block found by pattern; git log -L28,43:file retells the same data as the story of the commits that built that block.
  • git blame -w -C -C -C — -w ignores whitespace (prettier reformat won’t reassign ownership); -C follows code movement between files, up to three passes for harder searches. The demo’s kicker: GitLens showed “Kiril wrote this”; -C -C -C shows the block moved file-to-file across renames and Mattias actually wrote most of it — “your GUI does not do this.”
  • git diff --word-diff — word-level diff for small in-line changes.
  • rerere — covered in Git recovery; the series adds rerere.autoUpdate (auto-stage the replayed resolution).

Genre kin: git-flight-rules (OSS) is the recovery manual; this series is the fluency manual — same runbook shape, indexed by capability instead of disaster.

The GitButler tips series, part 2: new stuff (captured 2026-10-07)

gitbutler.com “New stuff in Git” (8.8 KB, captured):

  • branch.sort -committerdate + column.ui — branches by last-commit date in columns instead of alphabetical scroll; his coping hack (sc-0831-my-thing = initials/date/topic crammed into names) becomes unnecessary. Gotcha: -committerdate is a negative, not a --flag. (Bonus: git column is a standalone list-to-columns filter.)
  • --force-with-lease — force push that fails with “stale info” if the remote ref moved since your last fetch; solves the check-then-push race. “Almost always better than --force”: git config --global alias.fpush push --force-with-lease.
  • SSH commit signing — gpg.format ssh + user.signingkey; GPG’s UX misery replaced by the key you already have; GitHub/GitLab verify on upload.
  • git push --signed — signed pushes with a server-side transparency log; only meaningful on self-hosted servers (no major forge supports it; kernel.org writeup by Ryabitsev).
  • git maintenance start — background cron/LaunchAgent strategy incremental: commit-graph + prefetch hourly, loose-object cleanup + incremental repack daily, gc disabled — “make lots of things faster in the background all the time.” The homelab-friendly one for big monorepos.