Git Workflow and Versioning
Overview
Git is your safety net. Treat commits as save points, branches as sandboxes, and history as documentation. With AI agents generating code at high speed, disciplined version control keeps changes manageable, reviewable, and reversible.
When to Use
Always. Every code change flows through git.
Core Principles
Trunk-Based Development
Keep main always deployable. Work in short-lived feature branches that merge back within 1-3 days. Pushes to main trigger AWS Amplify builds.
main ──●──●──●──●──●──●── (always deployable, triggers Amplify)
╲ ╱ ╲ ╱
●──●─╱ ●──╱ ← short-lived feature branches (1-3 days)
1. Commit Early, Commit Often
Work pattern:
Implement slice → Test → Verify → Commit → Next slice
Not this:
Implement everything → Hope it works → Giant commit
2. Atomic Commits
Each commit does one logical thing:
# Good: Each commit is self-contained
a1b2c3d feat: add task creation endpoint with validation
d4e5f6g feat: add task creation form component
h7i8j9k feat: connect form to API and add loading state
m1n2o3p test: add task creation tests (unit + integration)
# Bad: Everything mixed
x1y2z3a Add task feature, fix sidebar, update deps, refactor utils
3. Descriptive Messages
<type>: <short description>
<optional body explaining why, not what>
Types: feat, fix, refactor, test, docs, chore
4. Keep Concerns Separate
Don't combine formatting changes with behavior changes. Don't combine refactors with features.
5. Size Your Changes
~100 lines → Easy to review, easy to revert
~300 lines → Acceptable for a single logical change
~1000 lines → Split into smaller changes
Branching Strategy
main (always deployable, Amplify deploys on push)
│
├── feature/task-creation ← One feature per branch
├── feature/user-settings ← Parallel work
└── fix/duplicate-tasks ← Bug fixes
- Branch from
main - Keep branches short-lived (merge within 1-3 days)
- Delete branches after merge
- Prefer feature flags over long-lived branches
Branch Naming
feature/<short-description> → feature/task-creation
fix/<short-description> → fix/duplicate-tasks
chore/<short-description> → chore/update-deps
refactor/<short-description> → refactor/auth-module
The Save Point Pattern
Agent starts work
│
├── Makes a change
│ ├── Test passes? → Commit → Continue
│ └── Test fails? → Revert to last commit → Investigate
│
└── Feature complete → All commits form a clean history
Change Summaries
After any modification, provide a structured summary:
CHANGES MADE:
- src/routes/tasks.ts: Added validation middleware to POST endpoint
- src/lib/validation.ts: Added TaskCreateSchema using Zod
THINGS I DIDN'T TOUCH (intentionally):
- src/routes/auth.ts: Has similar validation gap but out of scope
POTENTIAL CONCERNS:
- The Zod schema is strict — rejects extra fields. Confirm this is desired.
Pre-Commit Hygiene
# 1. Check what you're about to commit
git diff --staged
# 2. Ensure no secrets
git diff --staged | grep -i "password\|secret\|api_key\|token"
# 3. Run tests
pnpm test
# 4. Run linting and type checking
pnpm lint && pnpm tsc --noEmit
# 5. Run build
pnpm build
DaaS/Amplify-Specific
- The starter repo includes
amplify.yml— pushes tomaintrigger Amplify builds - Initial branch from starter is
temporary-local— create a feature branch before working - Verify with
git remote -vandgit branchbefore pushing - Always validate locally before merging to
main:pnpm install && pnpm build && pnpm test - Use PRs and require CI/build checks before merging to
main
Common Rationalizations
| Rationalization | Reality |
|---|---|
| "I'll commit when the feature is done" | One giant commit is impossible to review, debug, or revert. Commit each slice. |
| "The message doesn't matter" | Messages are documentation. Future you will need to understand what changed. |
| "I'll squash it all later" | Squashing destroys the development narrative. Prefer clean incremental commits. |
| "Branches add overhead" | Short-lived branches are free. Long-lived branches are the problem. |
| "I don't need a .gitignore" | Until .env with production secrets gets committed. Set it up immediately. |
Red Flags
- Large uncommitted changes accumulating
- Commit messages like "fix", "update", "misc"
- Formatting changes mixed with behavior changes
- No
.gitignorein the project - Committing
node_modules/,.env, or build artifacts - Long-lived branches that diverge significantly from main
- Force-pushing to shared branches
Verification
For every commit:
- Commit does one logical thing
- Message explains the why, follows type conventions
- Tests pass before committing
- No secrets in the diff
- No formatting-only changes mixed with behavior changes
-
.gitignorecovers standard exclusions