Engineering
Git Workflow
Branching strategy, conventional commits, PR anatomy, and review etiquette for professional team collaboration.
Branching
Branching Strategy
We use trunk-based development: short-lived feature branches merged frequently into main. No long-running branches.
Avoid
- Branches open for weeks
- Merging directly to main without a PR
- Feature branches with multiple unrelated changes
dev/stagingas permanent integration branches- Force-pushing to shared branches
Do
- Branch from
main, merge back within 1–2 days - One concern per branch
- Name:
feat/webhook-retry,fix/amount-validation - Delete branch after merge
- Rebase before opening PR to reduce noise
Branch lifecycle
branch from main
→
make commits
→
open PR
→
review + CI pass
→
squash merge to main
→
delete branch
Commits
Conventional Commits
Every commit message follows type(scope): description — lowercase, imperative mood, no period at the end.
| Type | When to use | Example |
|---|---|---|
feat |
New feature or behaviour | feat(webhook): add idempotency check on payment events |
fix |
Bug fix | fix(payment): reject negative amount values |
refactor |
Code change with no behaviour change | refactor(service): extract retry logic into RetryPolicy |
test |
Adding or updating tests | test(webhook): assert duplicate events are ignored |
docs |
Documentation only | docs(api): document POST /webhooks/payment contract |
chore |
Build, config, dependencies | chore: upgrade laravel/framework to 11.x |
perf |
Performance improvement | perf(events): add index on created_at for event queries |
If you can't find a single type that fits, the commit does too many things. Split it.
Pull Requests
PR Anatomy
A PR is a communication artifact, not just a code upload. The description is a status report to the reviewer and the future reader of git history.
## What
Brief explanation of what changed and why — not a diff summary, the WHY.
## How
Key design decisions made. Alternatives considered and rejected.
## Test plan
- [ ] Unit tests pass (`php artisan test`)
- [ ] Manually verified: duplicate webhook → 200, no duplicate row created
- [ ] Edge case: amount = 0 returns 422
## Notes for reviewer
Anything the reviewer should focus on or a known trade-off to discuss.
Bad PR title
- WIP
- fixes stuff
- update PaymentService.php
Good PR title
- feat(webhook): add idempotency for duplicate payment events
- fix(api): return 422 when amount is negative
- refactor(service): extract queue dispatch to dedicated job
Code Review
Review Etiquette
Code review is a dialogue. The goal is to ship better code — not to find fault. Both author and reviewer have responsibilities.
Author — avoid
- Submitting without a description
- PRs with 20+ files changed
- Getting defensive about comments
- Marking comments as resolved before discussing
- Merging before CI is green
Author — do
- Self-review before requesting review
- Explain non-obvious decisions inline
- Keep PRs small and focused
- Respond to every comment, even if just "done"
- Ask for a follow-up ticket for out-of-scope feedback
Reviewer — avoid
- "This is wrong." (no explanation)
- Nitpicking style that linters already catch
- Blocking on personal preference
Reviewer — do
- Prefix: nit: (style) vs blocking: (must fix)
- Explain the why behind every blocking comment
- Approve once blocking items are resolved
Hygiene
Git Hygiene
A clean history is documentation. Future-you and your teammates will thank present-you.
Anti-patterns
- Committing
.env, secrets, or compiled assets - Amending already-pushed commits
git add .without reviewing what's staged- Commits like "fix", "wip", "asdfgh"
- Squashing all history into one mega-commit
- Merge commits from pulling (use rebase)
Good habits
- Use
.gitignoreproactively; never commit secrets - Stage hunks with
git add -pfor precision - Use
git pull --rebaseas default - One logical change per commit
- Squash WIP commits before opening PR
- Tag releases; don't rely only on branch names
Set
git config --global pull.rebase true once and never deal with accidental merge commits again.