Every team argues about Git workflow until they pick one and stick with it. Here are the major strategies, when to use each, and how to avoid the common pitfalls.
The Three Main Workflows# 1. GitHub Flow (Simple)# m f f a e e i a a n t t u u ─ r r ─ e e ─ - - ─ a b ─ ● ─ ─ ● ─ ─ ─ ─ ─ ─ ● ● ─ ─ ─ ─ ─ ─ ─ ● ─ ● ─ ─ ─ ─ ─ ● ─ ─ ● ─ ─ ─ ─ ─ ─ ● ● ─ ─ ─ ─ ─ ● ─ ─ ─ ─ ─ Rules:
main is always deployableCreate feature branches from main Open PR, get review, merge to main Deploy immediately after merge Best for: Small teams, continuous deployment, SaaS
1
2
3
4
5
6
7
8
9
10
11
# Start feature
git checkout main
git pull origin main
git checkout -b feature/add-login
# Work...
git add .
git commit -m "Add login page"
git push origin feature/add-login
# Open PR, merge, deploy
2. GitFlow (Structured)# m r d f a e e e i l v a n e e t a l u s o r e p e ─ ─ ─ ─ ─ ─ ─ ● ● ─ ─ ─ ─ ● ─ ─ ─ ─ ● ─ ─ ─ ─ ─ ─ ● ─ ─ ─ ● ─ ● ─ ─ ─ ─ ─ ─ ─ ─ ─ ● ─ ● ─ ─ ─ ─ ─ ─ ─ ─ ─ ● ● ─ ● ─ ─ ─ ─ ─ ─ ● ─ ● ─ ● ─ ─ ─ ─ ─ ● ─ ─ ─ ─ ─ ─ ─ ● ─ ─ ─ ─ ─ ─ ─ ─ ─ Branches:
main: Production releases onlydevelop: Integration branchfeature/*: New featuresrelease/*: Release prephotfix/*: Emergency fixesBest for: Scheduled releases, versioned software, mobile apps
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Start feature
git checkout develop
git checkout -b feature/user-profile
# Complete feature
git checkout develop
git merge feature/user-profile
# Prepare release
git checkout -b release/1.2.0
# Bug fixes, version bumps
# Release
git checkout main
git merge release/1.2.0
git tag v1.2.0
git checkout develop
git merge release/1.2.0
3. Trunk-Based Development (Fast)# m a i n d ─ i ● r ─ ↑ e ● c ─ ↑ t ● ─ ↑ c ● o ─ ↑ m ● m ─ ↑ i ● t ─ ↑ s ● ─ ↑ o ● r ─ ↑ ● v ─ ↑ e ● r ─ ↑ y ● ─ ↑ s ● h ─ ↑ o ● r ─ ↑ t ● - ─ ↑ l ● i ─ ↑ v ● e ─ ↑ d ● ─ ↑ b ● r ─ ↑ a ● n ─ ↑ c ● h ─ ↑ e s
Rules:
Everyone commits to main (trunk) Branches live < 1 day Feature flags hide incomplete work CI runs on every commit Best for: Experienced teams, robust CI, feature flags in place
1
2
3
4
5
6
7
8
9
10
11
12
13
# Short-lived branch
git checkout main
git pull
git checkout -b quick-fix
# Work for a few hours max
git add .
git commit -m "Fix checkout button alignment"
git push origin quick-fix
# Merge same day
gh pr create --fill
gh pr merge --squash
Choosing a Workflow# Factor GitHub Flow GitFlow Trunk-Based Team size Small-Medium Any Medium-Large Release cadence Continuous Scheduled Continuous CI maturity Basic Basic Advanced Feature flags Optional Rare Required Complexity Low High Medium
Branch Naming# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Feature branches
feature/user-authentication
feature/JIRA-123-payment-integration
# Bug fixes
fix/login-redirect-loop
bugfix/JIRA-456-null-pointer
# Hotfixes (production emergencies)
hotfix/security-patch-xss
hotfix/v1.2.1
# Releases
release/1.2.0
release/2024-q1
# Experiments
experiment/new-algorithm
spike/redis-caching
Commit Messages# Conventional Commits# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Format
<type>( <scope>) : <description>
# Types
feat: New feature
fix: Bug fix
docs: Documentation
style: Formatting ( no code change)
refactor: Code restructure ( no behavior change)
test: Adding tests
chore: Maintenance
# Examples
feat( auth) : add OAuth2 login support
fix( checkout) : prevent double-charge on retry
docs( api) : update endpoint documentation
refactor( db) : extract query builder
chore( deps) : upgrade lodash to 4.17.21
Why It Matters# 1
2
3
4
5
6
7
# Auto-generate changelogs
npx conventional-changelog -p angular -i CHANGELOG.md -s
# Semantic versioning
feat: → minor version bump ( 1.1.0 → 1.2.0)
fix: → patch version bump ( 1.1.0 → 1.1.1)
BREAKING CHANGE: → major version bump ( 1.1.0 → 2.0.0)
Pull Request Best Practices# PR Template# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- .github/pull_request_template.md -->
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing done
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] No new warnings
## Screenshots (if applicable)
Small PRs Win# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Bad: 50 files, 2000 lines
# - Hard to review
# - High chance of bugs
# - Merge conflicts guaranteed
# Good: 5 files, 200 lines
# - Easy to review
# - Quick to merge
# - Low conflict risk
# If feature is big, split it:
# PR 1: Database schema
# PR 2: API endpoints
# PR 3: Frontend components
# PR 4: Integration
Code Review# Review Checklist# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
## Functionality
- [ ] Code does what PR claims
- [ ] Edge cases handled
- [ ] Error handling appropriate
## Code Quality
- [ ] Readable and maintainable
- [ ] No obvious bugs
- [ ] No security issues
- [ ] No performance issues
## Testing
- [ ] Tests cover new code
- [ ] Tests are meaningful
- [ ] No flaky tests added
## Documentation
- [ ] Public APIs documented
- [ ] Complex logic explained
- [ ] README updated if needed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Be specific
❌ "This is wrong"
✅ "This will throw if `user` is null. Add a null check on line 42."
# Explain why
❌ "Use a map here"
✅ "A Map would be O(1) lookup vs O(n) for this array. Important since we iterate 10k+ items."
# Offer solutions
❌ "This is inefficient"
✅ "Consider memoizing this calculation. Here's an example: [code]"
# Distinguish severity
🔴 Blocker: "This SQL injection must be fixed"
🟡 Suggestion: "Consider extracting this to a helper"
🟢 Nitpick: "Typo in variable name (optional to fix)"
Merge Strategies# Merge Commit# 1
git merge feature/login --no-ff
m f a e i a n t u ─ r ─ e ─ ─ ─ ● ─ ─ ● ─ ─ ─ ─ ─ ─ ─ ● ─ ─ ─ ─ ─ ─ ● ● ─ ─ ─ ─ ─ Preserves full history. Good for: Feature branches where history matters.
Squash and Merge# 1
2
git merge feature/login --squash
git commit -m "feat: add login functionality"
m a i n ─ ─ ─ ─ ─ ● ─ ( ─ s ─ q ─ u ─ a ● s ─ h ─ e ─ d ─ ─ f r o m 5 c o m m i t s )
Clean history. Good for: Small features, experimental work.
Rebase and Merge# 1
2
3
4
git checkout feature/login
git rebase main
git checkout main
git merge feature/login --ff-only
m a i n ─ ─ ─ ─ ─ ● ─ ─ ─ ─ ─ ● ( ─ l ─ i ─ n ● e ─ a ─ r ─ ● h ─ i ─ s ─ t ● o ─ r ─ y ─ ) ─ ─
Linear history. Good for: Teams that value clean history.
Handling Conflicts# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# During merge
git merge feature/other
# CONFLICT in file.js
# See what's conflicted
git status
# Open and fix manually, or:
git checkout --theirs file.js # Take their version
git checkout --ours file.js # Take our version
# Mark resolved
git add file.js
git commit
# Abort if stuck
git merge --abort
Prevention# 1
2
3
4
5
6
# Rebase frequently
git fetch origin
git rebase origin/main
# Keep branches short-lived
# Communicate about shared files
Protected Branches# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# GitHub branch protection
branches :
- name : main
protection :
required_pull_request_reviews :
required_approving_review_count : 1
dismiss_stale_reviews : true
required_status_checks :
strict : true
contexts :
- "ci/tests"
- "ci/lint"
enforce_admins : true
restrictions :
users : []
teams : [ "maintainers" ]
CI Integration# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# .github/workflows/pr.yml
name : PR Checks
on :
pull_request :
branches : [ main, develop]
jobs :
test :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- run : npm ci
- run : npm test
lint :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- run : npm ci
- run : npm run lint
build :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- run : npm ci
- run : npm run build
Common Mistakes# 1. Long-Lived Branches# 1
2
3
4
5
6
# Bad: feature branch lives for weeks
# - Diverges from main
# - Massive merge conflicts
# - Integration hell
# Good: merge frequently, use feature flags
2. Force Push to Shared Branches# 1
2
3
4
5
# NEVER on main/develop
git push --force origin main # 💀
# OK on your own feature branch (before review)
git push --force origin feature/my-work
3. Committing Directly to Main# 1
2
3
# Set up protection
gh api repos/{ owner} /{ repo} /branches/main/protection -X PUT \
-f required_pull_request_reviews = '{"required_approving_review_count":1}'
Start Here# Today: Pick a workflow (GitHub Flow for most teams)This week: Set up branch protectionThis month: Add PR template and review guidelinesThis quarter: Automate changelog generationThe best workflow is the one your team actually follows.
Git workflow debates are endless. Pick one, document it, enforce it. Move on to building things.