| name | git-workflow |
| description | Git conventions covering branch naming, conventional commits, PR format, squash strategy, and protected branches. Use when committing, branching, opening PRs, or setting up a git workflow for a project. |
Git Workflow
Git conventions: branch naming, conventional commits, PR format, squash strategy, and protected branches.
Branch Naming
Use the format: <type>/<ticket>-<short-description>
| Type | Purpose | Example |
|---|
feat/ | New feature | feat/PROJ-123-user-avatars |
fix/ | Bug fix | fix/PROJ-456-login-redirect |
chore/ | Maintenance, deps, config | chore/upgrade-react-19 |
docs/ | Documentation only | docs/api-authentication-guide |
refactor/ | Code restructuring | refactor/extract-auth-module |
test/ | Adding or fixing tests | test/order-service-coverage |
hotfix/ | Urgent production fix | hotfix/payment-timeout |
Rules
- Always branch from
main (or develop if using Git Flow)
- Use lowercase and hyphens -- no underscores, no camelCase
- Include the ticket number when a tracker exists
- Keep descriptions under 5 words
- Delete branches after merging
Conventional Commits
Follow the Conventional Commits specification.
Format
<type>(<scope>): <subject>
<body>
<footer>
Types
| Type | When to Use |
|---|
feat | New feature visible to users |
fix | Bug fix |
docs | Documentation changes only |
style | Formatting, whitespace (no logic changes) |
refactor | Code change that neither fixes a bug nor adds a feature |
perf | Performance improvement |
test | Adding or updating tests |
build | Build system or dependencies |
ci | CI/CD pipeline changes |
chore | Other changes that don't modify src or test files |
revert | Reverts a previous commit |
Rules
- Subject line under 72 characters
- Use imperative mood -- "add feature" not "added feature" or "adds feature"
- No period at the end of the subject
- Scope is optional but encouraged -- use the module or component name
- Body explains why, not what -- the diff shows what changed
- Footer for breaking changes and issue references
Examples
feat(auth): add OAuth2 login with Google
Adds Google OAuth2 as a login option alongside email/password.
Users can link their Google account in settings.
Closes #234
---
fix(cart): prevent duplicate items on rapid clicks
Added debounce to the "Add to Cart" button and server-side
idempotency check using the request ID header.
Fixes #567
---
feat(api)!: change pagination from offset to cursor-based
BREAKING CHANGE: The `page` and `per_page` query parameters are
replaced by `cursor` and `limit`. See migration guide in docs.
Pull Request Format
Title
Use the same format as conventional commits:
feat(auth): add OAuth2 login with Google
Description Template
## Summary
Brief description of what changed and why.
## Changes
- First change
- Second change
- Third change
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing completed
## Screenshots
(if UI changes)
## Related
Closes #123
PR Rules
- One concern per PR -- don't mix features with refactoring
- Keep PRs under 400 lines -- split larger changes into a stack
- Self-review before requesting review -- check the diff yourself first
- Respond to all review comments -- resolve or explain why not
- Update the PR description if scope changes
- Add reviewers based on CODEOWNERS -- or at least one domain expert
Merge Strategy
Squash and Merge (default)
Use squash merge for feature branches:
- All commits in the branch become one commit on
main
- The squash commit message uses the PR title
- The PR description becomes the commit body
- Individual commit history is preserved in the PR
When to Use Regular Merge
- Release branches -- preserve the full history
- Long-lived branches -- when commit history tells a story
- Merge commits from
main into a feature branch -- to stay up to date
When to Rebase
- Before opening a PR -- rebase on
main to get a clean diff
- To clean up local commits -- squash fixups before pushing
Protected Branches
main branch rules
- No direct pushes -- all changes go through PRs
- Require at least 1 approval (2 for critical paths)
- Require passing CI checks -- tests, lint, build
- Require up-to-date branch -- must be rebased on latest
main
- Require signed commits (optional but recommended)
- No force pushes
develop branch rules (if using Git Flow)
- Require passing CI checks
- Allow direct pushes from release managers (optional)
Tagging and Releases
- Use semantic versioning --
v1.2.3
- Tag releases on
main -- after the merge
- Write release notes -- summarize changes since the last release
- Automate with CI -- use GitHub Actions or equivalent to create releases on tag push
git tag -a v1.2.3 -m "Release v1.2.3"
git push origin v1.2.3
Workflow Summary
1. Create branch git checkout -b feat/PROJ-123-user-avatars main
2. Make commits git commit -m "feat(users): add avatar upload"
3. Push branch git push -u origin feat/PROJ-123-user-avatars
4. Open PR gh pr create --title "feat(users): add avatar upload"
5. Review cycle Address feedback, push fixes
6. Squash merge Merge via GitHub UI
7. Delete branch git branch -d feat/PROJ-123-user-avatars
8. Pull main git checkout main && git pull
Anti-patterns
- Committing to
main directly -- always use a branch and PR
- Giant PRs (1000+ lines) -- split into smaller, reviewable chunks
- Vague commit messages -- "fix stuff", "updates", "wip"
- Long-lived feature branches -- merge frequently or use feature flags
- Force pushing shared branches -- only force push your own branches
- Merge commits in feature branches -- rebase instead to keep history clean