Git Workflow
Follow these git practices.
Commit Standards
- Never skip hooks (
--no-verify) - Never force push to main/master
- Never commit directly to main (enforced by pre-commit hook)
- Write meaningful commit messages
- Don't update git config via automation
Pre-Commit Validation
Every commit automatically runs these checks:
- Branch Protection - Prevents commits directly to main
- Code Formatting - Prettier formats all staged files
- Linting - ESLint checks and auto-fixes staged TypeScript/JavaScript files
- Type Checking - TypeScript compiler validates entire codebase
- Commit Message - Validates conventional commit format
These checks happen before your commit is created, catching issues immediately.
Branching
All work must be done in feature branches. Direct commits to main are forbidden and blocked by the pre-commit hook.
Creating a Feature Branch
# Create and switch to a new feature branch
git checkout -b feat/my-feature
# Make changes
git add .
git commit -m "feat: add my feature"
# Push to remote
git push origin feat/my-feature
Branch Naming Convention
Use descriptive branch names with prefixes:
feat/feature-name - New features
fix/bug-description - Bug fixes
docs/topic - Documentation changes
refactor/what - Code refactoring
test/what - Test additions/changes
chore/what - Maintenance tasks
What Happens if You Try to Commit to Main?
The pre-commit hook will block the commit and display:
❌ Direct commits to main branch are forbidden!
Please create a feature branch and submit a pull request:
git checkout -b feat/your-feature-name
git add .
git commit -m "feat: your feature description"
git push origin feat/your-feature-name
Then create a pull request on GitHub.
What Happens on Every Commit?
When you run git commit, the pre-commit hook automatically:
🔍 Running pre-commit checks...
# 1. Checks you're not on main branch
# 2. Runs lint-staged:
# - Formats code with Prettier
# - Runs ESLint with auto-fix
# 3. Runs full typecheck
🔍 Running type checking...
# TypeScript compiler validates all files
✅ Pre-commit checks completed successfully!
If any check fails, the commit is blocked and you'll see the specific error to fix.
Handling Pre-Commit Hook Failures
Formatting/Linting Issues:
# lint-staged automatically fixes most issues
# If fixes were applied, stage them and commit again:
git add .
git commit -m "feat: your feature"
Type Errors:
# Fix the type errors shown in the output
# Then try committing again:
git commit -m "feat: your feature"
Slow Typecheck?
For large codebases, full typecheck on every commit can be slow. If this becomes an issue, you can temporarily bypass typecheck:
# NOT RECOMMENDED - Only use when absolutely necessary
SKIP_TYPECHECK=1 git commit -m "feat: your feature"
However, your code will still be typechecked in CI, so it's better to fix type errors locally.
Why Pre-Commit Checks Matter
| Benefit | Description |
|---|---|
| Faster feedback | Catch errors in seconds, not minutes |
| Cleaner commits | All code is formatted consistently |
| Fewer failed CI runs | Issues caught before pushing |
| Better code quality | Linting enforced on every commit |
| Reduced review time | Reviewers focus on logic, not formatting |
Release PRs
Release Please automatically creates Release PRs when you have releasable commits (feat, fix, perf).
What are Release PRs?
- Special PRs titled "chore(main): release X.Y.Z"
- Created and managed by Release Please bot
- Contains version bump + changelog updates
- Accumulates multiple commits until merged
Handling Release PRs
Do:
- Review the version bump and changelog
- Verify all changes are included
- Merge when ready to release
Don't:
- Modify Release PRs manually
- Add code changes to Release PRs
- Close Release PRs unnecessarily (bot will recreate)
When you merge a Release PR:
- GitHub Release is created automatically
- Deployment workflow triggers
- You approve the production deployment
Commit Messages
Use clear, descriptive messages following conventional commit format (enforced by commit-msg hook):
✅ GOOD (Conventional Commits):
- "feat: add fund creation validation"
- "fix: correct NAV calculation for zero units"
- "feat: update EOD service to handle missing prices"
- "docs: add CI/CD documentation"
- "chore: update dependencies"
❌ BAD:
- "Fix bug" (missing type prefix)
- "Update code" (missing type prefix)
- "WIP" (not descriptive)
- "feat add feature" (missing colon)
Conventional Commit Format
All commits must follow this format (enforced by commit-msg hook):
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat:- New feature (minor version bump)fix:- Bug fix (patch version bump)perf:- Performance improvement (patch version bump)docs:- Documentation only (no version bump)style:- Formatting, missing semicolons, etc. (no version bump)refactor:- Code restructuring (no version bump)test:- Adding tests (no version bump)build:- Build system changes (no version bump)ci:- CI/CD changes (no version bump)chore:- Maintenance tasks (no version bump)
Breaking Changes:
Add ! after type or BREAKING CHANGE: in footer for major version bump:
feat!: redesign authentication API
BREAKING CHANGE: Auth endpoints now require OAuth2
Scope (optional):
feat(auth): add Google OAuth
fix(portfolio): correct equity calculation
docs(api): update investor endpoints