engineering-handbook/git-workflow.md
Adam Moussa 2b5fe0f712 Add pre-push hook for npm ci validation
Catches lock file drift locally before it breaks CI. Includes
install instructions in git-workflow.md.
2026-05-14 18:25:10 -04:00

101 lines
3.3 KiB
Markdown

# Git Workflow
## Branching
- Never commit directly to `main`
- Delete branches after merge
- Use the appropriate branch prefix for the type of work:
| Prefix | Use when |
|---|---|
| `feature/<description>` | Adding new functionality or enhancing existing features |
| `bug/<description>` | Fixing a non-urgent defect found during development or testing |
| `hotfix/<description>` | Fixing a production issue that needs immediate attention |
**bug vs hotfix:** Use `bug/` for defects caught before they affect production (failing tests, broken dev flows, issues found in review). Use `hotfix/` only when production is impacted and the fix needs to bypass normal review cadence.
## Commits
- Commit each logical change individually with a descriptive message
- See [commit-messages.md](commit-messages.md) for formatting rules
- Keep the working tree clean: commit or stash before switching context
## Deploy-Then-Merge
The standard flow for changes that deploy to AWS:
1. Create a feature branch (`feature/add-receipt-parser`)
2. Develop and commit locally
3. Open a PR via `gh pr create`
4. Merge the feature branch into `main` locally
5. Deploy to the target environment (`sam deploy`, etc.)
6. Verify in production
7. Merge the PR on GitHub
This ensures production works before the PR closes. If the deploy fails, the PR stays open and `main` on GitHub is still clean.
## Push Discipline
- Push regularly; don't accumulate unpushed commits
- Never force push `main`
- Never amend or rewrite commits already pushed to `main`
- If you need to add context to a past change, use PR descriptions or issue comments
## Versioning
Use [Semantic Versioning](https://semver.org/) (SemVer) as the standard: `MAJOR.MINOR.PATCH`.
| Increment | When |
|---|---|
| `MAJOR` | Breaking changes to the public API or contract (removed endpoints, changed request/response shapes, incompatible config changes) |
| `MINOR` | New functionality that is backwards-compatible (new endpoints, new optional fields, new features) |
| `PATCH` | Backwards-compatible bug fixes, dependency updates, documentation corrections |
### When to version
Not every project needs versioning. Apply SemVer when the project has consumers that depend on its interface:
| Version | Don't version |
|---|---|
| Published packages (npm, PyPI) | Internal SAM stacks with no external consumers |
| Public APIs with external consumers | One-off scripts and migration tools |
| Shared libraries used across repos | Internal tools used only by the team that builds them |
| CLIs distributed to users | |
### How to tag
Create annotated tags on `main` after the PR is merged:
```bash
git tag -a v1.2.0 -m "v1.2.0"
git push origin v1.2.0
```
Start at `v0.1.0` for new projects. Move to `v1.0.0` when the interface is stable and has external consumers.
## Git Hooks
Recommended hooks live in [`hooks/`](hooks/) — copy them into `.git/hooks/` when setting up a project.
| Hook | Purpose |
|---|---|
| `pre-push` | Runs `npm ci` to catch lock file drift before it breaks CI |
Install for a Node.js project:
```bash
cp ~/Documents/repositories/engineering-handbook/hooks/pre-push .git/hooks/pre-push
chmod +x .git/hooks/pre-push
```
## Cleaning Up
After a PR is merged:
```bash
git checkout main
git pull
git branch -d feature/add-receipt-parser
```
Don't let stale local branches or untracked project directories accumulate.