Git branching strategies are how teams coordinate code changes without stepping on each other’s toes.
Let’s see Trunk-Based Development in action. Imagine a small team working on a web app.
# Developer A starts a small feature
git checkout main
git pull origin main
git checkout -b feature/user-profile-display
# ... make small, focused changes ...
git add .
git commit -m "Feat: Add basic user profile display"
git push origin feature/user-profile-display
# Developer B starts a quick bug fix
git checkout main
git pull origin main
git checkout -b fix/login-bug
# ... make small, focused changes ...
git add .
git commit -m "Fix: Correct login redirect issue"
git push origin fix/login-bug
Now, both developers want to merge their work back into main.
# Developer A merges their feature
git checkout main
git pull origin main
git merge --no-ff feature/user-profile-display
git push origin main
# Developer B merges their fix
git checkout main
git pull origin main
git merge --no-ff fix/login-bug
git push origin main
In Trunk-Based Development, main (or "trunk") is always production-ready. Developers create short-lived branches for features or fixes, integrate them into main frequently (multiple times a day is common), and rely on robust automated testing to catch regressions. The key is small, incremental changes and continuous integration.
Trunk-Based Development is the simplest strategy. It prioritizes speed and continuous integration. Developers work on a single main branch, or create very short-lived feature branches that are merged back into main quickly. The core idea is that main is always deployable.
GitFlow is a more structured approach, often used in projects with scheduled releases and multiple environments (development, staging, production). It uses several types of branches:
main: Represents production-ready code.develop: Represents the latest delivered development changes.feature/*: For developing new features. Branches are created fromdevelopand merged back intodevelop.release/*: For preparing a production release. Branches are created fromdevelop, bugs are fixed here, and then merged into bothmainanddevelop.hotfix/*: For urgent production fixes. Branches are created frommain, fixed, and merged into bothmainanddevelop.
GitHub Flow is a simpler, streamlined workflow often used for web applications.
mainis deployable.- Create a descriptive branch for new work (e.g.,
add-user-authentication). - Open a Pull Request (PR) when the work is ready for review.
- Discuss and review the code. Automated tests run on the PR.
- Once approved and tests pass, merge the PR into
main. - Deploy
mainimmediately.
The most surprising true thing about Git branching strategies is that the "best" one is entirely dependent on your team’s size, project complexity, release cadence, and tolerance for risk. What works for a solo developer building a personal project will likely be disastrous for a large enterprise team maintaining a critical banking system.
Here’s how it looks in practice with GitFlow:
# Start a new feature
git checkout develop
git pull origin develop
git checkout -b feature/new-reporting-module
# ... work on the feature ...
git add .
git commit -m "Feat: Implement basic reporting structure"
git push origin feature/new-reporting-module
# Later, a release is planned
git checkout develop
git pull origin develop
git checkout -b release/v1.2.0
# Fix bugs found during release testing
git checkout release/v1.2.0
# ... fix bugs ...
git commit -m "Fix: Correct data aggregation in reporting"
git push origin release/v1.2.0
# Merge release branch into main and develop
git checkout main
git pull origin main
git merge --no-ff release/v1.2.0
git push origin main
git checkout develop
git pull origin develop
git merge --no-ff release/v1.2.0
git push origin develop
The one thing most people don’t realize is how much overhead the more complex strategies like GitFlow introduce. Creating, merging, and managing multiple long-lived branches (develop, feature/*, release/*, hotfix/*) can become a significant administrative burden. The potential for merge conflicts increases dramatically with more active branches and longer-lived feature branches, often requiring dedicated effort just to keep branches synchronized. This complexity can slow down development velocity if not managed meticulously.
The next concept to explore is how to manage merge conflicts effectively when they inevitably arise.