
Git Flow vs Trunk Based
Safety (Git Flow) vs Agility (Trunk Based). How often do you deploy?

Safety (Git Flow) vs Agility (Trunk Based). How often do you deploy?
Why does my server crash? OS's desperate struggle to manage limited memory. War against Fragmentation.

Two ways to escape a maze. Spread out wide (BFS) or dig deep (DFS)? Who finds the shortest path?

Fast by name. Partitioning around a Pivot. Why is it the standard library choice despite O(N²) worst case?

Establishing TCP connection is expensive. Reuse it for multiple requests.

First day of my first collaborative project, the senior developer asked:
"We use Git Flow. Branch from
developfor your work."
Me: "What's Git Flow?"
Senior: (sighs) "You've never used Git?"
Me: "I have... just git add, git commit, git push..."
That's when I realized: "Using" Git and "using Git well" are two completely different worlds. It's like knowing how to ride a bicycle doesn't mean you understand city traffic patterns. I only knew the basic Git commands but had zero understanding of team collaboration philosophy.
I moved to a second company. It was a startup.
CTO: "We do Trunk Based Development. Push directly to main."
Me: "Wait, no branches? Isn't that risky?"
CTO: "Tests are automated, we deploy 100 times a day. Branch management is slower."
Same Git, opposite philosophies. My first company used five different branch types, but the second company had only one branch. Both used the same version control system but with completely different approaches. Initially confusing, but this became my catalyst for deeply studying branching strategies.
master, develop, feature, release, hotfix... my head hurtsmain? No conflicts?main break production?Most importantly: "Which should our team use?" I couldn't find answers. Google searches only returned vague responses like "it depends on your situation."
A senior's analogy made everything crystal clear:
"Different scales and risk levels! That's what it was all about."Git Flow = Boeing 747 (Large commercial airplane):
- 2 pilots, 10 crew members, 400 passengers
- 200-item pre-flight checklist
- Fuel check, aircraft inspection, tower clearance...
- Safety first, but 2 hours until departure
- Once airborne, safely transports 400 people
Trunk Based = Electric Scooter:
- Ride alone, leave immediately
- If charged, on the road in under 1 minute
- Fast, but crashes mean immediate injury
- Helmet (test automation) mandatory!
- Easy to change destination, mistakes have limited impact
The Boeing 747 is slow but safe. It's responsible for 400 lives. Meanwhile, the electric scooter is fast but risky. But since you ride alone, mistakes only hurt you. This analogy hit home. Git branching strategies aren't about technology choices—they're about risk management strategies.
master (production)
↓
develop
↓
feature/login
feature/payment
↓
release/v1.0
↓
hotfix/critical-bug
master (or main): Production release version
v1.0.0, v1.0.1)develop: Development main branch
feature/*: Feature development
developdevelop when completefeature/user-login, feature/payment-systemrelease/*: Release preparation
developmaster and develop when completehotfix/*: Emergency bug fixes
mastermaster and develop after fixIf I were building a login feature:
# 1. Create feature branch from develop
git checkout develop
git pull origin develop
git checkout -b feature/login
# 2. Work (1 week)
git commit -m "Add login UI"
git commit -m "Add authentication logic"
git commit -m "Add error handling"
git commit -m "Add unit tests"
# 3. Merge to develop
git checkout develop
git merge feature/login
git push origin develop
git branch -d feature/login
# 4. Release preparation (QA stage)
git checkout -b release/v1.0 develop
# If QA finds bugs, fix them here
git commit -m "Fix login button color"
git commit -m "Fix validation message"
# 5. Deploy
git checkout master
git merge release/v1.0
git tag v1.0.0
git push origin master --tags
# 6. Reflect in develop (includes bugfixes from QA)
git checkout develop
git merge release/v1.0
git push origin develop
Duration: 2 weeks ~ 1 month
When I first saw this process, I thought "Isn't this too complicated?" But after being assigned to a financial sector project, I understood. In environments where a single mistake can lead to financial damage for thousands of people, these validation stages are necessary.
Stability: Multiple validation stages
Concurrent development: 10 people can work on different features simultaneously
Version management: Clear distinction between v1.0, v2.0
Easy hotfixes: Immediate production bug fixes
Complexity: Hard for juniors to understand
Slowness: 2+ weeks per feature
Merge Hell: Many branches lead to conflict nightmare
Excessive process: Even small bugs wait 2 weeks
If I were to summarize, Git Flow is a strategy for "environments where mistakes are unacceptable."
main (= trunk)
├─ short-lived branch (< 1 day)
├─ short-lived branch
└─ short-lived branch
Core principle: Minimize branches, merge fast
# 1. Work on main directly or short branch
git checkout main
git pull
git checkout -b fix-button # optional
# 2. Work (few hours)
git commit -m "Fix button color"
git push origin fix-button
# 3. Merge to main immediately (or immediately after PR approval)
git checkout main
git merge fix-button
git push
git branch -d fix-button
# Or push directly to main (more aggressive teams)
git checkout main
git add .
git commit -m "Fix button"
git push
Duration: Hours ~ 1 day
When I first saw this approach, I thought "Are they crazy?" Push directly to main? Won't production break? But when the CTO showed me the dashboard, my jaw dropped. They were really deploying 100 times per day. With error rate below 0.1%.
Small commits: Even big features split into small pieces merged daily
Feature flags: Merge incomplete features (but hidden)
Fast feedback: CI/CD automatically tests
// Merge incomplete features to main
const PaymentPage = () => {
const { featureFlags } = useFeatureFlags();
if (featureFlags.newPayment) {
return <NewPaymentUI />; // In development (internal testers only)
} else {
return <OldPaymentUI />; // Current (regular users)
}
};
// Control via environment variables
// .env.production
FEATURE_NEW_PAYMENT=false // Regular users see false
// .env.development
FEATURE_NEW_PAYMENT=true // Developers see true
Deploy with featureFlags.newPayment = false to hide it. Once complete, just switch to true. Even gradual rollout is possible:
// Show new feature to only 10% of users
if (featureFlags.newPayment && user.id % 10 === 0) {
return <NewPaymentUI />;
}
When I embraced this pattern, the world looked different. The assumption that "feature completion = code merge" was shattered.
Speed: 100 deploys per day possible
Simplicity: Just one branch
Minimal conflicts: Frequent merges → no big conflicts
True CI: Original meaning of Continuous Integration
Risky: Bugs go straight to production
Tests mandatory: Disaster without automation
Culture required: Entire team must agree
Skill required: Ability to break big features into small pieces
I experienced this transition firsthand at a startup.
Feature development: 1 week
Code review: 2 days
QA: 1 week
Deploy wait: 1 week (until next release cycle)
Total: 3 weeks until user feedback
Problems:
This actually happened. I spent 3 weeks developing a "social login" feature, and when we finally did user testing, the feedback was "Email login is actually more convenient." Three weeks evaporated.
Day 1: Basic UI merged (hidden with Feature Flag)
Day 2: Logic added, merged (only for internal testers)
Day 3: Tests pass, 10% user release
Day 4: User feedback collected (real-time monitoring)
Day 5: Feedback applied, 100% release or rollback
Effects:
When I rebuilt the same "social login" feature with Trunk Based, we got user feedback on Day 3, immediately identified "button placement is weird," and fixed it on Day 4. With Git Flow, we would have learned this 3 weeks later.
# .github/workflows/ci.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: npm install
- name: Run linter
run: npm run lint
- name: Run unit tests
run: npm test
- name: Run integration tests
run: npm run test:integration
- name: Check code coverage
run: npm run coverage
# Block merge if tests fail
- name: Block if failed
if: failure()
run: |
echo "Tests failed! Cannot merge."
exit 1
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to production
run: |
echo "Deploying to production..."
# Deployment scripts for AWS, Vercel, Netlify, etc.
Rule: Test failure = merge blocked! No exceptions!
I once skipped tests and pushed to main:
git push --no-verify # ❌ Dangerous! Ignores pre-commit hook
Reason: "I'm in a hurry... I ran tests locally and they all passed..."
Result:
True cause: Passed locally but production environment variables were different. Would have failed in CI/CD but I skipped it.
Lesson:
--no-verify is betraying teammatesAfter this incident, the team made a rule: "Use --no-verify = buy coffee for everyone." Sounds like a joke but we actually enforced it, and we never had such incidents again.
| Team Size | Recommended | Reason |
|---|---|---|
| 1~3 | Trunk Based | No branch management overhead needed. Everyone knows what everyone else is doing |
| 4~10 | Trunk Based + PR | Code review but merge fast (within 1 day) |
| 10~30 | GitHub Flow | Simplified Git Flow with main + feature branches |
| 30+ | Git Flow | Multiple teams working simultaneously, version management essential |
| Finance/Medical | Git Flow | Safety first. One mistake = legal issues |
This is what I use nowadays:
main (always deployable)
├─ feature/login (PR 1~3 days)
├─ feature/payment (PR 1~3 days)
└─ hotfix/bug (Direct merge or immediate PR)
Rules:
main = always deployable: Can press deploy button anytimeActual workflow:
# 1. Create feature branch (Monday morning)
git checkout -b feature/dark-mode
# 2. Commit continuously while working
git commit -m "Add dark mode toggle button"
git commit -m "Add dark mode styles"
# 3. Create PR (Tuesday morning)
git push origin feature/dark-mode
# Create PR on GitHub
# 4. Code review (Tuesday afternoon)
# Colleague: "LGTM! 👍"
# 5. Merge (Tuesday afternoon)
# Squash and merge or Merge commit
# 6. Auto-deploy (Tuesday evening)
# CI/CD automatically deploys to production
Pros:
CEO: "Competitors launched yesterday, where are we?"
Developer: "In QA. Next week in the release branch..."
CEO: "Next week? We need it right now!"
Developer: "But the process..."
CEO: "😡"
This actually happened at my first startup. A competitor launched a "live chat" feature, and we had already built it but had to wait 2 weeks for the release cycle. We ultimately lost 10 customers to the competitor.
Lesson: Git Flow is overkill for startups. In environments where speed is life, use Trunk Based or GitHub Flow.
# Friday evening 6 PM
git add .
git commit -m "Quick fix"
git push # Push to main without tests
# Friday evening 6:05 PM
"Site's not working!"
"Payment isn't processing!"
"Login button disappeared!"
This happened to my colleague. On a Friday evening, he pushed a "small fix" without testing... ended up working the entire weekend to rollback and fix it.
Lesson: Without automation, Git Flow is safer. "Fast deployment" and "irresponsible deployment" are different.
Week 1: Start feature/big-refactor
Week 2: Continue work (main is 30 commits ahead)
Week 3: Finally done!
Week 3: Attempt merge → 200 conflicts
Week 3: Spend 2 days resolving conflicts
Week 3: Test again → 50 failures
Week 4: Give up and rewrite
This hell was my personal experience. I tried to do a "big refactor" all at once, managed the branch separately for 3 weeks, and when merging, everything collapsed.
Lesson:
Correct approach:
Day 1: Change folder structure (merge)
Day 2: Fix import paths (merge)
Day 3: Rename functions (merge)
Day 4: Optimize logic (merge)
✅ Long deploy cycles (monthly or longer) ✅ Multiple versions maintained simultaneously (v1 support + v2 development) ✅ Large teams (30+ people) ✅ Safety is paramount (finance, medical, infrastructure) ✅ Package software (customers install directly) ✅ Legacy systems (high change impact)
✅ Deploy multiple times per day ✅ Fast experiments, fast fixes (lots of A/B testing) ✅ Perfect CI/CD automation (80%+ test coverage) ✅ Small teams (under 10 people) ✅ SaaS services (can update anytime) ✅ Mature team culture (mutual trust, responsibility)
✅ Middle ground between the two (most teams) ✅ Code review culture (PR mandatory) ✅ Daily to weekly deployments ✅ Startups to mid-sized companies (10~30 people) ✅ Both speed and stability important ✅ Realistic choice (perfect automation difficult)
Git Flow vs Trunk Based is a difference in philosophy, not technology.
Early career (Git Flow): "Why so slow? So frustrating..." Now (GitHub Flow): "Just the right speed."
There's no right answer. Choose what fits your team.Lessons I learned across multiple companies:
One thing is certain:
"Using Git without a branching strategy is like driving without a license."
I'm embarrassed about asking "What's Git Flow?" on my first project, but thanks to that experience, I can now design branching strategies that fit team situations. I hope you find the right strategy for your team.