
Dev Git Workflow
- 90 installs
- 73 repo stars
- Updated July 13, 2026
- vasilyu1983/ai-agents-public
Helps with automation & workflows tasks.
About
dev-git-workflow is a Claude Code skill for automation & workflows. It helps solo builders move faster with AI-assisted development.
- dev-git-workflow
- Automation & Workflows
- AI-coding skill
Dev Git Workflow by the numbers
- 90 all-time installs (skills.sh)
- +2 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #847 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/vasilyu1983/ai-agents-public --skill dev-git-workflowAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 90 |
|---|---|
| repo stars | ★ 73 |
| Last updated | July 13, 2026 |
| Repository | vasilyu1983/ai-agents-public ↗ |
What it does
Helps with automation & workflows tasks.
Files
Git Workflow (Modern Team Collaboration)
Use modern Git collaboration patterns: GitHub Flow for continuous deploy, trunk-based for scale, Conventional Commits for automation, stacked diffs for large features.
Use this skill to choose a branching model, standardize PR discipline, enforce commit conventions, and harden repository settings for safe collaboration.
Quick Start
1. Identify constraints (team size, release cadence, CI maturity, compliance). 2. Choose a branching strategy using the decision tree. 3. Apply the baseline repo settings (branch protection, approvals, checks, merge strategy). 4. Use the relevant reference doc for implementation details. 5. If asked "best practice in 2026", verify via web search using data/sources.json as a starting source list.
Quick Reference
| Task | Tool/Command | When to Use | Reference |
|---|---|---|---|
| Create feature branch | git switch -c feat/name main | Start new work | Branching Strategies |
| Create feature worktree | git worktree add .worktrees/feature -b feature/name | Isolate one feature per agent/branch | AI Agent Worktrees |
| Squash WIP commits | git rebase -i HEAD~3 | Clean up before PR | Interactive Rebase |
| Conventional commit | git commit -m "feat: add feature" | All commits | Commit Conventions |
| Force push safely | git push --force-with-lease | After rebase | Common Mistakes |
| Resolve conflicts | git mergetool | Merge conflicts | Conflict Resolution |
| Create stacked PRs | gt create stack-name (Graphite) | Large features | Stacked Diffs |
| Auto-generate changelog | npx standard-version | Before release | Release Management |
| Run quality gates | GitHub Actions / GitLab CI | Every PR | Automated Quality Gates |
AI Agent Feature Loop
[AI Agent Worktrees Reference](references/ai-agent-worktrees.md) — Full guide to worktree isolation for Claude Code, Codex, Aider, and other AI coding agents.
flowchart LR
A[Plan] --> B[Create worktree<br>per agent/feature]
B --> C[Verify .gitignore<br>+ install deps]
C --> D[Agent works<br>scoped commits]
D --> E[Quality gates]
E -->|pass| F[PR + merge]
E -->|fail| D
F --> G[Cleanup worktree<br>+ delete branch]
style D fill:#fff3cd,stroke:#d4a017
style F fill:#d4edda,stroke:#28a745For AI-assisted engineering, prefer this default loop:
1. Create one worktree per feature branch (git worktree add .worktrees/<feature> -b feature/<name>). 2. Verify the worktree directory is in .gitignore (git check-ignore -q .worktrees). 3. Install dependencies and verify clean test baseline before starting work. 4. Implement scoped changes only for that feature. 5. Run repository quality gate(s) before PR. 6. Open one focused PR to the integration branch. 7. After merge, clean up: git worktree remove + git branch -d.
Parallel agents: One worktree per agent, disjoint file ownership, orchestrator merges from main. See AI Agent Worktrees for setup, safety patterns, and cleanup.
If repository scripts exist (for example scripts/git/feature-workflow.sh), use them to enforce this loop.
Local Safety Preflight (Before Checkout/Merge/Commit)
Use this quick sequence to avoid common local Git blockers during agent-driven work.
1. Working tree cleanliness:
git status --porcelain- If non-empty, decide explicitly: commit, stash, or abort branch switch.
2. Lock/process check:
- If Git commands fail with
index.lock, check running Git processes first: test -f .git/index.lock && ps aux | rg "[g]it"- Remove stale lock only after confirming no active Git process.
3. Branch switch guard:
- Do not
checkout/switchwhen local changes would be overwritten. - Commit/stash intentionally; avoid accidental context loss.
4. Merge conflict protocol:
- On conflict, stop new edits, resolve conflict file-by-file, rerun relevant tests, then complete merge commit.
5. Automation note:
- For recurring branch operations, prefer project scripts/worktrees over ad-hoc local branch juggling.
Decision Tree: Choosing Branching Strategy
Use this decision tree to select the optimal branching strategy for your team based on team size, release cadence, and CI/CD maturity.
Team characteristics -> What's your situation?
├─ Small team (1-5 devs) + Continuous deployment + High CI/CD maturity?
│ └─ GitHub Flow (main + feature branches)
│
├─ Medium team (5-15 devs) + Continuous deployment + High CI/CD maturity?
│ └─ Trunk-Based Development (main + short-lived branches)
│
├─ Large team (15+ devs) + Continuous deployment + Very high CI/CD maturity?
│ └─ Trunk-Based + Feature Flags (progressive rollout)
│
├─ Scheduled releases + Medium CI/CD maturity?
│ └─ GitFlow (main + develop + release branches)
│
└─ Multiple versions + Low-Medium CI/CD maturity?
└─ GitFlow (long-lived release branches)Navigation: Core Workflows
Branching Strategies
[Branching Strategies Comparison](references/branching-strategies.md) - Comprehensive guide to choosing and implementing branching strategies
- GitHub Flow (recommended for modern teams): Simple, continuous deployment
- Trunk-Based Development (enterprise scale): Short-lived branches, daily merges
- GitFlow (structured releases): Scheduled releases, multiple versions
- Decision matrix: Team size, release cadence, CI/CD maturity
- Migration paths between strategies
Pull Request Best Practices
[PR Best Practices Guide](references/pr-best-practices.md) - Effective code reviews and fast PR cycles
- PR size guidelines: keep PRs reviewable (often 200-400 LOC works well; split larger changes)
- Review categories: BLOCKER, WARNING, NITPICK
- Review etiquette: Collaborative feedback, code examples
- PR description templates: What, Why, How, Testing
- Data-driven insights on review efficiency
Commit Conventions
[Conventional Commits Standard](references/commit-conventions.md) - Commit message formats and semantic versioning integration
- Conventional commit format:
type(scope): description - Commit types: feat, fix, BREAKING CHANGE, refactor, docs
- SemVer automation: Auto-bump versions from commits
- Changelog generation: Automated from commit history
- Tools: commitlint, semantic-release, standard-version
---
Navigation: Advanced Techniques
Stacked Diffs
[Stacked Diffs Implementation](references/stacked-diffs-guide.md) - Platform-specific workflows and team adoption
- What are stacked diffs: Break large features into reviewable chunks
- When to use: Features > 500 lines, complex refactoring
- GitLab native support: MR chains
- GitHub with Graphite: CLI-based stacking
- Benefits: 60% faster review cycles, better quality
Interactive Rebase
[Interactive Rebase & History Cleanup](references/interactive-rebase-guide.md) - Maintain clean commit history
- Auto-squash workflow:
fixup!andsquash!commits - Interactive rebase commands: pick, reword, edit, squash, fixup, drop
- Splitting commits: Break large commits into focused changes
- Reordering commits: Logical commit history
- Best practices: Never rebase public branches
Conflict Resolution
[Conflict Resolution Techniques](references/conflict-resolution.md) - Merge strategies and conflict handling
- Resolution strategies:
--ours,--theirs, manual merge - Rebase vs merge: When to use each
- Merge tool setup: VS Code, Meld, custom tools
- Conflict markers: Understanding
<<<<<<<,=======,>>>>>>> - Prevention strategies: Frequent rebasing, small PRs
---
Navigation: Automation & Quality
Automated Quality Gates
[Automated Quality Gates](references/automated-quality-gates.md) - CI/CD pipelines and quality enforcement
- Essential gates: Tests, coverage, linting, security scans
- Advanced gates: Performance benchmarks, bundle size, a11y checks
- GitHub Actions workflows: Complete PR checks pipeline
- GitLab CI pipelines: MR quality gates
- Pre-commit hooks: Husky + lint-staged setup
- Quality metrics thresholds: Coverage 80%, complexity < 10
Validation Checklists
[Validation Checklists](references/validation-checklists.md) - Pre-PR, pre-merge, pre-release checklists
- Before creating PR: Code quality, commit hygiene, testing
- Before merging PR: Review process, CI/CD checks, final verification
- Before releasing: Pre-release testing, version management, documentation
- Post-deployment: Immediate verification, monitoring, tasks
- Hotfix checklist: Critical bug fast-track process
Release Management
[Release Management](references/release-management.md) - Versioning and deployment workflows
- Semantic versioning: MAJOR.MINOR.PATCH
- Manual release workflow: GitFlow release branches
- Automated releases: semantic-release automation
- Hotfix workflow: Emergency patches
- Changelog generation: Keep a Changelog format
- Release checklists: Pre-release, release day, post-release
---
Navigation: AI Agent Workflows
AI Agent Worktrees
[AI Agent Worktrees](references/ai-agent-worktrees.md) - Worktree isolation patterns for AI coding agents
- When to use worktrees with agents (decision table)
- Directory conventions (
.worktrees/, global paths,.gitignore) - Agent-specific patterns: Claude Code, Codex, Aider, Copilot Workspace
- Parallel agent execution: one worktree per agent, disjoint file ownership
- Safety: lock contention, conflict detection, cross-agent file guards
- Cleanup lifecycle: removal, pruning, batch cleanup scripts
---
Navigation: Learning & Troubleshooting
Monorepo Workflows
[Monorepo Workflows](references/monorepo-workflows.md) - Git patterns for monorepo repositories
- Trunk-based branching for monorepos
- Sparse checkout and partial clone
- Affected-only CI (Nx, Turborepo, Bazel)
- CODEOWNERS per package/directory
- Monorepo vs polyrepo decision table
Git Hooks Automation
[Git Hooks Automation](references/git-hooks-automation.md) - Pre-commit, commit-msg, pre-push hooks
- Husky v9+ and lefthook setup
- lint-staged and commitlint integration
- Custom hooks (gitleaks, file size limits, branch naming)
- Team distribution strategies
Git Bisect Debugging
[Git Bisect Debugging](references/git-bisect-debugging.md) - Regression hunting with git bisect
- Manual and automated bisect workflows
- Writing bisect test scripts
- Handling merge commits, log and replay
Common Mistakes
[Common Mistakes & Fixes](references/common-mistakes.md) - Learn from common pitfalls
- Large unfocused PRs -> Split into stacked diffs
- Vague commit messages -> Use conventional commits
- Rewriting public history -> Never rebase main
- Ignoring review comments -> Address all feedback
- Committing secrets -> Use environment variables
- Force push dangers -> Use
--force-with-lease
Decision Tables
When to Use Each Branching Strategy
| Requirement | GitHub Flow | Trunk-Based | GitFlow |
|---|---|---|---|
| Continuous deployment | [OK] Best | [OK] Best | [FAIL] Poor |
| Scheduled releases | [WARNING] OK | [WARNING] OK | [OK] Best |
| Multiple versions | [FAIL] Poor | [FAIL] Poor | [OK] Best |
| Small team (< 5) | [OK] Best | [WARNING] OK | [FAIL] Overkill |
| Large team (> 15) | [WARNING] OK | [OK] Best | [WARNING] OK |
| Fast iteration | [OK] Best | [OK] Best | [FAIL] Poor |
PR Size vs Review Time
| LOC | Review Time | Bug Detection | Recommendation |
|---|---|---|---|
| < 50 | < 10 min | High | [OK] Ideal for hotfixes |
| 50-200 | 10-30 min | High | [OK] Ideal for features |
| 200-400 | 30-60 min | Medium-High | [OK] Acceptable |
| 400-1000 | 1-2 hours | Medium | [WARNING] Consider splitting |
| > 1000 | > 2 hours | Low | [FAIL] Always split |
Do / Avoid
GOOD: Do
- Keep PRs under 400 lines (200-400 optimal)
- Use conventional commit messages
- Rebase before opening PR (clean history)
- Require at least one approval before merge
- Run CI checks on every PR
- Use stacked diffs for large features (>500 LOC)
- Squash WIP commits before merge
- Use
--force-with-lease(not--force)
BAD: Avoid
- Long-lived feature branches (>3 days)
- Merging without review
- Rebasing public/shared branches
- Force pushing to main/master
- Committing secrets (even "temporarily")
- Large monolithic PRs (>1000 lines)
- Vague commit messages ("fix", "update")
- Skipping CI to merge faster
Anti-Patterns
| Anti-Pattern | Problem | Fix |
|---|---|---|
| Long-lived branches | Merge conflicts, stale code | Trunk-based, short branches |
| Unreviewed merges | Bugs reach production | Branch protection rules |
| Rebasing main | History corruption | Never rebase public branches |
| 1000+ LOC PRs | Poor review quality | Stacked diffs, split PRs |
| "fix" commits | Unclear history | Conventional commits |
| No CI gates | Broken main | Required status checks |
| Secrets in history | Security breach | Pre-commit hooks, gitleaks |
Repository Baseline (Security + Reliability)
Set these repo defaults before scaling a team:
- Branch protection: require PRs to
main(no direct pushes), require status checks, require up-to-date branch on merge. - Review gates: require approvals; enforce CODEOWNERS for sensitive paths (auth, payments, infra, prod configs).
- History policy: pick merge strategy (squash vs merge commits) and make it consistent; document exceptions.
- Signed changes: require signed commits and signed tags for releases (team-specific key management).
- Secret prevention: local pre-commit + server-side secret scanning/push protection; rotate on incident.
- Merge safety: use merge queue (or equivalent) for busy repos to keep
maingreen under high concurrency. - Cost control: cache dependencies/builds; run heavy jobs conditionally; cap CI minutes for untrusted forks.
Template: assets/pull-requests/pr-template.md Guide: assets/template-git-workflow-guide.md
Security-Sensitive Changes
For security-related git operations, see dev-git-commit-message/assets/template-security-commits.md:
- Secrets detection with pre-commit hooks
- Handling accidental secret commits
- Security commit metadata (CVE, CVSS)
- Branch protection for security-sensitive code
Optional: AI/Automation
Note: AI tools assist but cannot replace human judgment for merge decisions.
- PR summarization - Generate description from commits
- Change risk labeling - Flag high-risk files (auth, payments)
- Review suggestions - Identify potential reviewers
Bounded Claims
- AI summaries need human verification
- Risk labels are suggestions, not guarantees
- Merge decisions always require human approval
---
Related Skills
- Software Code Review - Code review standards and techniques
- Quality Debugging - Git bisect, debugging workflows
- DevOps Platform Engineering - CI/CD pipelines, automation
- Software Testing & Automation - Test-driven development, coverage gates
- Documentation Standards - Changelog formats, documentation workflows
- Git Commit Message - Commit message conventions, security commits
Usage Notes
For Claude Code:
- Recommend GitHub Flow for most modern teams (simple, effective)
- Suggest stacked diffs for features > 500 lines
- Always validate commit messages against conventional commit format
- Check PR size - warn if > 400 lines, block if > 1000 lines
- Reference assets/ for copy-paste ready configurations
- Use references/ for deep-dive implementation guidance
Progressive Disclosure:
1. Start with Quick Reference for fast lookups 2. Use Decision Tree for choosing strategies 3. Navigate to specific resources for detailed implementation 4. Reference templates for production-ready configurations 5. Check validation checklists before PR/merge/release
---
Quick Command Reference
Common Operations:
# Rebase feature branch
git fetch origin && git rebase origin/main
# Interactive rebase last 3 commits
git rebase -i HEAD~3
# Squash all commits in branch
git rebase -i $(git merge-base HEAD main)
# Force push safely
git push --force-with-lease origin feature-branch
# Undo last commit (keep changes)
git reset --soft HEAD~1
# Cherry-pick specific commit
git cherry-pick abc123
# Stash changes
git stash push -m "WIP: implementing feature X"
git stash popConflict Resolution:
# Pull latest with rebase
git pull --rebase origin main
# Use visual merge tool
git mergetool
# Accept their changes
git checkout --theirs <file>
# Accept your changes
git checkout --ours <file>Trend Awareness Protocol
IMPORTANT: When users ask recommendation questions about Git workflows, branching strategies, or collaboration tools, verify current trends via web search (and/or the links in data/sources.json) before answering.
Trigger Conditions
- "What's the best Git workflow for [team size/use case]?"
- "What should I use for [branching/PR management]?"
- "What's the latest in Git collaboration?"
- "Current best practices for [branching/code review]?"
- "Is [GitFlow/Trunk-Based] still relevant in 2026?"
- "[GitHub Flow] vs [Trunk-Based] vs [GitFlow]?"
- "Best PR stacking tool?"
Required Searches
1. Search: "Git workflow best practices 2026" 2. Search: "[specific strategy] vs alternatives 2026" 3. Search: "Git collaboration trends January 2026" 4. Search: "[branching/PR tools] comparison 2026"
What to Report
After searching, provide:
- Current landscape: What Git workflows/tools are popular NOW
- Emerging trends: New collaboration patterns, tools, or practices gaining traction
- Deprecated/declining: Strategies/tools losing relevance or support
- Recommendation: Based on fresh data, not just static knowledge
Example Topics (verify with fresh search)
- Branching strategies (Trunk-Based, GitHub Flow, GitFlow)
- PR stacking tools (Graphite, git-stack, Stacked PRs)
- Merge queue implementations (GitHub, GitLab)
- Code review platforms and automation
- Conventional commits and changelog tools
- Git hosting platform features (GitHub, GitLab, Bitbucket)
- AI-assisted Git workflows
Fact-Checking
- Use web search/web fetch to verify current external facts, versions, pricing, deadlines, regulations, or platform behavior before final answers.
- Prefer primary sources; report source links and dates for volatile information.
- If web access is unavailable, state the limitation and mark guidance as unverified.
# GitHub Actions - PR Quality Checks
# Place in: .github/workflows/pr-checks.yml
name: PR Quality Checks
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches:
- main
- develop
# Cancel previous runs if new commit pushed
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# Job 1: Code Quality Checks
quality:
name: Code Quality
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for better analysis
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Check code formatting
run: npm run format:check
- name: Type check
run: npm run type-check
if: hashFiles('tsconfig.json') != ''
# Job 2: Tests and Coverage
test:
name: Tests & Coverage
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm test -- --coverage
- name: Check coverage threshold
run: |
COVERAGE=$(npm test -- --coverage --silent | grep -oP '\d+(?=%)' | head -1)
THRESHOLD=80
echo "Coverage: $COVERAGE%"
if [ "$COVERAGE" -lt "$THRESHOLD" ]; then
echo "::error::Coverage $COVERAGE% is below $THRESHOLD% threshold"
exit 1
fi
- name: Upload coverage reports
uses: codecov/codecov-action@v3
with:
files: ./coverage/coverage-final.json
flags: unittests
fail_ci_if_error: true
# Job 3: Build Check
build:
name: Build Verification
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Check bundle size
uses: andresz1/size-limit-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
skip_step: install
# Job 4: Security Scan
security:
name: Security Scan
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Snyk security scan
uses: snyk/actions/node@master
continue-on-error: true # Don't block on vulnerabilities, just report
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
- name: Check for secrets
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
head: HEAD
- name: Dependency audit
run: npm audit --audit-level=moderate
# Job 5: PR Size Check
pr-size:
name: PR Size Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check PR size
run: |
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
# Count lines changed
LINES_CHANGED=$(git diff --shortstat $BASE_SHA $HEAD_SHA | grep -oP '\d+(?= insertion)|\d+(?= deletion)' | awk '{s+=$1} END {print s}')
echo "Lines changed: $LINES_CHANGED"
# Warning at 400, error at 1000
if [ "$LINES_CHANGED" -gt 1000 ]; then
echo "::error::PR is too large ($LINES_CHANGED lines). Consider splitting into smaller PRs."
exit 1
elif [ "$LINES_CHANGED" -gt 400 ]; then
echo "::warning::PR is large ($LINES_CHANGED lines). Consider splitting for faster reviews."
fi
- name: Label PR by size
uses: CodeSeoul/pr-size-labeler@v1
with:
max_xs: 10
max_s: 100
max_m: 400
max_l: 1000
max_xl: 2000
# Job 6: Conventional Commits Check
commitlint:
name: Commit Message Validation
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install commitlint
run: |
npm install --save-dev @commitlint/cli @commitlint/config-conventional
- name: Validate PR title
uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
docs
style
refactor
perf
test
build
ci
chore
revert
scopes: |
auth
api
ui
db
requireScope: false
- name: Validate all commits
run: |
npx commitlint --from ${{ github.event.pull_request.base.sha }} --to HEAD --verbose
# Job 7: Accessibility Check (for frontend projects)
a11y:
name: Accessibility Check
runs-on: ubuntu-latest
if: hashFiles('**/package.json') != '' && github.event.pull_request.draft == false
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Run accessibility tests
run: npm run test:a11y
continue-on-error: true # Report but don't block
# Job 8: Performance Benchmarks (optional)
performance:
name: Performance Benchmarks
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run benchmarks
run: npm run benchmark
continue-on-error: true
- name: Comment PR with results
uses: actions/github-script@v7
if: always()
with:
script: |
const fs = require('fs');
const benchmarks = fs.readFileSync('benchmark-results.txt', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## Performance Benchmarks\n\`\`\`\n${benchmarks}\n\`\`\``
});
# Job 9: Required Checks Summary
all-checks:
name: All Checks Passed
runs-on: ubuntu-latest
needs: [quality, test, build, security, pr-size, commitlint]
if: always()
steps:
- name: Check all jobs
run: |
if [[ "${{ needs.quality.result }}" != "success" ]] || \
[[ "${{ needs.test.result }}" != "success" ]] || \
[[ "${{ needs.build.result }}" != "success" ]] || \
[[ "${{ needs.security.result }}" != "success" ]] || \
[[ "${{ needs.pr-size.result }}" != "success" ]] || \
[[ "${{ needs.commitlint.result }}" != "success" ]]; then
echo "::error::One or more required checks failed"
exit 1
fi
echo "All required checks passed!"
# Optional: Auto-assign reviewers
# Uncomment if you want automatic reviewer assignment
#
# reviewer-assignment:
# name: Assign Reviewers
# runs-on: ubuntu-latest
# steps:
# - name: Auto-assign reviewers
# uses: kentaro-m/auto-assign-action@v1.2.1
# with:
# configuration-path: '.github/auto-assign.yml'
# Optional: Auto-label by files changed
# Uncomment if you want automatic labels based on changed files
#
# labeler:
# name: Auto-label PR
# runs-on: ubuntu-latest
# steps:
# - uses: actions/labeler@v5
# with:
# configuration-path: '.github/labeler.yml'
# repo-token: ${{ secrets.GITHUB_TOKEN }}
# GitLab CI - Merge Request Quality Checks
# Place in: .gitlab-ci.yml
# Pipeline stages
stages:
- validate
- test
- quality
- security
- report
# Global variables
variables:
NODE_VERSION: "20"
COVERAGE_THRESHOLD: "80"
# Cache configuration
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .npm/
# Workflow rules - only run on MRs
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
# Job templates
.node_job_template: &node_job
image: node:${NODE_VERSION}
before_script:
- npm ci --cache .npm --prefer-offline
# Stage 1: Validation
commitlint:
stage: validate
image: node:${NODE_VERSION}
script:
- npm install @commitlint/cli @commitlint/config-conventional
- echo "module.exports = {extends: ['@commitlint/config-conventional']};" > commitlint.config.js
- npx commitlint --from $CI_MERGE_REQUEST_DIFF_BASE_SHA --to HEAD --verbose
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
mr-size-check:
stage: validate
image: alpine:latest
before_script:
- apk add --no-cache git
script:
- |
git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
LINES_CHANGED=$(git diff --shortstat origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME...HEAD | grep -oP '\d+(?= insertion)|\d+(?= deletion)' | awk '{s+=$1} END {print s}')
echo "Lines changed: $LINES_CHANGED"
if [ "$LINES_CHANGED" -gt 1000 ]; then
echo "ERROR: MR is too large ($LINES_CHANGED lines). Split into smaller MRs."
exit 1
elif [ "$LINES_CHANGED" -gt 400 ]; then
echo "WARNING: MR is large ($LINES_CHANGED lines). Consider splitting for faster reviews."
fi
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# Stage 2: Tests
unit-tests:
<<: *node_job
stage: test
script:
- npm test -- --coverage
- COVERAGE=$(npm test -- --coverage --silent | grep -oP '\d+(?=%)' | head -1 || echo "0")
- echo "Coverage: $COVERAGE%"
- |
if [ "$COVERAGE" -lt "$COVERAGE_THRESHOLD" ]; then
echo "ERROR: Coverage $COVERAGE% is below $COVERAGE_THRESHOLD% threshold"
exit 1
fi
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
paths:
- coverage/
expire_in: 1 week
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
integration-tests:
<<: *node_job
stage: test
services:
- postgres:15
- redis:7
variables:
POSTGRES_DB: test_db
POSTGRES_USER: test_user
POSTGRES_PASSWORD: test_password
DATABASE_URL: postgresql://test_user:test_password@postgres:5432/test_db
REDIS_URL: redis://redis:6379
script:
- npm run test:integration
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
- "src/**/*.ts"
- "tests/integration/**/*.ts"
e2e-tests:
<<: *node_job
stage: test
script:
- npm run test:e2e
artifacts:
when: on_failure
paths:
- tests/e2e/screenshots/
- tests/e2e/videos/
expire_in: 1 week
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
- "src/**/*.ts"
- "tests/e2e/**/*.ts"
# Stage 3: Code Quality
lint:
<<: *node_job
stage: quality
script:
- npm run lint
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
format-check:
<<: *node_job
stage: quality
script:
- npm run format:check
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
type-check:
<<: *node_job
stage: quality
script:
- npm run type-check
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
exists:
- tsconfig.json
build:
<<: *node_job
stage: quality
script:
- npm run build
artifacts:
paths:
- dist/
- build/
expire_in: 1 week
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
code-quality:
stage: quality
image: docker:stable
services:
- docker:stable-dind
variables:
DOCKER_DRIVER: overlay2
CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:latest"
allow_failure: true
script:
- |
docker run \
--env SOURCE_CODE="$PWD" \
--volume "$PWD":/code \
--volume /var/run/docker.sock:/var/run/docker.sock \
"$CODE_QUALITY_IMAGE" /code
artifacts:
reports:
codequality: gl-code-quality-report.json
expire_in: 1 week
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# Stage 4: Security
dependency-scan:
<<: *node_job
stage: security
script:
- npm audit --audit-level=moderate
allow_failure: true
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
secret-detection:
stage: security
image: alpine:latest
before_script:
- apk add --no-cache git
script:
- |
git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
git diff origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME...HEAD | grep -iE '(password|secret|key|token|api_key)' && exit 1 || exit 0
allow_failure: false
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
sast:
stage: security
image: returntocorp/semgrep
script:
- semgrep --config=auto --json --output=gl-sast-report.json .
artifacts:
reports:
sast: gl-sast-report.json
expire_in: 1 week
allow_failure: true
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# Stage 5: Report
merge-request-report:
stage: report
image: alpine:latest
needs:
- unit-tests
- lint
- build
before_script:
- apk add --no-cache curl jq
script:
- |
# Post comment to MR with summary
COMMENT=$(cat <<EOF
## CI/CD Pipeline Summary
All checks passed.
- Unit tests: Passed
- Linting: Passed
- Build: Passed
- Code coverage: $(cat coverage/coverage-summary.json | jq '.total.lines.pct')%
Ready for review!
EOF
)
curl --request POST \
--header "PRIVATE-TOKEN: $CI_JOB_TOKEN" \
--data "body=$COMMENT" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: on_success
# Optional: Performance benchmarks
performance:
<<: *node_job
stage: quality
script:
- npm run benchmark || true
- cat benchmark-results.txt
artifacts:
reports:
metrics: benchmark-results.txt
expire_in: 1 week
allow_failure: true
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
# Optional: Accessibility tests
accessibility:
<<: *node_job
stage: quality
script:
- npm run build
- npm run test:a11y || true
allow_failure: true
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
# Optional: Bundle size check
bundle-size:
<<: *node_job
stage: quality
script:
- npm run build
- npm run analyze:bundle || true
artifacts:
paths:
- bundle-analysis.html
expire_in: 1 week
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
# Merge request approval rules (configure in GitLab UI)
# Settings > Merge Requests > Merge request approvals
# - Require 2 approvals
# - Prevent approval by author
# - Prevent committers from approving
# - Require approval from code owners
# - Remove all approvals when new commits are pushed
# Branch protection rules (configure in GitLab UI)
# Settings > Repository > Protected branches
# - Protected: main, develop
# - Allowed to merge: Maintainers
# - Allowed to push: No one
# - Require approval before merging
# - Pipelines must succeed
Pull Request Description Template
Copy this template for high-quality pull request descriptions.
---
Summary
[1-2 sentence description of what changed and why]
Motivation
[Business or technical reason for this change]
Why is this change needed? What problem does it solve?
Changes
[Detailed list of what changed]
- Added X feature
- Refactored Y module
- Fixed Z bug
Implementation Details
[Technical approach and key decisions]
- Chose approach A over B because [reason]
- Used library X for [specific need]
- Considered edge cases: [list]
Testing
[How you verified this works]
- [ ] Unit tests added (coverage: X%)
- [ ] Integration tests pass
- [ ] Manual testing completed
- [ ] Tested on Chrome, Firefox, Safari
- [ ] Tested edge cases: [list]
Screenshots/Videos
[For UI changes - delete if not applicable]
Before: [image or video]
After: [image or video]
Performance Impact
[If applicable - delete if not relevant]
- Benchmark results: [data]
- Load time: before X ms -> after Y ms
- Database queries: optimized from N to M
Security Considerations
[If applicable - delete if not relevant]
- Input validation added for [fields]
- Authorization check for [resource]
- No secrets in code (verified)
- Tested for OWASP Top 10 vulnerabilities
Deployment Notes
[Important information for deployment]
- Database migration required:
npm run migrate - Feature flag:
ENABLE_FEATURE_X(default: false) - Environment variable:
API_TIMEOUT=5000 - Backward compatible: Yes/No
Rollback Plan
[If needed]
- Disable feature flag
ENABLE_FEATURE_X - Or: Revert commit abc123
- Or: Run rollback migration:
npm run migrate:down
Related Issues
Fixes #234 Relates to #456 Part of epic #789
Questions for Reviewers
[Specific areas where you want feedback]
- Is the error handling approach appropriate?
- Should we add more test coverage for X?
- Any performance concerns with this implementation?
---
Examples
Example 1: Feature Addition
Summary
Add user profile editing with avatar upload and real-time validation
Motivation
User research shows 60% of users want to customize their profiles. Adding profile editing reduces support tickets by allowing self-service updates.
Target metric: Reduce profile-related support tickets by 40%
Changes
- Added profile edit form with real-time validation
- Implemented avatar upload with image cropping
- Added profile update API endpoint with rate limiting
- Updated user model with new fields (bio, location, website)
Implementation Details
Avatar Upload:
- Used
multerfor file upload handling - Implemented client-side image cropping with
react-easy-crop - Images stored in S3 with CDN caching
- Max file size: 5MB, formats: JPG, PNG
- Auto-generate thumbnails (100x100, 400x400)
Validation:
- Real-time validation using Zod schema
- Debounced input (500ms) to reduce API calls
- Username uniqueness check with 2s cache
- Email format validation with disposable email check
Security:
- Rate limiting: 10 profile updates per hour per user
- File upload validation (magic number check, not just extension)
- XSS prevention on bio field
- CSRF token required for updates
Testing
- [x] Unit tests: Zod schemas, upload utils (coverage: 95%)
- [x] Integration tests: profile update API, file upload flow
- [x] E2E tests: full edit flow with Playwright
- [x] Manual testing: Tested on Chrome, Firefox, Safari, Mobile
- [x] Edge cases tested:
- Large avatar upload (5MB+) -> Shows error
- Invalid image format -> Shows error
- Duplicate username -> Shows error
- XSS attempt in bio -> Sanitized
Screenshots
Profile Edit Form:

Avatar Cropping:

Performance Impact
- Avatar upload: average 2.5s for 2MB image
- Profile save: average 120ms
- Added Redis caching for username uniqueness checks
- Database query optimized with index on users.username
Security Considerations
- File upload validates magic numbers (not just extension)
- Bio field sanitized with DOMPurify to prevent XSS
- Rate limiting prevents abuse (10 updates/hour)
- CSRF token required for all update requests
- No PII logged in application logs
Deployment Notes
Database Migration Required:
npm run migrate:profile-fieldsAdds columns: bio (text), location (varchar), website (varchar), avatar_url (varchar)
Environment Variables:
AWS_S3_BUCKET=user-avatars
AWS_S3_REGION=us-east-1
CDN_URL=https://cdn.example.comFeature Flag:
ENABLE_PROFILE_EDIT(default: false)- Enable after successful staging verification
Backward Compatible: Yes (all new fields nullable)
Rollback Plan
1. Disable feature flag: ENABLE_PROFILE_EDIT=false 2. Or rollback migration: npm run migrate:down profile-fields 3. Or revert commit: git revert abc123
Related Issues
Fixes #234 (User profile editing) Fixes #456 (Avatar upload) Relates to #567 (Account settings redesign) Part of epic #789 (User experience improvements)
Questions for Reviewers
1. Should we add more image formats (WebP, AVIF)? 2. Is 10 updates/hour rate limit too strict? 3. Any concerns with S3 storage costs for avatars? 4. Should we add A/B testing for the new profile page?
---
Example 2: Bug Fix
Summary
Fix race condition in user registration causing duplicate accounts
Motivation
Production issue: 0.5% of registrations create duplicate user accounts when submitted multiple times rapidly (double-click, slow network retry).
Impact: 50 duplicate accounts per day, causing login failures and support tickets.
Changes
- Added database unique constraint on users.email
- Implemented transaction handling for user creation
- Added idempotency key to registration API
- Improved error handling for duplicate email errors
Implementation Details
Root Cause: Registration endpoint didn't handle concurrent requests. When user double-clicked "Sign Up" or network retried, two requests reached the server simultaneously before the first user was committed to database.
Fix: 1. Database level: Added unique constraint on users.email (prevents duplicates) 2. Application level: Wrapped user creation in transaction 3. API level: Added idempotency key header (dedupe retries)
Idempotency:
// Client sends: Idempotency-Key: uuid
// Server caches registration attempts for 24h
// Duplicate requests return original responseTesting
- [x] Unit tests: transaction rollback, constraint violations
- [x] Integration tests: concurrent registration requests
- [x] Load tests: 100 concurrent registrations with same email
- [x] Manual tests: Double-click submit, network retry scenarios
Test Results:
- Before: 5/100 concurrent requests created duplicates
- After: 0/100 duplicates, proper error returned
Performance Impact
- Negligible (< 5ms added latency for unique constraint check)
- Idempotency cache uses Redis (1MB memory for 1000 requests)
Security Considerations
- Unique constraint prevents email enumeration attacks (same error for existing)
- Idempotency keys expire after 24h
- No rate limiting changes (existing 10 requests/hour remains)
Deployment Notes
Database Migration Required:
npm run migrate:user-email-uniqueMigration Steps: 1. Identify existing duplicates: npm run fix:duplicate-users 2. Manually resolve duplicates (merge or delete) 3. Run migration to add unique constraint 4. Deploy new code
Downtime: None (migration runs online) Backward Compatible: Yes
Monitoring:
- Alert on duplicate email errors (expected during migration)
- Track idempotency cache hit rate
Rollback Plan
1. Revert code deploy (keeps constraint, no duplicates) 2. Or drop constraint: ALTER TABLE users DROP CONSTRAINT users_email_unique; (Note: This allows duplicates again, not recommended)
Related Issues
Fixes #789 (Duplicate user accounts) Relates to #790 (Registration error handling)
Questions for Reviewers
1. Should we add the same constraint to users.username? 2. Is 24h too long for idempotency key expiration? 3. Do we need to backfill idempotency keys for existing users?
---
When to Use Each Section
Always Include
- Summary
- Motivation
- Changes
- Testing
- Related Issues
Include When Applicable
- Implementation Details (for complex changes)
- Screenshots (for UI changes)
- Performance Impact (if performance changed)
- Security Considerations (if security-related)
- Deployment Notes (if requires deployment steps)
- Rollback Plan (for risky changes)
- Questions for Reviewers (when you need specific feedback)
Can Omit
- Screenshots (for backend-only changes)
- Performance Impact (for documentation changes)
- Security Considerations (for non-security changes)
- Deployment Notes (for fully backward-compatible changes)
- Rollback Plan (for low-risk changes like docs, tests)
---
Copy-Paste Template
## Summary
## Motivation
## Changes
-
## Implementation Details
## Testing
- [ ] Unit tests added
- [ ] Integration tests pass
- [ ] Manual testing completed
## Screenshots
[Delete if not applicable]
## Performance Impact
[Delete if not applicable]
## Security Considerations
[Delete if not applicable]
## Deployment Notes
## Rollback Plan
## Related Issues
Fixes #
## Questions for ReviewersRelease Workflow Template
Complete workflow for managing software releases with semantic versioning and automation.
---
Overview
This template provides a production-ready release workflow combining:
- Semantic Versioning (SemVer) - MAJOR.MINOR.PATCH version scheme
- Conventional Commits - Automated version bumping from commit messages
- Automated Releases - CI/CD-driven release process
- Release Notes - Auto-generated changelogs
---
Release Types & Version Bumping
Semantic Versioning Format
MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD]
Examples:
- 1.0.0 - Initial stable release
- 1.2.3 - Patch release
- 2.0.0 - Major release (breaking changes)
- 2.1.0-beta.1 - Pre-release version
- 2.1.0+20240115 - Build metadataVersion Bump Rules
| Change Type | Commit Prefix | Version Impact | Example |
|---|---|---|---|
| Breaking change | feat!: or BREAKING CHANGE: | MAJOR (1.0.0 -> 2.0.0) | API redesign |
| New feature | feat: | MINOR (1.0.0 -> 1.1.0) | Add user export |
| Bug fix | fix: | PATCH (1.0.0 -> 1.0.1) | Fix login issue |
| Performance | perf: | PATCH (1.0.0 -> 1.0.1) | Optimize queries |
| Other | docs:, style:, refactor:, test:, chore: | No version bump | Update README |
---
Manual Release Workflow (GitFlow)
Use this workflow for scheduled releases with manual control.
1. Prepare Release Branch
# Create release branch from develop
git checkout develop
git pull origin develop
git checkout -b release/v2.1.0
# Bump version in package files
# package.json, pyproject.toml, Cargo.toml, etc.
npm version 2.1.0 --no-git-tag-version
# OR
# Edit version manually in package.json, setup.py, etc.
# Commit version bump
git commit -am "chore: bump version to 2.1.0"2. Generate Changelog
# Option 1: Use standard-version (recommended)
npm install -g standard-version
npx standard-version --dry-run # Preview changes
npx standard-version # Generate CHANGELOG.md
# Option 2: Manual changelog
# Edit CHANGELOG.md with release notesCHANGELOG.md Format:
# Changelog
## [2.1.0] - 2024-11-20
### Added
- User profile export feature (#234)
- OAuth2 social login support (#456)
### Fixed
- Race condition in user registration (#789)
- Memory leak in WebSocket handler (#790)
### Changed
- Improved error messages for API validation (#567)
### Breaking Changes
- Removed deprecated /api/v1/users endpoint (use /api/v2/users)3. Merge to Main and Tag
# Merge release to main
git checkout main
git merge --no-ff release/v2.1.0
git tag -a v2.1.0 -m "Release version 2.1.0"
# Push to remote
git push origin main --tags
# Merge back to develop
git checkout develop
git merge --no-ff release/v2.1.0
git push origin develop
# Delete release branch
git branch -d release/v2.1.0
git push origin --delete release/v2.1.04. Publish Release
# Publish to npm/PyPI/etc.
npm publish
# Or create GitHub/GitLab release
gh release create v2.1.0 \
--title "Release v2.1.0" \
--notes-file CHANGELOG.md---
Automated Release Workflow (Recommended)
Use semantic-release for fully automated version management.
Setup semantic-release
1. Install Dependencies:
npm install --save-dev semantic-release \
@semantic-release/changelog \
@semantic-release/git \
@semantic-release/github2. Configure `.releaserc.json`:
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
["@semantic-release/changelog", {
"changelogFile": "CHANGELOG.md"
}],
"@semantic-release/npm",
["@semantic-release/git", {
"assets": ["CHANGELOG.md", "package.json"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}],
"@semantic-release/github"
]
}3. GitHub Actions Workflow:
Create .github/workflows/release.yml:
name: Release
on:
push:
branches:
- main
permissions:
contents: write
issues: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx semantic-release4. GitLab CI Configuration:
Create .gitlab-ci.yml:
release:
stage: release
image: node:lts
only:
- main
script:
- npm ci
- npm test
- npx semantic-release
variables:
GL_TOKEN: $CI_JOB_TOKEN
NPM_TOKEN: $NPM_TOKENHow semantic-release Works
1. Analyze commits since last release
↓
2. Determine next version (MAJOR, MINOR, PATCH)
↓
3. Generate release notes from commits
↓
4. Update CHANGELOG.md
↓
5. Bump version in package.json
↓
6. Create Git tag
↓
7. Publish to npm/GitHub/etc.
↓
8. Post GitHub release with notesExample Commit History -> Version:
feat: add user export -> 1.0.0 -> 1.1.0
fix: resolve memory leak -> 1.1.0 -> 1.1.1
feat!: redesign API -> 1.1.1 -> 2.0.0---
Pre-release Workflow
Create Alpha/Beta Releases
Manual (GitFlow):
# Create pre-release branch
git checkout -b release/v2.0.0-beta.1 develop
# Bump version to pre-release
npm version 2.0.0-beta.1 --no-git-tag-version
git commit -am "chore: release v2.0.0-beta.1"
# Merge to main and tag
git checkout main
git merge --no-ff release/v2.0.0-beta.1
git tag v2.0.0-beta.1
git push origin main --tags
# Publish pre-release
npm publish --tag betaAutomated (semantic-release):
Configure .releaserc.json for pre-releases:
{
"branches": [
"main",
{
"name": "beta",
"prerelease": true
},
{
"name": "alpha",
"prerelease": true
}
]
}Push to beta branch:
git checkout -b beta
git push origin beta
# Triggers release: 2.0.0-beta.1---
Hotfix Workflow
GitFlow Hotfix
# Create hotfix branch from main
git checkout main
git checkout -b hotfix/v2.0.1
# Fix the issue
git commit -m "fix: resolve critical security vulnerability"
# Bump version
npm version patch --no-git-tag-version
git commit -am "chore: bump version to 2.0.1"
# Merge to main
git checkout main
git merge --no-ff hotfix/v2.0.1
git tag v2.0.1
git push origin main --tags
# Merge to develop
git checkout develop
git merge --no-ff hotfix/v2.0.1
git push origin develop
# Delete hotfix branch
git branch -d hotfix/v2.0.1Trunk-Based Hotfix
# Fix directly on main (or short-lived branch)
git checkout main
git checkout -b hotfix/security-patch
# Fix the issue
git commit -m "fix: resolve critical security vulnerability"
# Merge via PR with expedited review
# Automated release triggers from main---
Release Checklist
Pre-Release Checklist
- [ ] All tests pass in CI/CD
- [ ] Code coverage meets threshold (e.g., 80%)
- [ ] All PRs merged and approved
- [ ] Documentation updated
- [ ] CHANGELOG.md reviewed (if manual)
- [ ] Version number follows SemVer
- [ ] Breaking changes documented
- [ ] Migration guide written (if breaking changes)
- [ ] Staging environment tested
- [ ] Performance benchmarks pass
- [ ] Security scan completed (no critical vulnerabilities)
Release Execution Checklist
- [ ] Create release branch (GitFlow) or merge to main (Trunk-Based)
- [ ] Bump version number
- [ ] Generate/review changelog
- [ ] Create Git tag
- [ ] Push tag to remote
- [ ] Publish package (npm, PyPI, Docker, etc.)
- [ ] Create GitHub/GitLab release
- [ ] Update documentation site
- [ ] Notify stakeholders (Slack, email, etc.)
Post-Release Checklist
- [ ] Monitor error tracking (Sentry, Rollbar, etc.)
- [ ] Check metrics dashboard
- [ ] Monitor user feedback
- [ ] Verify deployment to production
- [ ] Update project board/Jira
- [ ] Tweet/blog announcement (if public release)
- [ ] Merge release branch back to develop (GitFlow)
---
Release Types
Patch Release (1.0.0 -> 1.0.1)
When: Bug fixes, performance improvements, documentation updates
Scope: Backward-compatible changes only
Timeline: As needed (hotfixes can be immediate)
Example Commits:
fix: resolve null pointer exception in user service
perf: optimize database queries for user search
docs: update API authentication examplesMinor Release (1.0.0 -> 1.1.0)
When: New features, backward-compatible API additions
Scope: Additive changes, no breaking changes
Timeline: Weekly, bi-weekly, or monthly
Example Commits:
feat: add user profile export to CSV
feat: implement OAuth2 social login
feat: add real-time notificationsMajor Release (1.0.0 -> 2.0.0)
When: Breaking changes, API redesigns, major refactors
Scope: Can include breaking changes
Timeline: Quarterly, bi-annually, or annually
Example Commits:
feat!: redesign REST API with new resource structure
BREAKING CHANGE: Remove deprecated /api/v1/* endpoints
feat!: migrate to new authentication systemMigration Guide Template:
# Migration Guide: v1.x -> v2.0
## Breaking Changes
### 1. API Endpoint Changes
**Before (v1.x)**:
GET /api/v1/users
**After (v2.0)**:
GET /api/v2/users
### 2. Authentication Changes
**Before (v1.x)**:
Authorization: Token <token>
**After (v2.0)**:
Authorization: Bearer <token>
## Migration Steps
1. Update API base URL
2. Replace authentication headers
3. Update request/response formats
4. Run migration script: `npm run migrate:v2`
## Support Timeline
- v1.x: Supported until 2025-06-01
- v2.0: Current stable version---
Rollback Plan
Rollback Strategies
1. Revert Git Tag (Recommended):
# Revert to previous version
git revert v2.1.0..HEAD
git tag v2.1.1
git push origin main --tags
# Publish rollback version
npm publish2. Republish Previous Version:
# Republish previous stable version
git checkout v2.0.0
npm publish
# Update latest tag
npm dist-tag add package-name@2.0.0 latest3. Hotfix Release:
# Create hotfix on top of failed release
git checkout -b hotfix/v2.1.1 v2.1.0
# Fix critical issue
git commit -m "fix: resolve critical deployment issue"
npm version patch
git push origin hotfix/v2.1.1Rollback Checklist
- [ ] Identify root cause of failure
- [ ] Decide rollback strategy
- [ ] Notify stakeholders
- [ ] Execute rollback
- [ ] Verify rollback in staging
- [ ] Deploy rollback to production
- [ ] Monitor metrics post-rollback
- [ ] Document incident for postmortem
---
Version Compatibility Matrix
Document version compatibility for multi-component systems.
| API Version | Client Version | Database Schema | Supported Until |
|-------------|----------------|-----------------|-----------------|
| 2.1.x | >= 2.0.0 | v5 | 2025-12-31 |
| 2.0.x | >= 1.5.0 | v4 | 2025-06-01 |
| 1.x.x | >= 1.0.0 | v3 | 2024-12-31 |---
Tools Comparison
| Tool | Use Case | Pros | Cons |
|---|---|---|---|
| semantic-release | Fully automated | Zero-config, CI/CD native | Less control over process |
| standard-version | Manual trigger | More control, dry-run mode | Manual execution required |
| release-it | Interactive | User-friendly prompts | Not ideal for full automation |
| Manual | Full control | Complete flexibility | Error-prone, time-consuming |
---
Advanced Configurations
Monorepo Releases
Use Lerna or semantic-release-monorepo:
{
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
["@semantic-release/npm", {
"pkgRoot": "packages/core"
}],
["@semantic-release/npm", {
"pkgRoot": "packages/utils"
}]
]
}Custom Release Notes
Customize release note template:
{
"plugins": [
["@semantic-release/release-notes-generator", {
"preset": "angular",
"writerOpts": {
"headerPartial": "## {{version}} ({{date}})\n\n"
}
}]
]
}---
References
- Semantic Versioning: https://semver.org/
- Conventional Commits: https://www.conventionalcommits.org/
- semantic-release: https://semantic-release.gitbook.io/
- standard-version: https://github.com/conventional-changelog/standard-version
- GitHub Releases: https://docs.github.com/en/repositories/releasing-projects-on-github
- GitLab Releases: https://docs.gitlab.com/ee/user/project/releases/
Git Workflow Guide (Trunk-Based and GitFlow)
Use this template to standardize branching, PRs, releases, and hotfixes.
---
Core
1) Choose a Model (Decision Matrix)
| Team/Product Constraint | Recommended Model |
|---|---|
| Continuous deploy, strong CI, feature flags available | Trunk-based |
| Many devs, many daily merges, strong CI, need fast feedback | Trunk-based (+ merge queue) |
| Scheduled releases, multiple supported versions | GitFlow |
| Low CI maturity, manual releases, strict release gates | GitFlow (temporary) |
---
2) Trunk-Based Workflow (Default for Modern Teams)
Branches
main(trunk): always releasable- Short-lived branches:
feat/*,fix/*,chore/*(lifetime hours to a few days)
Flow
1. Branch from main 2. Small commits (Conventional Commits) 3. Open PR early (draft PR encouraged) 4. CI gates + review 5. Merge (squash or merge-commit; pick one) 6. Deploy from main (continuous) or tag releases
Release and Hotfix
- Prefer forward fixes on
main. - For critical incidents: short-lived
hotfix/*frommain, merge back, tag if needed.
Required Guardrails
- Branch protection on
main(PRs only, required checks, required reviews) - Merge queue for high-traffic repos (keeps
maingreen under concurrency) - Feature flags for incomplete work (avoid long-lived branches)
---
3) GitFlow Workflow (When Scheduled Releases Dominate)
Branches
main: production releases (tagged)develop: integration branch (must stay green)release/*: stabilization for a scheduled releasehotfix/*: emergency fixes frommain
Flow
1. Feature branches off develop 2. Merge to develop behind CI gates 3. Cut release/x.y branch for stabilization 4. Fixes go into release/x.y and are merged back to develop 5. Merge release/x.y to main, tag release, deploy
Risks to Manage
- Merge debt between
developandmain - Long-lived release branches drifting from trunk
- Slower feedback cycles (invest in CI to transition to trunk-based over time)
---
4) Merge Strategy (Pick and Enforce)
| Strategy | Pros | Cons | Recommended Use |
|---|---|---|---|
| Squash merge | Clean history, easy reverts | Loses commit granularity | Most product repos |
| Merge commit | Preserves branch context | Noisier history | Repos needing branch topology |
| Rebase merge | Linear history | Risky for shared branches | Small teams with strong git discipline |
Rules:
- Never rebase shared branches (
main,develop,release/*) after publishing. - Use
--force-with-leaseonly on personal feature branches.
---
5) PR Checklist (Minimum)
- [ ] Clear description: what/why/how, testing evidence
- [ ] Small and reviewable (<400 LOC preferred; split if larger)
- [ ] CI: tests, lint, security scan where applicable
- [ ] No secrets, credentials, or sensitive data
- [ ] Rollout and rollback notes for risky changes
Template: pull-requests/pr-template.md
---
Optional: AI/Automation
- PR summaries and changelog drafts (human-verified)
- Change risk labeling based on file paths (human-approved)
- Suggested reviewers based on CODEOWNERS/history (human-confirmed)
Bounded Claims
- Automation cannot replace ownership, review, or release approval.
{
"metadata": {
"title": "Git Collaboration Workflow - Sources",
"description": "High-signal sources for Git workflows, PR discipline, branching models, repository hardening, and release practices",
"last_updated": "2026-01-17"
},
"git_core": [
{
"name": "Git Documentation",
"url": "https://git-scm.com/doc",
"description": "Official Git documentation hub",
"add_as_web_search": false
},
{
"name": "Pro Git (book)",
"url": "https://git-scm.com/book/en/v2",
"description": "Comprehensive Git book (branches, rebasing, workflows, internals)",
"add_as_web_search": false
}
],
"workflows": [
{
"name": "Trunk-Based Development",
"url": "https://trunkbaseddevelopment.com/",
"description": "Trunk-based development patterns and trade-offs",
"add_as_web_search": true
},
{
"name": "Gitflow Workflow (Atlassian)",
"url": "https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow",
"description": "GitFlow concepts and comparisons",
"add_as_web_search": true
}
],
"platform_docs": [
{
"name": "GitHub Flow",
"url": "https://docs.github.com/en/get-started/quickstart/github-flow",
"description": "Official GitHub Flow guide",
"add_as_web_search": true
},
{
"name": "GitHub - About protected branches",
"url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches",
"description": "Branch protection rules and enforcement options",
"add_as_web_search": true
},
{
"name": "GitHub - About CODEOWNERS",
"url": "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners",
"description": "CODEOWNERS file behavior for review routing and gates",
"add_as_web_search": true
},
{
"name": "GitHub - Managing a merge queue",
"url": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue",
"description": "Merge queue for keeping main green under high concurrency",
"add_as_web_search": true
},
{
"name": "GitHub - Commit signature verification",
"url": "https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification",
"description": "Signed commits/tags and verification behavior",
"add_as_web_search": true
},
{
"name": "GitLab - Merge requests",
"url": "https://docs.gitlab.com/ee/user/project/merge_requests/",
"description": "Merge request workflows, approvals, and pipelines",
"add_as_web_search": true
},
{
"name": "GitLab - Stacked diffs",
"url": "https://docs.gitlab.com/user/project/merge_requests/stacked_diffs/",
"description": "Stacked diffs workflow for large changes",
"add_as_web_search": true
},
{
"name": "GitLab CLI - glab stack",
"url": "https://docs.gitlab.com/cli/stack/",
"description": "GitLab CLI commands for stacked diffs workflow (v1.42.0+)",
"add_as_web_search": true
},
{
"name": "The Stacking Workflow",
"url": "https://www.stacking.dev/",
"description": "Comprehensive comparison of stacking tools (Graphite, ghstack, Sapling, spr)",
"add_as_web_search": true
}
],
"commit_and_release": [
{
"name": "Conventional Commits Specification",
"url": "https://www.conventionalcommits.org/en/v1.0.0/",
"description": "Standard commit format used for automation and changelogs",
"add_as_web_search": true
},
{
"name": "Semantic Versioning 2.0.0",
"url": "https://semver.org/",
"description": "SemVer specification",
"add_as_web_search": false
},
{
"name": "Keep a Changelog",
"url": "https://keepachangelog.com/",
"description": "Changelog format standard",
"add_as_web_search": false
}
],
"security": [
{
"name": "Gitleaks",
"url": "https://gitleaks.io/",
"description": "Secret scanning for git repos (local + CI integration)",
"add_as_web_search": true
},
{
"name": "TruffleHog",
"url": "https://github.com/trufflesecurity/trufflehog",
"description": "Secret scanning and verification for git history",
"add_as_web_search": true
}
],
"optional_ai": [
{
"name": "PR summarization and risk labeling (Optional)",
"url": "https://docs.github.com/en/copilot",
"description": "Optional AI assistance for PR summaries (requires human review; product features vary)",
"add_as_web_search": true,
"optional": true
}
]
}
AI Agent Worktrees — Isolated Workspaces for Coding Agents
Git worktrees enable AI coding agents (Claude Code, Codex, Copilot Workspace, Aider, etc.) to work in isolated directories while sharing the same repository. Each agent gets its own checkout, its own branch, and its own working tree — no git stash juggling, no accidental cross-contamination.
Typical Flow
flowchart TD
A[Human / Orchestrator<br>main checkout] -->|1. Plan features| B{How many agents?}
B -->|Single agent| C1[Create worktree<br>git worktree add .worktrees/feat -b feature/x]
B -->|Multiple agents| C2[Create N worktrees<br>one per agent + feature branch]
C1 --> D1[Verify .gitignore<br>git check-ignore -q .worktrees]
C2 --> D2[Verify .gitignore<br>+ assign file ownership per agent]
D1 --> E1[Install deps + verify tests pass]
D2 --> E2[Install deps in each worktree<br>verify baseline tests]
E1 --> F1[Agent works in .worktrees/feat<br>scoped commits on feature/x]
E2 --> F2[Agents work in parallel<br>each in own worktree + branch]
F1 --> G[Run quality gates<br>tests, lint, type-check]
F2 --> G
G -->|Pass| H[Open PR to integration branch]
G -->|Fail| F1
H --> I[Orchestrator reviews + merges<br>upstream-first if dependencies exist]
I --> J[Cleanup<br>git worktree remove + git branch -d]
J --> K[git worktree prune<br>verify: git worktree list]
style A fill:#e1f0ff,stroke:#4a90d9
style F1 fill:#fff3cd,stroke:#d4a017
style F2 fill:#fff3cd,stroke:#d4a017
style I fill:#d4edda,stroke:#28a745
style J fill:#f8d7da,stroke:#dc3545Parallel Multi-Agent Detail
sequenceDiagram
participant O as Orchestrator (main)
participant W1 as Worktree 1 (.worktrees/auth)
participant W2 as Worktree 2 (.worktrees/payments)
participant W3 as Worktree 3 (.worktrees/search)
O->>W1: git worktree add + launch Agent 1
O->>W2: git worktree add + launch Agent 2
O->>W3: git worktree add + launch Agent 3
par Parallel execution
W1->>W1: Implement auth (feature/auth)
W2->>W2: Implement payments (feature/payments)
W3->>W3: Implement search (feature/search)
end
W1-->>O: Done — commits on feature/auth
W2-->>O: Done — commits on feature/payments
W3-->>O: Done — commits on feature/search
O->>O: Check for file overlap (comm -12)
O->>O: Merge feature/auth → main (upstream first)
O->>O: Rebase feature/payments onto main
O->>O: Merge feature/payments → main
O->>O: Rebase feature/search onto main
O->>O: Merge feature/search → main
O->>W1: git worktree remove
O->>W2: git worktree remove
O->>W3: git worktree remove
O->>O: git worktree pruneContents
- When to Use Worktrees with AI Agents
- Directory Conventions
- Setup: One Worktree per Agent
- Agent-Specific Patterns
- Parallel Agent Execution
- Safety and Conflict Prevention
- Cleanup Lifecycle
- Decision Table
- Anti-Patterns
- Quick Command Reference
---
When to Use Worktrees with AI Agents
| Scenario | Worktree? | Why |
|---|---|---|
| Single agent, single feature | Optional | Branch checkout is fine |
| Single agent, context isolation needed | Yes | Keeps main checkout clean for human work |
| Multiple agents working in parallel | Required | Prevents file conflicts between agents |
| Agent + human working simultaneously | Recommended | Human keeps main checkout; agent works in worktree |
| CI/CD bot building while you develop | Yes | Avoids lock contention on .git/index |
| Codex (cloud sandbox) | No | Codex creates its own sandbox per task |
Rule of thumb: If more than one actor (human or agent) touches the repo simultaneously, use worktrees.
---
Directory Conventions
Three common placement strategies, in priority order:
1. Project-local hidden directory (preferred)
myproject/
.worktrees/
feature-auth/ # worktree for auth feature
fix-payment-bug/ # worktree for payment fix
src/ # main checkout
.gitignore # must contain .worktrees/Advantages: Visible to the project, easy to discover, co-located.
2. Project-local visible directory
myproject/
worktrees/
feature-auth/
.gitignore # must contain worktrees/3. Global directory (outside project)
~/.local/share/worktrees/myproject/
feature-auth/
fix-payment-bug/Advantages: No .gitignore management needed. Useful for repos where you cannot modify .gitignore.
Priority resolution
1. If .worktrees/ or worktrees/ exists in the project, use it. 2. If CLAUDE.md or AGENTS.md specifies a worktree directory, use that. 3. Otherwise, create .worktrees/ and add it to .gitignore.
---
Setup: One Worktree per Agent
Step 1: Verify .gitignore (project-local only)
# Check if worktree directory is ignored
git check-ignore -q .worktrees 2>/dev/null
echo $? # 0 = ignored (good), 1 = not ignored (fix it)If not ignored, add it:
echo ".worktrees/" >> .gitignore
git add .gitignore && git commit -m "chore: ignore worktree directory"Step 2: Create worktree with feature branch
# From main checkout
git worktree add .worktrees/feature-auth -b feature/auth
# Or from an existing remote branch
git worktree add .worktrees/feature-auth origin/feature/authStep 3: Install dependencies (auto-detect)
cd .worktrees/feature-auth
# Node.js
[ -f package.json ] && npm install
# Python
[ -f requirements.txt ] && pip install -r requirements.txt
[ -f pyproject.toml ] && poetry install || pip install -e .
# Rust
[ -f Cargo.toml ] && cargo build
# Go
[ -f go.mod ] && go mod downloadStep 4: Verify clean baseline
# Run project tests to confirm worktree starts clean
npm test # or pytest, cargo test, go test ./...If tests fail before any changes, the worktree has a pre-existing issue — report it before proceeding.
---
Agent-Specific Patterns
Claude Code
Claude Code has native worktree support via the EnterWorktree tool.
Interactive session (single agent):
# Claude Code creates and enters a worktree automatically
# via the EnterWorktree tool during brainstorming/execution skillsHeadless / multi-agent via CLI:
# Launch agent 1 in its own worktree
cd .worktrees/feature-auth
claude --print "Implement OAuth2 login flow in src/auth/"
# Launch agent 2 in a separate worktree (parallel terminal)
cd .worktrees/feature-payments
claude --print "Add Stripe webhook handler in src/payments/"Subagent delegation (Task tool): The orchestrator agent stays in the main checkout. Each subagent receives a worktree path in its handoff:
Goal: Implement auth middleware
Constraints: Only modify files under src/auth/
Worktree: .worktrees/feature-auth (already created, deps installed)
Do-not-touch: src/payments/, src/core/
Output: working tests, conventional commits on feature/auth branchOpenAI Codex
Codex runs in cloud sandboxes — each task already gets an isolated environment. Worktrees are not needed for Codex's own execution. However, when you review Codex output locally:
# Create a worktree to review/test Codex's branch locally
git fetch origin
git worktree add .worktrees/codex-feature origin/codex/feature-name
cd .worktrees/codex-feature
npm testAider / Other Terminal Agents
# Create worktree, then point the agent at it
git worktree add .worktrees/feature-search -b feature/search
cd .worktrees/feature-search
aider --file src/search/index.ts src/search/engine.tsGitHub Copilot Workspace
Copilot Workspace operates in its own cloud environment (similar to Codex). Use worktrees for local review of its output branches.
---
Parallel Agent Execution
Running multiple AI agents simultaneously is the primary use case for worktrees.
Architecture
myproject/ # Human works here (main branch)
.worktrees/
feature-auth/ # Agent 1: auth feature
feature-payments/ # Agent 2: payments feature
fix-search-perf/ # Agent 3: search performance fixRules for parallel agents
1. One worktree per agent. Never share a worktree between agents. 2. One branch per worktree. Git enforces this — you cannot check out the same branch in two worktrees. 3. Disjoint file ownership. Each agent should own a bounded set of files. If agents need to touch the same file, serialize them (wave dispatch pattern). 4. Orchestrator stays in main. The coordinating agent/human uses the main checkout to review, merge, and verify.
Launching parallel agents (shell example)
# Create worktrees
git worktree add .worktrees/feat-auth -b feature/auth
git worktree add .worktrees/feat-payments -b feature/payments
# Launch agents in parallel (background processes)
(cd .worktrees/feat-auth && claude --print "Implement OAuth2 flow") &
(cd .worktrees/feat-payments && claude --print "Add Stripe webhooks") &
wait
# Orchestrator reviews from main checkout
git log --oneline feature/auth feature/paymentsMerge strategy after parallel work
1. Merge the upstream dependency branch first (e.g., feature/auth before feature/payments if payments depends on auth). 2. Rebase the downstream branch onto the updated integration branch. 3. Run full test suite after each merge. 4. If conflicts arise, the orchestrator resolves them — not the subagents.
---
Safety and Conflict Prevention
.gitignore discipline
Always verify before creating project-local worktrees:
git check-ignore -q .worktrees || {
echo ".worktrees/" >> .gitignore
git add .gitignore
git commit -m "chore: ignore worktree directory"
}Why critical: Without this, git status will show the entire worktree contents as untracked files, and git add . will stage them into your commit.
Lock file contention
Multiple worktrees share the same .git directory (via .git/worktrees/). Most Git operations are safe in parallel, but some can contend:
| Operation | Safe in parallel? | Notes |
|---|---|---|
git add / git commit | Yes | Each worktree has its own index |
git fetch | Yes | Updates shared refs safely |
git gc / git prune | No | Run only when no agent is active |
git worktree add/remove | No | Serialize worktree management |
Preventing cross-agent file conflicts
- Define
Owned filesandDo-not-touch filesin every agent handoff. - If two agents must modify the same file, use wave dispatch: finish agent 1, then start agent 2.
- After parallel execution, check for conflicts before merging:
# Check if branches touch the same files
git diff --name-only main..feature/auth > /tmp/auth-files.txt
git diff --name-only main..feature/payments > /tmp/payments-files.txt
comm -12 <(sort /tmp/auth-files.txt) <(sort /tmp/payments-files.txt)
# If output is non-empty, review those files for conflictsStale worktree detection
# List all worktrees and their branch status
git worktree list
# Find worktrees with branches already merged to main
for wt in $(git worktree list --porcelain | grep "^worktree " | cut -d' ' -f2); do
branch=$(git -C "$wt" branch --show-current 2>/dev/null)
if [ -n "$branch" ] && git branch --merged main | grep -q "$branch"; then
echo "STALE: $wt ($branch is merged)"
fi
done---
Cleanup Lifecycle
After a feature branch is merged, clean up its worktree promptly.
Standard cleanup
# 1. Remove the worktree
git worktree remove .worktrees/feature-auth
# 2. Delete the branch (if merged)
git branch -d feature/auth
# 3. Prune worktree metadata (if worktree was deleted manually)
git worktree pruneBatch cleanup script
#!/usr/bin/env bash
# Clean up all worktrees whose branches are merged to main
set -euo pipefail
git worktree list --porcelain | grep "^worktree " | cut -d' ' -f2 | while read -r wt; do
[ "$wt" = "$(git rev-parse --show-toplevel)" ] && continue # skip main
branch=$(git -C "$wt" branch --show-current 2>/dev/null || true)
if [ -n "$branch" ] && git branch --merged main | grep -qw "$branch"; then
echo "Removing: $wt ($branch)"
git worktree remove "$wt"
git branch -d "$branch" 2>/dev/null || true
fi
done
git worktree prunePost-merge checklist
- [ ] Worktree directory removed (
git worktree remove) - [ ] Feature branch deleted (
git branch -d) - [ ] No orphaned
node_modules/venv/targetleft behind - [ ]
git worktree listshows only active worktrees
---
Decision Table
| Question | Answer | Action |
|---|---|---|
| How many agents run at once? | 1 | Worktree optional; branch checkout is fine |
| 2+ | One worktree per agent (required) | |
| Human working at same time? | Yes | Agent(s) in worktrees; human in main checkout |
| No | Agent can use main checkout | |
| Agent is cloud-based (Codex)? | Yes | No local worktree needed; agent has its own sandbox |
| Reviewing locally | Create worktree to test agent's branch | |
| Agents touch same files? | Yes | Serialize via wave dispatch; do not parallelize |
| No | Safe to parallelize in separate worktrees | |
| Project has CI that runs locally? | Yes | Worktrees prevent CI and agent from competing |
---
Anti-Patterns
| Anti-Pattern | Problem | Fix |
|---|---|---|
| Two agents in one worktree | File conflicts, corrupted state | One worktree per agent, always |
| Worktree not in `.gitignore` | Worktree contents tracked by Git | git check-ignore before creating |
| Running `git gc` during parallel work | Can corrupt shared refs | Only run when all agents are idle |
| No file ownership in handoff | Agents overwrite each other's work | Define Owned files / Do-not-touch per agent |
| Forgetting to install deps | Agent hits import errors, wastes tokens | Auto-detect and run setup after worktree creation |
| Leaving stale worktrees | Disk bloat, confusing git worktree list | Clean up after branch merge |
| Nesting worktrees inside worktrees | Git confusion, broken refs | Always create worktrees from the main checkout |
---
Quick Command Reference
# Create worktree with new branch
git worktree add .worktrees/my-feature -b feature/my-feature
# Create worktree from existing remote branch
git worktree add .worktrees/my-feature origin/feature/my-feature
# List all worktrees
git worktree list
# Remove a worktree
git worktree remove .worktrees/my-feature
# Prune stale worktree metadata
git worktree prune
# Check if directory is gitignored
git check-ignore -q .worktrees
# See which files two branches both changed
comm -12 <(git diff --name-only main..branch-a | sort) \
<(git diff --name-only main..branch-b | sort)
# Move a worktree to a new location
git worktree move .worktrees/old-name .worktrees/new-name---
Related Resources
- Git Workflow SKILL.md — AI Agent Feature Loop, Local Safety Preflight
- Branching Strategies — GitHub Flow, Trunk-Based, GitFlow
- Agents & Subagents Skill — Orchestration, handoffs, wave dispatch
- Common Mistakes — Force push, lock files, history rewriting
Automated Quality Gates for Pull Requests
Enforce code quality automatically in PRs using CI/CD pipelines and quality gates.
Contents
- CI/CD Quality Gate Checklist
- GitHub Actions Quality Gates
- GitLab CI Quality Gates
- Pre-commit Hooks (Local Quality Gates)
- Quality Metrics & Thresholds
- PR Status Checks (GitHub)
- Automated PR Comments
- Skipping Quality Gates (Emergency Hotfixes)
- Quality Gate Exemptions
- Monitoring Quality Trends
- Related Resources
---
CI/CD Quality Gate Checklist
Essential Gates
Must-have for all projects:
- [ ] All tests pass (unit, integration, e2e)
- [ ] Code coverage > threshold (e.g., 80%)
- [ ] No linter errors
- [ ] No security vulnerabilities (SAST scan)
- [ ] No secrets in code
- [ ] PR size < 1000 lines (warning)
Advanced Gates
Recommended for production applications:
- [ ] Performance benchmarks pass
- [ ] Bundle size < threshold
- [ ] Accessibility (a11y) checks pass
- [ ] API compatibility check (no breaking changes)
- [ ] Dependency license check
- [ ] Code complexity metrics (cyclomatic complexity)
- [ ] Documentation coverage
- [ ] Docker image scan (if applicable)
---
GitHub Actions Quality Gates
Merge Queue Support (Required for GitHub Merge Queue)
IMPORTANT: If your repository uses GitHub merge queue, you MUST include the merge_group event trigger. Without this, status checks won't run when PRs are added to the merge queue, causing merges to fail.
on:
pull_request:
branches: [main, develop]
merge_group: # Required for merge queue!
branches: [main]Third-party CI providers: Update your CI configuration to run when branches matching gh-readonly-queue/{base_branch}/* are pushed. These are temporary branches created by the merge queue.
Merge Queue Configuration Options
When configuring merge queue in Settings -> Branches -> Branch protection:
| Setting | Description | Recommendation |
|---|---|---|
| Build concurrency | Max parallel CI builds (1-100) | 5-10 for balanced throughput |
| Minimum group size | PRs to batch before testing | 2-3 for busy repos |
| Maximum group size | Max PRs per batch | 5-10 to limit blast radius |
| Wait timeout | Max time waiting for CI | 60-120 minutes |
| Only merge non-failing | Skip flaky test failures | Enable if tests are flaky |
Best practices for merge queues:
- Keep CI fast (< 15 min) to maximize throughput
- Fix flaky tests - they cause unnecessary queue delays
- Use caching and parallelism to reduce CI time
- Monitor time-in-queue and failure rates
- Consider batching PRs to reduce redundant CI runs
See GitHub merge queue documentation for full configuration options.
---
Complete PR Checks Workflow
File: .github/workflows/pr-checks.yml
name: PR Quality Gates
on:
pull_request:
branches: [main, develop]
merge_group: # Support merge queue
branches: [main]
jobs:
quality-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # For accurate coverage diffs
# Setup
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
# Tests
- name: Run unit tests
run: npm test -- --coverage
- name: Check coverage threshold
run: |
COVERAGE=$(npm test -- --coverage --silent | grep -oP '\d+(?=%)')
if [ "$COVERAGE" -lt 80 ]; then
echo "[FAIL] Coverage $COVERAGE% below 80% threshold"
exit 1
fi
echo "[OK] Coverage $COVERAGE% meets threshold"
- name: Run integration tests
run: npm run test:integration
- name: Run E2E tests
run: npm run test:e2e
# Code Quality
- name: Lint code
run: npm run lint
- name: Type check
run: npm run type-check
- name: Check code formatting
run: npm run format:check
# Security
- name: Security scan (Snyk)
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
- name: Check for secrets
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
# Performance
- name: Run performance benchmarks
run: npm run bench
- name: Check bundle size
uses: andresz1/size-limit-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
# PR Size Check
- name: Check PR size
uses: CodeSeoul/pr-size-labeler@v1
with:
maximum: 1000
labels: |
{
"0": "size/XS",
"100": "size/S",
"300": "size/M",
"500": "size/L",
"1000": "size/XL"
}
# Upload Results
- name: Upload coverage reports
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Comment PR with results
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '[OK] All quality gates passed!'
})---
GitLab CI Quality Gates
Complete MR Checks Pipeline
File: .gitlab-ci.yml
stages:
- test
- quality
- security
variables:
COVERAGE_THRESHOLD: "80"
# Tests
test:unit:
stage: test
image: node:20-alpine
script:
- npm ci
- npm test -- --coverage
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
test:integration:
stage: test
image: node:20-alpine
services:
- postgres:15
variables:
POSTGRES_DB: test_db
POSTGRES_USER: test_user
POSTGRES_PASSWORD: test_pass
script:
- npm ci
- npm run test:integration
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
# Code Quality
code-quality:
stage: quality
image: docker:stable
services:
- docker:stable-dind
script:
- docker run --rm
-v $(pwd):/code
codeclimate/codeclimate analyze
artifacts:
reports:
codequality: gl-code-quality-report.json
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
lint:
stage: quality
image: node:20-alpine
script:
- npm ci
- npm run lint
- npm run format:check
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
# Security
security:sast:
stage: security
image: returntocorp/semgrep
script:
- semgrep ci --config auto
artifacts:
reports:
sast: gl-sast-report.json
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
security:dependency-scan:
stage: security
image: node:20-alpine
script:
- npm audit --audit-level=moderate
- npm run license-check
allow_failure: true
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
# Coverage Check
coverage-threshold:
stage: quality
image: node:20-alpine
script:
- |
COVERAGE=$(cat coverage/coverage-summary.json | jq '.total.lines.pct')
if (( $(echo "$COVERAGE < $COVERAGE_THRESHOLD" | bc -l) )); then
echo "[FAIL] Coverage $COVERAGE% below $COVERAGE_THRESHOLD% threshold"
exit 1
fi
echo "[OK] Coverage $COVERAGE% meets threshold"
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'---
Pre-commit Hooks (Local Quality Gates)
Using Husky + lint-staged
Installation:
npm install --save-dev husky lint-staged
npx husky install
npm pkg set scripts.prepare="husky install"Setup pre-commit hook:
npx husky add .husky/pre-commit "npx lint-staged"Configuration (.lintstagedrc.json):
{
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write",
"jest --bail --findRelatedTests"
],
"*.{json,md,yml,yaml}": [
"prettier --write"
],
"*.{css,scss}": [
"stylelint --fix",
"prettier --write"
]
}---
Quality Metrics & Thresholds
Recommended Thresholds
| Metric | Threshold | Severity | Action |
|---|---|---|---|
| Test Coverage | < 80% | [FAIL] Blocking | Must add tests |
| Linter Errors | > 0 | [FAIL] Blocking | Must fix |
| Security Vulnerabilities | High/Critical | [FAIL] Blocking | Must patch |
| PR Size | > 1000 LOC | [WARNING] Warning | Consider splitting |
| Cyclomatic Complexity | > 10 | [WARNING] Warning | Consider refactoring |
| Bundle Size Increase | > 10% | [WARNING] Warning | Review dependencies |
| Build Time | > 10 min | ℹ Info | Optimize if possible |
---
PR Status Checks (GitHub)
Required Status Checks
Configure in Settings -> Branches -> Branch protection rules:
Required checks before merging:
- [OK] All tests pass
- [OK] Code coverage ≥ 80%
- [OK] No linter errors
- [OK] Security scan clean
- [OK] PR approved by 1+ reviewers
Optional checks (warnings only):
- [WARNING] PR size check
- [WARNING] Performance benchmarks
- [WARNING] Bundle size increase
---
Automated PR Comments
Coverage Report Comment
Using GitHub Actions:
- name: Comment PR with coverage
uses: romeovs/lcov-reporter-action@v0.3.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
lcov-file: ./coverage/lcov.info
title: "Coverage Report"Code Quality Summary
- name: Comment PR with quality metrics
uses: actions/github-script@v7
with:
script: |
const coverage = process.env.COVERAGE;
const lintErrors = process.env.LINT_ERRORS;
const testResults = process.env.TEST_RESULTS;
const body = `
## Quality Metrics
| Metric | Value | Status |
|--------|-------|--------|
| Coverage | ${coverage}% | ${coverage >= 80 ? '[OK]' : '[FAIL]'} |
| Lint Errors | ${lintErrors} | ${lintErrors == 0 ? '[OK]' : '[FAIL]'} |
| Tests | ${testResults} | [OK] |
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});---
Skipping Quality Gates (Emergency Hotfixes)
When to Skip
Only skip quality gates for:
- Critical production outages
- Security vulnerabilities requiring immediate patch
- Data loss prevention
How to skip (use sparingly):
# Commit message bypass (if configured)
git commit -m "fix: critical security patch [skip-ci]"
# Or manual approval in GitHub/GitLabPost-hotfix requirements:
- [ ] Create follow-up PR to add missing tests
- [ ] Document why gates were skipped
- [ ] Review in next team retrospective
---
Quality Gate Exemptions
Configuration Example
`.quality-gates.yml`:
exemptions:
- path: "legacy/**/*"
reason: "Legacy code - gradual migration"
checks:
- coverage # Don't block on coverage
expires: "2025-12-31"
- path: "scripts/**/*"
reason: "Build scripts - different standards"
checks:
- complexity
- coverage
- path: "**/*.test.ts"
reason: "Test files"
checks:
- complexity # Tests can be complex---
Monitoring Quality Trends
Track Over Time
Metrics to monitor:
- Average PR size
- Time to merge
- Test coverage trend
- Build success rate
- Security vulnerability count
Tools:
- GitHub Insights - Built-in PR metrics
- Codecov - Coverage trends
- SonarQube - Code quality trends
- Grafana - Custom dashboards
---
Related Resources
- PR Best Practices Guide - PR size and review guidelines
- Branching Strategies Comparison - Workflow patterns
- Commit Conventions - Commit message standards
Branching Strategies - Comprehensive Comparison
Deep dive into modern Git branching strategies with decision frameworks, migration paths, and real-world examples.
Contents
- Strategy Comparison Matrix
- GitHub Flow - Detailed Guide
- Trunk-Based Development - Detailed Guide
- GitFlow - Detailed Guide
- Migration Paths
- Team Size Recommendations
- Branching Strategy Checklist
- Anti-Patterns to Avoid
- Real-World Examples
---
Strategy Comparison Matrix
Feature Comparison
| Feature | GitHub Flow | Trunk-Based | GitFlow |
|---|---|---|---|
| Complexity | Low | Low-Medium | High |
| Learning Curve | Easy | Medium | Steep |
| Branch Count | 2-5 | 1-3 | 5-10+ |
| Merge Frequency | Multiple/day | Continuous | Weekly/release |
| Release Process | Tag main | Tag main | Release branches |
| Hotfix Process | Branch from main | Branch from main | Dedicated hotfix/* |
| CI/CD Fit | Excellent | Excellent | Poor |
| Team Size | 1-15 | 5-50+ | Any |
| Best For | Startups, SaaS | Enterprises, CI/CD | Versioned software |
---
GitHub Flow - Detailed Guide
Philosophy
"Deploy from main, always. Main is always production-ready."
Full Workflow
1. Create Feature Branch:
# Always branch from latest main
git checkout main
git pull origin main
git checkout -b feature/user-dashboard
# Naming conventions
feature/user-authentication
feature/payment-integration
bugfix/login-error
hotfix/security-patch
docs/api-documentation2. Develop with Frequent Commits:
# Make incremental progress
git commit -m "feat: add dashboard layout component"
git commit -m "feat: add metrics cards to dashboard"
git commit -m "test: add dashboard component tests"
git commit -m "docs: document dashboard props"
# Push frequently for backup
git push origin feature/user-dashboard3. Open Pull Request Early:
# Draft PR for early feedback
Title: [WIP] User Dashboard
## What
Building user dashboard with metrics and activity feed
## Progress
- [x] Layout component
- [x] Metrics cards
- [ ] Activity feed
- [ ] Responsive design
- [ ] E2E tests
## Questions
- Should we show real-time metrics or daily aggregates?
- Any design feedback on the layout?4. Review & Iterate:
# Address review comments
git commit -m "refactor: extract metrics calculation logic"
git commit -m "fix: handle missing data in metrics cards"
git push origin feature/user-dashboard
# Rebase to keep history clean (optional)
git fetch origin
git rebase origin/main
git push --force-with-lease origin feature/user-dashboard5. Merge & Deploy:
# After approval, merge via GitHub/GitLab UI
# Or locally:
git checkout main
git pull origin main
git merge --no-ff feature/user-dashboard
git push origin main
# Automated deployment triggers
# Tag if needed
git tag -a v1.2.0 -m "Release: User Dashboard"
git push origin v1.2.0
# Clean up
git branch -d feature/user-dashboard
git push origin --delete feature/user-dashboardGitHub Flow with Feature Flags
For large features that can't ship atomically:
// Use feature flags to hide incomplete work
import { featureFlags } from './config';
function Dashboard() {
if (!featureFlags.userDashboard) {
return <LegacyDashboard />;
}
return <NewDashboard />;
}
// Merge to main even if incomplete
// Enable flag when readyAdvantages:
- Deploy incomplete code safely
- Test in production with limited users
- Gradual rollout capability
---
Trunk-Based Development - Detailed Guide
Philosophy
"Integrate continuously, release confidently. Branches live hours, not days."
Core Principles
1. Short-Lived Branches: < 24 hours from creation to merge 2. Small Commits: < 400 lines of code per commit 3. Feature Flags: Hide incomplete features 4. High Test Coverage: > 80% to catch integration issues 5. Continuous Integration: Every commit tested automatically
Full Workflow
1. Create Micro-Branch:
# Branch for single, focused change
git checkout -b feat/add-user-filter main
# Commit 1: Implementation
git commit -m "feat: add user filter dropdown component"
# Commit 2: Tests
git commit -m "test: add user filter component tests"
# Commit 3: Integration
git commit -m "feat: integrate user filter with table"
# Total time: 2-4 hours2. Use Feature Flags for Large Features:
# Feature flag in code
from feature_flags import is_enabled
def process_payment(order):
if is_enabled('new_payment_processor'):
return new_payment_flow(order)
else:
return legacy_payment_flow(order)
# Deploy to main even if new flow not ready
# Enable flag after testing3. Merge Rapidly:
# Push and create PR immediately
git push origin feat/add-user-filter
# Request quick review (< 2 hours)
# Small PRs get reviewed faster
# Merge within same day
git checkout main
git pull origin main
git merge feat/add-user-filter
git push origin main
# Delete branch immediately
git branch -d feat/add-user-filter
git push origin --delete feat/add-user-filter4. Continuous Deployment:
# .github/workflows/main.yml
name: CI/CD
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: npm test
- name: Deploy to production
if: success()
run: npm run deployTrunk-Based with Release Branches (Scaled)
For teams releasing on schedule:
# Development on main
git checkout main
git commit -m "feat: new feature"
git push origin main
# Weekly release branch
git checkout -b release/2024-w47 main
git push origin release/2024-w47
# Continue development on main
git checkout main
git commit -m "feat: another feature"
# Hotfix on release branch
git checkout release/2024-w47
git cherry-pick <commit-hash>
git push origin release/2024-w47---
GitFlow - Detailed Guide
Philosophy
"Structured releases with parallel development and maintenance."
Branch Structure
main (production)
├─ release/v2.1.0 (release prep)
└─ develop (integration)
├─ feature/user-auth
├─ feature/payment
└─ feature/notifications
hotfix/security-patch (from main)Full Workflow
1. Feature Development:
# Create feature branch from develop
git checkout develop
git pull origin develop
git checkout -b feature/user-authentication
# Develop feature
git commit -m "feat: add JWT authentication"
git commit -m "feat: add refresh token logic"
git commit -m "test: add auth integration tests"
# Keep up-to-date with develop
git fetch origin
git rebase origin/develop
# Merge back to develop
git checkout develop
git merge --no-ff feature/user-authentication
git push origin develop
# Delete feature branch
git branch -d feature/user-authentication2. Release Preparation:
# Create release branch from develop
git checkout develop
git pull origin develop
git checkout -b release/v2.1.0
# Version bump and final fixes
npm version minor
git commit -am "chore: bump version to 2.1.0"
# Bug fixes only on release branch
git commit -m "fix: resolve edge case in auth"
# Merge to main
git checkout main
git merge --no-ff release/v2.1.0
git tag -a v2.1.0 -m "Release 2.1.0"
git push origin main --tags
# Merge back to develop
git checkout develop
git merge --no-ff release/v2.1.0
git push origin develop
# Delete release branch
git branch -d release/v2.1.03. Hotfix Process:
# Critical bug in production
git checkout main
git pull origin main
git checkout -b hotfix/security-patch
# Fix and test
git commit -m "fix: patch SQL injection vulnerability"
npm version patch # 2.1.0 -> 2.1.1
# Merge to main
git checkout main
git merge --no-ff hotfix/security-patch
git tag -a v2.1.1 -m "Hotfix: Security patch"
git push origin main --tags
# Merge to develop
git checkout develop
git merge --no-ff hotfix/security-patch
git push origin develop
# Delete hotfix branch
git branch -d hotfix/security-patch---
Migration Paths
From GitFlow to GitHub Flow
Why Migrate: Faster releases, simpler workflow, better CI/CD fit
Step 1: Simplify Branches:
# Merge all open features to develop
git checkout develop
git merge feature/auth
git merge feature/payments
# Final release from develop
git checkout main
git merge develop
git tag v3.0.0
# Delete develop branch
git branch -D develop
git push origin --delete developStep 2: Adopt GitHub Flow:
# New workflow: feature branches from main
git checkout main
git checkout -b feature/new-feature
# ... develop, PR, merge to mainStep 3: Update CI/CD:
# Before (GitFlow)
on:
push:
branches: [develop]
# After (GitHub Flow)
on:
push:
branches: [main]From GitHub Flow to Trunk-Based
Why Migrate: Scale to larger teams, reduce merge conflicts
Step 1: Add Feature Flags:
// Install feature flag library
npm install @openfeature/server-sdk
// Wrap new features
if (featureFlags.isEnabled('new-search')) {
return <NewSearch />;
}Step 2: Enforce Short-Lived Branches:
# .github/workflows/pr-checks.yml
- name: Check branch age
run: |
DAYS_OLD=$(git log --since="2 days ago" --oneline | wc -l)
if [ "$DAYS_OLD" -eq 0 ]; then
echo "Branch is > 2 days old. Please merge or rebase."
exit 1
fiStep 3: Increase Merge Frequency:
# Before: Merge when feature complete
# After: Merge daily with feature flags
git commit -m "feat: add search UI (behind flag)"
git push
# Merge same day, even if incomplete---
Team Size Recommendations
Small Teams (1-5 developers)
Recommendation: GitHub Flow
Why:
- Minimal overhead
- Fast iteration
- Easy to understand
- No coordination needed
Setup:
# Branch protection on main
Protected branches: main
Require PR before merge: Yes
Require approvals: 1
Require status checks: Yes (CI)Medium Teams (5-15 developers)
Recommendation: GitHub Flow or Trunk-Based
Why:
- Enough developers for merge conflicts
- Need faster integration (trunk-based)
- Or keep simple with GitHub Flow + feature flags
Setup:
# Trunk-based setup
Protected branches: main
Require PR before merge: Yes
Require approvals: 2
Branch age limit: 24 hours (automated check)
Feature flags: Required for large featuresLarge Teams (15+ developers)
Recommendation: Trunk-Based Development
Why:
- Reduces merge conflicts through rapid integration
- Scales to hundreds of developers
- Requires mature CI/CD and testing
Setup:
# Enterprise trunk-based
Protected branches: main, release/*
Require PR before merge: Yes
Require approvals: 2
Automated tests: Required
Code coverage: > 80%
Feature flags: Mandatory
Deployment: Automated to staging, manual to prodVersioned Software Teams
Recommendation: GitFlow
Why:
- Support multiple versions (e.g., 2.x and 3.x)
- Scheduled releases (monthly, quarterly)
- Need structured release process
Setup:
# GitFlow setup
Protected branches: main, develop
Feature branches: feature/*
Release branches: release/*
Hotfix branches: hotfix/*
Require PR for all merges: Yes
Version tags: Required on main---
Branching Strategy Checklist
GitHub Flow Readiness
- [ ] Can deploy multiple times per day
- [ ] Have automated CI/CD pipeline
- [ ] Test coverage > 70%
- [ ] Team < 15 developers
- [ ] Single production version
- [ ] Fast review culture (< 4 hours)
Trunk-Based Readiness
- [ ] Can deploy daily
- [ ] Have feature flag system
- [ ] Test coverage > 80%
- [ ] Automated quality gates
- [ ] Fast CI/CD (< 10 minutes)
- [ ] Team trained on short-lived branches
GitFlow Readiness
- [ ] Release on schedule (weekly, monthly)
- [ ] Support multiple versions
- [ ] Need QA phase before release
- [ ] Regulated industry (finance, healthcare)
- [ ] Comfortable with complexity
- [ ] Have release manager role
---
Anti-Patterns to Avoid
Long-Lived Feature Branches
Problem: Feature branch open for weeks, massive merge conflicts
Fix: Use stacked diffs or feature flags
# Bad
git checkout -b feature/rewrite-everything
# ... 3 weeks later, 5000 line diff
# Good
git checkout -b feat/extract-service-layer (400 lines)
git checkout -b feat/add-new-api (300 lines)
git checkout -b feat/migrate-clients (200 lines)Branching from Branches
Problem: Pyramid of branches, unclear base
Fix: Always branch from main or develop
# Bad
feature/A -> feature/B -> feature/C
# Good
main -> feature/A (merge)
main -> feature/B (merge)
main -> feature/C (merge)No Branch Protection
Problem: Accidental direct commits to main
Fix: Enable branch protection
# GitHub branch protection
main:
require_pull_request: true
required_approvals: 2
dismiss_stale_reviews: true
require_status_checks: true
checks:
- CI/CD Pipeline
- Code Coverage
- Security Scan---
Real-World Examples
Example 1: SaaS Startup (GitHub Flow)
Team: 5 developers Deployment: 10x/day to production Workflow:
# Developer workflow
git checkout main
git pull
git checkout -b feature/add-export
git commit -m "feat: add CSV export"
git push origin feature/add-export
# Create PR, review, merge
# Deployment happens automaticallyResults:
- Features ship in hours, not days
- Minimal process overhead
- High deployment frequency
Example 2: Fintech Company (Trunk-Based)
Team: 30 developers Deployment: Daily to staging, weekly to prod Workflow:
# Developer workflow with feature flags
git checkout main
git pull
git checkout -b feat/fraud-detection
git commit -m "feat: add fraud detection (behind flag FRAUD_V2)"
git push origin feat/fraud-detection
# PR reviewed within 2 hours, merged same day
# Feature flag enabled after validationResults:
- Reduced merge conflicts by 70%
- Faster integration
- Safe production testing with flags
Example 3: Enterprise Software (GitFlow)
Team: 50 developers Deployment: Quarterly releases Workflow:
# Feature development
git checkout develop
git checkout -b feature/sso-integration
# ... 2 weeks of development
git checkout develop
git merge feature/sso-integration
# Release preparation
git checkout -b release/v4.0.0 develop
# ... QA testing for 2 weeks
git checkout main
git merge release/v4.0.0
git tag v4.0.0Results:
- Structured release process
- Support for multiple versions
- Predictable release schedule
Conventional Commits & Semantic Versioning
Comprehensive guide to commit message conventions and automated versioning.
Contents
- Conventional Commits Specification
- Commit Types
- Examples
- Scopes
- Writing Good Commit Messages
- Semantic Versioning (SemVer)
- Automation Tools
- Changelog Generation
- Best Practices
- Enforcement Strategies
- Team Adoption
- Common Mistakes
- Quick Reference
---
Conventional Commits Specification
Format
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]Components
Type (required): Category of change Scope (optional): Area affected (module, component, package) Description (required): Brief summary in imperative mood Body (optional): Detailed explanation of what and why Footer (optional): Breaking changes, issue references
---
Commit Types
Standard Types
| Type | Purpose | SemVer Impact | Changelog Section |
|---|---|---|---|
feat | New feature | MINOR (0.1.0) | Features |
fix | Bug fix | PATCH (0.0.1) | Bug Fixes |
docs | Documentation only | None | Documentation |
style | Code style (formatting, whitespace) | None | - |
refactor | Code refactoring | None | - |
perf | Performance improvement | PATCH | Performance |
test | Tests only | None | - |
build | Build system, dependencies | None | Build System |
ci | CI configuration | None | - |
chore | Maintenance tasks | None | - |
revert | Revert previous commit | Depends | - |
Breaking Changes
| Marker | SemVer Impact | Example |
|---|---|---|
BREAKING CHANGE: in footer | MAJOR (1.0.0) | See below |
| Exclamation mark after type/scope | MAJOR (1.0.0) | feat!: remove API v1 |
---
Examples
Feature (MINOR version bump)
Simple Feature:
git commit -m "feat: add user profile page"With Scope:
git commit -m "feat(auth): add OAuth2 social login"With Body:
git commit -m "feat(api): add pagination to user list endpoint
Add limit and offset query parameters for paginating users.
Default limit is 20, maximum is 100.
Returns total count in response headers for client pagination UI."With Issue Reference:
git commit -m "feat(dashboard): add metrics visualization
Closes #234"Bug Fix (PATCH version bump)
Simple Fix:
git commit -m "fix: resolve null pointer in login"With Root Cause:
git commit -m "fix(auth): prevent duplicate user creation on concurrent requests
Race condition occurred when multiple requests tried to create
the same user simultaneously. Added database unique constraint
and transaction handling to prevent duplicates.
Fixes #456"With Testing Notes:
git commit -m "fix(api): handle 404 errors for deleted resources
Previously returned 500 error when resource was deleted.
Now returns proper 404 with error message.
Added integration tests to verify error handling."Breaking Change (MAJOR version bump)
With Footer:
git commit -m "feat(api): migrate to REST API v2
Remove support for all v1 endpoints and migrate to new
response format with consistent error handling.
BREAKING CHANGE: All v1 endpoints removed. Clients must upgrade
to v2 API. See migration guide: docs/api-v2-migration.md"With ! Marker:
git commit -m "feat(auth)!: change JWT payload structure
BREAKING CHANGE: JWT payload now uses 'userId' instead of 'id'.
Existing tokens will be invalidated. Users must re-login."Multiple Breaking Changes:
git commit -m "refactor!: restructure database schema
BREAKING CHANGE: User table renamed to 'users' (was 'user')
BREAKING CHANGE: Deleted 'legacy_auth' table, use 'auth_tokens' instead
BREAKING CHANGE: Changed 'created_at' to timestamp (was string)
Migration required: npm run migrate:v2"Documentation
git commit -m "docs: update API authentication guide
Add examples for OAuth2 flow and refresh tokens."git commit -m "docs(readme): add installation instructions for Windows"Refactoring
git commit -m "refactor: extract auth logic to separate service"git commit -m "refactor(api): simplify error handling middleware
Consolidate duplicate error handling code into single middleware.
No functional changes."Performance
git commit -m "perf: optimize database queries with indexes
Add indexes on user.email and post.created_at columns.
Reduces query time from 500ms to 50ms for user search."git commit -m "perf(frontend): lazy load dashboard components
Reduce initial bundle size by 200KB by lazy loading charts."Tests
git commit -m "test: add integration tests for auth flow"git commit -m "test(api): increase coverage for error handling
Add tests for edge cases: network failures, timeouts,
invalid responses. Coverage increased from 75% to 92%."Build & Dependencies
git commit -m "build: upgrade to Node.js 20"git commit -m "build(deps): bump axios from 1.4.0 to 1.6.0
Security fix for CVE-2023-12345"CI/CD
git commit -m "ci: add code coverage reporting to GitHub Actions"git commit -m "ci: enable auto-merge for dependabot PRs
Auto-merge dependency updates if all tests pass."Chore
git commit -m "chore: update .gitignore for IDE files"git commit -m "chore: clean up unused dependencies"Revert
git commit -m "revert: feat(api): add pagination
This reverts commit abc123def456.
Pagination caused performance issues in production."---
Scopes
Common Scopes by Project Type
Backend API:
auth- Authentication/authorizationapi- API endpointsdb- Database, migrationsmiddleware- Express/Koa middlewareservice- Business logic servicesutils- Utility functions
Frontend:
ui- UI componentspages- Page componentsstore- State managementhooks- React hooksstyles- CSS, stylingroutes- Routing
Mobile:
ios- iOS specific codeandroid- Android specific codenavigation- Navigationscreens- Screen components
Infrastructure:
infra- Infrastructure codedeploy- Deployment scriptsmonitoring- Monitoring setupsecurity- Security config
Monorepo:
packages/auth- Auth packageapps/web- Web applicationapps/mobile- Mobile application
---
Writing Good Commit Messages
Imperative Mood
Use imperative mood in description (like giving a command).
Good (imperative):
feat: add user authentication
fix: resolve memory leak
docs: update installation guideBad (past tense):
feat: added user authentication
fix: resolved memory leak
docs: updated installation guideRule: The commit should complete the sentence: "If applied, this commit will _[your commit message]_"
Be Specific
Good (specific):
fix(auth): prevent race condition in token refresh
Add mutex lock to prevent concurrent token refresh requests
from creating duplicate tokens.Bad (vague):
fix: fix bugExplain Why, Not What
The diff shows what changed. The message should explain why.
Good (explains why):
perf(api): add Redis caching for user profile endpoint
User profile is fetched on every request but changes infrequently.
Caching reduces database load by 80% and improves response time
from 200ms to 20ms.Bad (just what):
perf: add cachingUse Body for Context
When to use body:
- Complex changes that need explanation
- Non-obvious solutions or trade-offs
- Multiple related changes
- Breaking changes
Example:
feat(search): implement fuzzy search with Elasticsearch
Replace PostgreSQL full-text search with Elasticsearch to support:
- Fuzzy matching (handle typos)
- Faceted search (filters)
- Relevance scoring
- Real-time indexing
Considered alternatives:
- Algolia: too expensive for our scale
- Meilisearch: lacks advanced features we need
Performance improvement: 100ms -> 20ms avg query time
Closes #789---
Semantic Versioning (SemVer)
Version Format
MAJOR.MINOR.PATCHExample: 2.3.1
Version Increments
| Change Type | Increment | Example | Description |
|---|---|---|---|
| Breaking change | MAJOR | 2.3.1 -> 3.0.0 | Incompatible API changes |
| New feature | MINOR | 2.3.1 -> 2.4.0 | Backward-compatible functionality |
| Bug fix | PATCH | 2.3.1 -> 2.3.2 | Backward-compatible fixes |
Pre-release Versions
1.0.0-alpha.1 # Alpha version (early testing)
1.0.0-beta.2 # Beta version (feature complete, bugs expected)
1.0.0-rc.1 # Release candidate (production ready, final testing)How Conventional Commits Map to SemVer
Automatic Version Bumping:
feat: add feature A -> 1.0.0 -> 1.1.0 (MINOR)
feat: add feature B -> 1.1.0 -> 1.2.0 (MINOR)
fix: resolve bug X -> 1.2.0 -> 1.2.1 (PATCH)
fix: resolve bug Y -> 1.2.1 -> 1.2.2 (PATCH)
feat!: breaking change -> 1.2.2 -> 2.0.0 (MAJOR)---
Automation Tools
1. Commitlint
Enforce commit conventions in git hooks or CI/CD.
Install:
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# Create config
echo "export default {extends: ['@commitlint/config-conventional']};" > commitlint.config.jsHusky Hook (validate commits locally):
npm install --save-dev husky
# Add hook
npx husky add .husky/commit-msg 'npx commitlint --edit $1'CI/CD (GitHub Actions):
- name: Validate PR title
uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}2. Standard-Version
Automate changelog and version bumps (manual trigger).
Install:
npm install --save-dev standard-versionUsage:
# Generate changelog and bump version
npm run release
# First release
npm run release -- --first-release
# Pre-release
npm run release -- --prerelease alphaWhat it does: 1. Analyzes commits since last tag 2. Determines next version (SemVer) 3. Updates CHANGELOG.md 4. Bumps version in package.json 5. Creates git tag
3. Semantic-Release
Fully automated version management (triggers on CI/CD).
Install:
npm install --save-dev semantic-releaseConfiguration (.releaserc.json):
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/git",
"@semantic-release/github"
]
}GitHub Actions:
name: Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}What it does: 1. Analyzes commits on main branch 2. Determines next version 3. Generates release notes 4. Updates CHANGELOG.md 5. Publishes to npm 6. Creates GitHub release 7. Commits version bump
---
Changelog Generation
Automatic Changelog from Commits
Example CHANGELOG.md:
# Changelog
All notable changes to this project will be documented in this file.
## [2.1.0] - 2024-03-15
### Features
- **auth**: add OAuth2 social login ([abc123](https://github.com/user/repo/commit/abc123))
- **dashboard**: add metrics visualization ([def456](https://github.com/user/repo/commit/def456))
### Bug Fixes
- **api**: handle 404 errors for deleted resources ([ghi789](https://github.com/user/repo/commit/ghi789))
- **auth**: prevent duplicate user creation ([jkl012](https://github.com/user/repo/commit/jkl012))
### Performance
- **api**: add Redis caching for user profiles ([mno345](https://github.com/user/repo/commit/mno345))
## [2.0.0] - 2024-02-01
### BREAKING CHANGES
- **api**: migrate to REST API v2 ([pqr678](https://github.com/user/repo/commit/pqr678))
- Remove all v1 endpoints
- New response format
- Migration guide: docs/api-v2-migration.md
### Features
- **api**: add pagination to all list endpoints ([stu901](https://github.com/user/repo/commit/stu901))---
Best Practices
Atomic Commits
Each commit should be a single logical change.
Good (atomic):
git commit -m "feat: add user authentication"
git commit -m "test: add auth integration tests"
git commit -m "docs: document auth API"Bad (mixing changes):
git commit -m "Add auth, fix bug, update docs"Commit Frequency
Commit often, but keep commits meaningful.
Good rhythm:
- Implement feature -> commit
- Write tests -> commit
- Fix discovered bug -> commit
- Update docs -> commit
Too frequent (bad):
git commit -m "WIP"
git commit -m "fix typo"
git commit -m "fix another typo"
git commit -m "actually fix it now"Solution: Use git commit --amend or interactive rebase to clean up before pushing.
Squashing Before Merge
Clean up messy commit history before merging:
# Interactive rebase to squash commits
git rebase -i HEAD~5
# Or use --autosquash workflow
git commit -m "feat: add feature"
git commit -m "fixup! feat: add feature" # Auto-squashes
git rebase -i --autosquash main---
Enforcement Strategies
Local Enforcement (Git Hooks)
Pre-commit hook (format check):
#!/bin/bash
# .git/hooks/pre-commit
npm run lint
npm run test:quickCommit-msg hook (commitlint):
#!/bin/bash
# .git/hooks/commit-msg
npx commitlint --edit $1CI/CD Enforcement
GitHub Actions:
name: Commit Checks
on:
pull_request:
jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Validate commits
uses: wagoid/commitlint-github-action@v5GitLab CI:
commitlint:
stage: test
script:
- npm install @commitlint/cli @commitlint/config-conventional
- echo "module.exports = {extends: ['@commitlint/config-conventional']};" > commitlint.config.js
- npx commitlint --from $CI_MERGE_REQUEST_DIFF_BASE_SHA --to HEAD
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'---
Team Adoption
Gradual Rollout
Phase 1: Education (Week 1-2)
- Share commit convention guide
- Demo tools (commitlint, semantic-release)
- Show benefits (automated changelogs)
Phase 2: Soft Enforcement (Week 3-4)
- Add commitlint warnings (not blocking)
- Encourage conventional commits in PRs
- Team reviews examples together
Phase 3: Hard Enforcement (Week 5+)
- Enable commitlint in CI/CD (blocking)
- Require conventional commits for all PRs
- Reject non-conforming commits
Commit Message Templates
Create git template:
# ~/.gitmessage
# <type>[optional scope]: <description>
#
# [optional body]
#
# [optional footer(s)]
#
# Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
git config --global commit.template ~/.gitmessageNow git commit opens editor with template filled in.
---
Common Mistakes
Mistake 1: Vague Types
Bad:
git commit -m "chore: update stuff"Good:
git commit -m "build(deps): upgrade React from 17 to 18"Mistake 2: Missing Scope
Bad:
git commit -m "feat: add feature"Good:
git commit -m "feat(auth): add OAuth2 social login"Mistake 3: Past Tense
Bad:
git commit -m "fixed bug in login"Good:
git commit -m "fix(auth): resolve race condition in login"Mistake 4: No Context
Bad:
git commit -m "fix: bug"Good:
git commit -m "fix(api): prevent null pointer when user not found
Return 404 error instead of 500 when user ID doesn't exist.
Added validation middleware to check resource existence.
Fixes #456"---
Quick Reference
Commit Message Checklist
- [ ] Type is valid (feat, fix, docs, etc.)
- [ ] Scope is appropriate (if used)
- [ ] Description is imperative mood ("add" not "added")
- [ ] Description is specific and clear
- [ ] Body explains why (if complex)
- [ ] Footer references issues (if applicable)
- [ ] Breaking changes marked with exclamation mark or BREAKING CHANGE footer
Common Commands
# Amend last commit
git commit --amend
# Rewrite commit message
git commit --amend -m "new message"
# Interactive rebase (clean up history)
git rebase -i HEAD~3
# Auto-squash fixup commits
git commit -m "fixup! previous commit message"
git rebase -i --autosquash main
# Sign commits
git commit -S -m "commit message"Resources
- Conventional Commits Spec: https://www.conventionalcommits.org
- Semantic Versioning: https://semver.org
- Commitlint: https://commitlint.js.org
- Standard-Version: https://github.com/conventional-changelog/standard-version
- Semantic-Release: https://semantic-release.gitbook.io