Adds 3 new topic files (ai-parallel-agents, api-integration, python-patterns) and extends 21 existing topic files with new gotchas and patterns surfaced from memory across tracked projects. Index updated accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7.4 KiB
Git & Source Control
Commit Practices
- Use meaningful commit messages; prefer small, focused commits over large batches
- Never commit secrets in plaintext — use SOPS + age or equivalent encryption
- Enable pre-commit hooks where appropriate (secret detection, linting, formatting)
- Commit each implementation phase separately. For multi-phase milestones, commit at each phase boundary with tests passing. Each commit should be self-contained and independently describable. Phase-by-phase commits surface issues early, keep history bisectable, and make later review and reflection far easier than one large end-of-milestone commit.
Repo Initialization
- Rename default branch immediately after
git init.git initstill createsmasteron many systems despitemainbeing the modern default. Rungit branch -m master main(or configureinit.defaultBranch = mainglobally) before first push — otherwisegit push -u origin mainfails withsrc refspec main does not match any. Bake this into any project-bootstrap script.
Pre-Commit Hooks
- Block
local_secrets/and similar directories from being committed - Auto-encrypt files matching
.sops.yamlrules that aren't yet encrypted - Enable with
git config core.hooksPath .githooks - Consider secret detection, linting, and formatting hooks
- Copy hook scripts into
.git/hooks/; don't symlink. A symlinked hook resolves to the working-tree file, which changes on every branch switch — hooks then run stale (or wrong-branch) logic. Use aninstall-hooks.shthat copies the source script into.git/hooks/, and re-run it whenever the source changes. - Document the sync-then-commit sequence when hooks require an up-to-date main. If a pre-commit hook requires local
mainto matchorigin/main, the commit silently blocks when localmainis even one commit behind. Standard sequence:git checkout main && git pull --ff-only && git checkout <branch> && git rebase main.
GitOps Workflow
- All infrastructure changes should be tracked in Git
- No manual changes without corresponding GitOps manifests — anything applied manually (e.g.,
kubectl apply,helm install) should immediately get a corresponding tracked manifest - For ArgoCD-managed clusters: edit in Git, push, sync — never edit live resources directly
Separate Data Repos from Code Repos for GitOps Controllers
When a GitOps controller watches a git repo for declarative state (zone files, policy documents, config blobs), keep that data in a repo separate from the controller's app code. Mixing the two means every data change triggers CI builds (container rebuilds, test runs) for no reason, and pollutes the code repo's history with non-code churn.
Separation yields:
- Pure data commits with no CI noise
- Cleaner webhook targeting per-repo
- Independent access control for data editors vs code maintainers
- Simpler rollback semantics — revert a data change without touching the controller image
Remote Conventions
- SSH workflows preferred over HTTPS for Git remotes
- Use SSH config host aliases for multi-user setups (e.g.,
gitea.example.com-<user>) - Remote URL format:
git@<host-alias>:<org>/<repo>.git - Optionally push-mirror to GitHub for public visibility
- Prefer internal hostnames for self-hosted Git remotes on the local network. SSH push to a self-hosted Git server through a public/VPS hostname can return
kex_exchange_identification: read: Connection reset by peer, especially during heavy agent activity — VPS routes often have connection limits or rate limiting that fail silently under load. On the local network, use the internal hostname in SSH aliases for heavy push workflows; reserve the public hostname for external access or HTTPS. Test withssh -T <alias>immediately after configuring.
Cross-User Pushes
- Prefer SSH aliases over temp-URL swaps. When a repo is owned by user A but your default SSH key authenticates as user B, configure a dedicated SSH host alias (
Host gitea.example.com-userAwith matching private key) and usegit@gitea.example.com-userA:org/repo.git. Avoid temp-URL-swap (embedding an HTTPS token in the remote URL, pushing, then resetting) — it's clunky, prone to shell-quoting errors, and leaks tokens into reflog/history. - API-created repos need the SSH user as a collaborator. If a repo is created via API token (user A) but pushes use an SSH alias authenticating as user B, user B has no access by default. Add the SSH-authenticating user as admin collaborator via API before the first push. Applies to Gitea, GitHub, and any platform where API auth and SSH auth use different identities.
Access and Clone Gotchas
- Org repos require explicit collaborator grants. Don't assume organizational membership implies write access — verify permissions before setting up automation or CI/CD.
- Shallow clones break push operations.
git clone --depth 1is fine for read-only CI jobs, but pipelines that push artifacts, tags, or mirror to other remotes need full clones.
Cross-Remote Hygiene for Multi-Remote Projects
When a project has divergent remotes (e.g., local Gitea with granular commits + GitHub with squash-merged PRs), histories diverge and naive merges explode.
- Never
git merge <remote>/<branch> --allow-unrelated-histories— it produces 50+ mass conflicts across unrelated files. - Import specific files instead:
git checkout <remote>/<branch> -- <specific-files>brings those paths in as a normal local change. - Always diff after a bulk checkout.
git checkoutfrom a remote silently overwrites locally-modified files with older remote versions with zero warning. Rungit statusand review each touched file before staging; restore withgit checkout HEAD -- <file>if an unwanted overwrite happened. - After an upstream PR squash-merge, reset — don't rebase — local branches to main. Rebase against a squashed history leaves phantom commits; a clean
git reset --hard origin/mainon the local branch is correct.
Version Management
- Use the latest stable version of dependencies unless pinned for a reason
- Verify versions from live sources (
helm search repo, upstream docs, package registries) — don't rely on memory - Document the reason in a comment if a version is intentionally pinned below latest
- Check compatibility matrices before upgrading (e.g., Talos ↔ Kubernetes, framework ↔ runtime)
Placeholder Conventions in Template-Heavy Repos
When files contain multiple templating syntaxes (Go templates {{ .var }}, CI variables ${{ }}, Helm {{ }}, etc.), use a distinct placeholder convention for your own substitutions that can't be confused with any templating language:
- Double-underscore:
__CUSTOMER_NAME__,__DOMAIN__ - All-caps curly brace (no spaces):
{{CUSTOMER_NAME}}(distinct from Go's{{ .Title }}with spaces and dots)
Choose one convention per repo and document it.
Git Worktrees for Parallel Agent Work
When running parallel agents or tasks that modify the same repo:
- Give each task its own branch and worktree (
git worktree add .worktrees/<task-id> -b <branch>) - Tasks with no dependencies branch from HEAD; tasks with one dependency branch from that dependency's branch
- Tasks with multiple dependencies get an octopus merge base branch
- Worktrees share the
.gitobject store — fast creation, minimal disk usage - Keep containers detached (
docker run -d, not--rm) so logs survive for inspection after exit