You've learned Git commands. Now let's see how real development teams actually use Git day to day — from branching strategies to deployments, code reviews, and fixing production bugs at speed.
Introduction
Git commands are one thing. Using Git properly in a real development team is another.
You can know git commit, git push, and git merge perfectly and still feel lost the first time a senior developer says:
"Create a feature branch off
develop, open a PR when it's ready, and don't push directly tomain."
This article bridges that gap.
Whether you are a beginner trying to understand how teams work, or an intermediate developer looking to sharpen your workflow, this guide covers the branching strategies, environments, and team practices that show up in real projects — from small startups to large engineering organisations.
A Note on Real-World Workflows
Every engineering team has its own workflow.
A startup with five engineers may work very differently from a bank with hundreds of developers. The strategies in this article are the most common patterns you will encounter, but do not be surprised if your future team combines ideas from several of them — or has invented their own hybrid entirely.
The goal is not to memorise a strategy. The goal is to understand the reasoning behind each one so you can adapt to any team confidently.
Table of Contents
- Why Branching Matters in Real Projects
- The Common Environments
- How Code Moves Between Environments
- Common Branch Types
- GitHub Flow
- Git Flow
- Trunk-Based Development
- Environment-Based Branching
- Feature Flags
- Pull Requests and Code Reviews
- What Happens After a Merge?
- How This Looks on GitHub
- CI/CD and Branch Protection Rules
- Where Does DevOps Fit?
- A Security Perspective
- Hotfix Scenario: Fixing Production Quickly
- Which Strategy Do Real Companies Use?
- Which Branching Strategy Should Beginners Learn First?
- Common Mistakes Teams Make
- Final Thoughts
1. Why Branching Matters in Real Projects
In a solo project, branching is a good habit.
In a team project, branching is essential.
Without a clear branching strategy, teams run into problems like:
- Two developers overwriting each other's work
- Untested code being deployed directly to users
- A bug fix accidentally breaking an unrelated feature
- No clear way to roll back a bad deployment
- Confusion over which branch is the "source of truth"
A branching strategy is simply an agreed set of rules for how your team creates, names, and merges branches. It answers questions like:
- Where does new feature work start?
- How does code get reviewed before merging?
- How do we push code to production safely?
- What do we do when there is a bug in production right now?
Why main exists
Most tutorials say: "main is production." But why does it exist as a special branch?
The main branch represents the source of truth for your project. In most organisations, every commit on main should be deployable at any moment. That means if someone triggers a deployment of main right now, the application should work correctly for users.
This concept — a deployable branch — is fundamental to understanding why teams protect main so carefully.
💡 Many organisations configure GitHub so that nobody — not even senior engineers — can push directly to
main. All changes must go through a pull request. Do not assume you will always be able to push directly; on most professional teams, you will not.
2. The Common Environments
Before understanding branching strategies, it helps to understand the environments that code typically passes through on its way to users.
Laptop → Sandbox → Dev → QA/Test → Staging → Production
Local Development (Your Laptop)
This is your machine. You write code here, run it, test it, and break things freely. Nothing here affects anyone else.
Sandbox Environment
A personal or isolated environment where a developer can test their work independently before sharing it with the team. Sandboxes are often spun up on demand and torn down afterwards. They are useful for experimenting with infrastructure changes, testing integrations, or working on something that is not ready for the shared dev environment yet.
Development Environment (Dev)
A shared server where developers see each other's work integrated together. Often automatically updated when code is merged into a develop branch. It is not stable and changes frequently throughout the day.
QA / Test Environment
Used by QA engineers or testers to verify that features work correctly and that nothing is broken. More controlled than the dev environment, but still not user-facing.
Staging Environment
A near-identical copy of production. Staging is used for final checks before a release goes live. Stakeholders often review features here. It should behave exactly like production — same data structure, same configuration, same infrastructure where possible.
Production Environment
The live environment that real users interact with. Code here must be stable, tested, and approved. Changes to production are treated with the highest level of care.
Each environment has a higher bar for stability than the last. Code earns its way to production by passing through every gate before it.
3. How Code Moves Between Environments
In most teams, code does not jump directly from a developer's laptop to production. It moves through a deliberate pipeline.
Your laptop
↓
Feature branch (your work in progress)
↓
Pull Request (code review + automated tests)
↓
develop / main (integration)
↓
Sandbox / Dev environment (integration testing)
↓
QA / Test environment (quality assurance)
↓
Staging environment (final review)
↓
Production (live for users)
Each step acts as a quality gate. The further along the pipeline the code moves, the more confidence the team has that it is safe to ship.
In many teams, this movement is automated. When you merge a PR into develop, a CI/CD pipeline may automatically deploy that code to the dev environment. When code reaches main, it may automatically deploy to staging or production.
Understanding this pipeline is just as important as understanding Git commands.
4. Common Branch Types
Most teams use a consistent naming convention for branches. Here are the types you will encounter in real projects:
| Branch | Purpose |
|---|---|
main |
Production-ready code. Always stable and deployable. |
develop |
Integration branch where completed features are merged before release. |
feature/* |
New feature work. Created from develop or main. |
bugfix/* |
Fixing a non-urgent bug found in development or testing. |
hotfix/* |
Urgent fix for a bug in production. Bypasses the normal flow. |
release/* |
Preparing a release. Used for final tweaks before merging to main. |
Naming conventions in practice
Teams often include a ticket or issue number in the branch name for traceability:
feature/AUTH-42-add-oauth-login
bugfix/UI-17-fix-mobile-nav-overlap
hotfix/PROD-99-fix-payment-timeout
release/v2.4.0
This makes it immediately clear what the branch is for, which ticket it relates to, and what kind of change it contains — even months later when someone is reading through the history.
5. GitHub Flow
GitHub Flow is a lightweight, simple branching strategy suited for teams that deploy frequently — sometimes many times a day.
main ──────────────────────────────────────► (always deployable)
│ ▲
└──► feature/login │
│ │
│ commits │
▼ │
Pull Request │
│ │
Code Review │
│ │
CI Checks │
│ │
Approved ────────────────────┘
Merge
│
Production
The rules
-
mainis always deployable - All new work happens on a feature branch created from
main - Open a pull request early, even before the work is finished
- Get the branch reviewed and tested via CI
- Merge into
mainand deploy
In practice
git switch main
git pull
git switch -c feature/add-dark-mode
# do your work
git add .
git commit -m "Add dark mode toggle to settings page"
git push -u origin feature/add-dark-mode
# open a pull request on GitHub
# get it reviewed and approved
# merge and deploy
Who should use it
GitHub Flow works well for small to medium teams, web applications with continuous deployment, open source projects, and teams that want simplicity over ceremony. It is the ideal starting point for beginners joining a real team.
6. Git Flow
Git Flow is a more structured strategy designed for teams with scheduled releases. It was introduced by Vincent Driessen in 2010 and became very influential in enterprise and product teams.
main ──────────────────────────────────► (tagged releases)
▲ ▲
│ │
hotfix/fix ────┘ release/v2.1 ──► develop
│
┌────────────────┤
│ │
feature/login feature/dashboard
The key branches
main — production-ready code only. Tagged with version numbers.
develop — the integration branch. All features merge here first.
feature/* — individual feature branches, created from develop.
release/* — created from develop when preparing a release. Only bug fixes and release prep happen here, no new features.
hotfix/* — created from main for urgent production fixes.
A typical Git Flow lifecycle
# Start a new feature
git switch develop
git switch -c feature/user-profile
git commit -m "Add user profile page"
# Merge back into develop via pull request
git switch develop
git merge feature/user-profile
git branch -d feature/user-profile
# When ready to release
git switch -c release/v2.1.0
git commit -m "Bump version to 2.1.0"
# Merge into main and tag
git switch main
git merge release/v2.1.0
git tag -a v2.1.0 -m "Release version 2.1.0"
# Merge back into develop
git switch develop
git merge release/v2.1.0
Who should use it
Git Flow works well for teams with scheduled versioned releases, mobile or desktop apps going through an approval process, and projects that maintain multiple versions simultaneously. It can feel heavy for small teams or fast-moving web projects, but it provides clear structure for complex release cycles.
7. Trunk-Based Development
Trunk-based development (TBD) is a strategy where all developers commit to a single branch — the trunk, usually main — as frequently as possible, often multiple times a day.
main (trunk)
▲ ▲ ▲ ▲ ▲
│ │ │ │ │
Dev1 Dev2 Dev1 Dev3 Dev2
(short-lived branches merged within hours, not days)
The core principles
- Branches are short-lived — hours or a day at most
- Commits to
mainare small and frequent - Broken builds are fixed immediately — they are the team's top priority
- Feature flags control what users see (more on this below)
Why teams use it
Trunk-based development avoids the painful merge conflicts that come from long-lived branches. When everyone integrates constantly, there is never a large divergence to reconcile at the end of a sprint.
It is the approach favoured by high-performing engineering organisations and is closely tied to mature CI/CD pipelines.
Who should use it
Teams with strong automated test coverage, mature CI/CD tooling, and experience with feature flags. It can be challenging for beginners without these foundations in place.
8. Environment-Based Branching
Some teams structure their branches to directly mirror their deployment environments.
feature/* ──► develop ──► staging ──► main
│ │ │
Dev env Staging env Production
Each branch maps directly to an environment:
| Branch | Environment |
|---|---|
develop |
Development server |
staging |
Staging server |
main |
Production |
Merging a PR into develop automatically deploys to the dev server. Merging into staging deploys to staging. Merging staging into main goes to production.
This gives every environment a clear, always-current state. Developers, QA, and stakeholders know exactly what is deployed where at all times. The trade-off is that code must move through each environment sequentially, which can slow fast-moving teams down.
9. Feature Flags
Feature flags (also called feature toggles) let you deploy code to production without making it visible or active for users.
The code is live in production. The feature is switched off. When the team is ready, they flip the flag — no new deployment needed.
A simple example
if (featureFlags.newDashboard === true) {
renderNewDashboard();
} else {
renderOldDashboard();
}
Why teams use feature flags
- Deploy incomplete features safely — they are hidden from users
- Roll out features to a percentage of users first (gradual rollout)
- Instantly disable a feature if something goes wrong, without a full rollback deployment
- Enable trunk-based development — unfinished work can be merged to
mainwithout affecting users
The trade-off
Feature flags add complexity. Old flags that are never cleaned up become permanent dead code. Teams often track flag debt the same way they track technical debt, and schedule regular cleanup cycles.
10. Pull Requests and Code Reviews
A pull request (PR) — called a merge request (MR) on GitLab — is a formal request to merge one branch into another.
In real teams, almost no code goes directly into main or develop without a pull request. PRs are how teams maintain quality, catch mistakes, and share knowledge across the codebase.
What a good pull request looks like
- Small — focuses on one change. Easier to review and easier to revert.
- Well described — explains what changed, why it changed, and how to test it.
- Linked to a ticket — connects the change to a task in the project tracker.
- Tested — includes or references relevant tests.
A poor PR is large, vague, touches many unrelated files, and is hard to review meaningfully.
The code review process
- Developer opens a PR and assigns reviewers
- Reviewers read the code and leave comments
- Developer addresses feedback and pushes updates
- Reviewers approve when satisfied
- PR is merged
PR etiquette for beginners
- Do not take review comments personally — the goal is better code, not criticism of you
- Respond to every comment, even if just to confirm you have addressed it
- Keep PRs small. A 50-line PR gets reviewed properly. A 2,000-line PR gets rubber-stamped.
- Write a clear description — reviewers should not have to guess what you changed or why
11. What Happens After a Merge?
Many beginners ask: "Okay, I merged. Now what?"
Here is what typically happens after a PR is merged:
✅ Your feature branch is deleted (either automatically or manually)
✅ The CI/CD pipeline triggers automatically
✅ Automated tests run against the merged code
✅ If tests pass, the application is deployed to the appropriate environment (Dev, Staging, or Production — depending on which branch was merged into)
✅ Your teammates pull the latest changes before starting new work
✅ The ticket is marked as done in the project tracker
✅ Development continues on the next task
The merge is not the end of the story — it is the handoff point between development and delivery.
12. How This Looks on GitHub
Many beginners are comfortable with Git in the terminal but are not sure what to do on the GitHub interface. Here is a quick orientation:
Branches — visible under the repository's branch dropdown or the Branches tab. Every branch you push appears here.
Pull Requests — opened from the Pull Requests tab. Once you push a branch, GitHub often shows a prompt to open a PR directly.
Review comments — reviewers leave inline comments on specific lines of code inside the PR. You can reply, resolve, and push new commits to address them — all visible in the PR thread.
CI/CD status — automated test results appear directly in the PR as green checkmarks or red crosses. A PR with failing checks should not be merged until the issues are resolved.
Merge button — once reviews are approved and checks pass, the merge button becomes available. On protected branches, it may be restricted to certain team members.
Branch deletion — after merging, GitHub offers a one-click option to delete the feature branch. Use it. Stale branches are clutter.
Understanding the GitHub interface alongside your terminal workflow is what makes the full Git loop feel complete.
13. CI/CD and Branch Protection Rules
Continuous Integration and Continuous Delivery (CI/CD)
Continuous Integration (CI) — every push triggers an automated pipeline that runs tests, checks code style, and builds the project. If something fails, the team knows immediately.
Continuous Delivery/Deployment (CD) — after tests pass, the code is automatically deployed to an environment.
How CI/CD connects to branching
| Event | Pipeline action |
|---|---|
| Push to any branch | Run tests |
| PR opened | Run tests + linting + security checks |
Merge to develop
|
Deploy to dev/sandbox environment |
Merge to staging
|
Deploy to staging environment |
Merge to main
|
Deploy to production |
Branch Protection Rules
On GitHub, these are configured under Settings → Branches. Common rules for main:
- Require pull request before merging — no direct pushes allowed
- Require approvals — at least one reviewer must approve
- Require status checks to pass — CI tests must pass before merging
- Require branches to be up to date — branch must be current with
main - Restrict who can merge — only certain roles can merge to
main
As a beginner joining a team, you may find that you cannot push to main directly. This is standard practice that protects everyone, including senior developers.
14. Where Does DevOps Fit?
Git is the starting point of the entire modern software delivery pipeline. Here is how a single git push can trigger a full deployment flow in a DevOps environment:
Developer writes code
│
git push
│
GitHub
│
CI Pipeline triggers
│
┌────┴─────────────┐
│ │
Tests run Linting / SAST
│ │
└────────┬─────────┘
│
Security scan
│
Build Docker image
│
Push to container registry
│
Deploy to Dev / Sandbox
│
Deploy to Staging
│
Manual approval (optional)
│
Deploy to Production
Every step in this pipeline is triggered by a Git event — a push, a merge, a tag. This is why branching strategy and DevOps pipeline design are inseparable. The branches you define determine what gets built, tested, and deployed, and when.
Understanding this flow is what takes a developer from "I know Git commands" to "I understand how software ships."
15. A Security Perspective
Git workflows are not just about code quality — they are part of your security posture. These are the practices that security-conscious teams implement:
Protect main — enforce branch protection rules so that no single person, however senior, can push directly to production.
Require pull request reviews — every change to a critical branch should have at least one other set of eyes on it.
Require signed commits — Git allows commits to be cryptographically signed, proving they came from a verified author. This matters in regulated industries.
Enable secret scanning — GitHub's secret scanning automatically detects accidentally committed credentials and alerts you before they are exposed.
Restrict force pushes — git push --force can rewrite history and erase evidence of changes. Disable it on protected branches.
Use least privilege for repository access — not everyone needs write access to every repository. Give team members the minimum permissions they need to do their work.
Audit logs — platforms like GitHub Enterprise provide audit logs of who did what and when. In regulated environments, this is a compliance requirement.
These practices apply whether you are a developer, a DevOps engineer, or a security professional. Git is infrastructure, and infrastructure needs to be secured.
16. Hotfix Scenario: Fixing Production Quickly
A hotfix is an urgent bug fix applied directly to the production codebase, bypassing the normal development flow.
When do you need a hotfix?
- A critical bug is causing errors for live users
- A security vulnerability has been discovered
- A payment or data process is failing
You cannot wait for the next release cycle. You need to fix it now.
The hotfix workflow (Git Flow)
# Start from main (production code)
git switch main
git pull
git switch -c hotfix/fix-payment-timeout
# Make the minimal fix
git add .
git commit -m "Fix payment gateway timeout handling"
# Merge into main and tag
git switch main
git merge hotfix/fix-payment-timeout
git tag -a v2.1.1 -m "Hotfix: payment timeout"
git push origin main --tags
# Merge back into develop so the fix is not lost
git switch develop
git merge hotfix/fix-payment-timeout
git push origin develop
# Clean up
git branch -d hotfix/fix-payment-timeout
The hotfix workflow (GitHub Flow)
git switch main
git pull
git switch -c hotfix/fix-payment-timeout
# make the fix
git push -u origin hotfix/fix-payment-timeout
# open a PR directly into main
# get fast approval from a senior developer
# merge and deploy
Key principles for hotfixes
- Keep the fix minimal — only change what is strictly necessary
- Get a second pair of eyes even under pressure — a rushed fix can introduce a new problem
- Merge the hotfix back into
developimmediately, or it will be lost in the next release - Document what happened — production incidents should be reviewed and learned from
17. Which Strategy Do Real Companies Use?
Theory is useful, but it helps to see how these strategies map to real environments.
| Organisation type | Common strategy |
|---|---|
| Early-stage startup | GitHub Flow |
| SaaS / web product | GitHub Flow or Trunk-Based Development |
| Open source project | GitHub Flow |
| Bank or financial institution | Git Flow or environment-based branching |
| Enterprise software | Git Flow |
| Large tech companies (FAANG) | Trunk-Based Development with feature flags |
| Regulated industry (healthcare, fintech) | Environment-based branching with strict approval gates |
Most mature organisations have evolved their own hybrid. They take the core ideas from these strategies and adapt them to their team size, release cadence, compliance requirements, and tooling.
18. Which Branching Strategy Should Beginners Learn First?
Start with GitHub Flow
GitHub Flow is the most beginner-friendly strategy. It has minimal complexity, maps directly to how GitHub works, and teaches the core loop that underpins all other strategies:
branch → commit → pull request → review → merge → deploy
Once that loop feels natural, everything else is a variation on it.
A simple decision guide
| Your situation | Recommended strategy |
|---|---|
| Solo project or learning | Simple branching or GitHub Flow |
| Small team, deploying often | GitHub Flow |
| Team with scheduled releases | Git Flow |
| Mature team, strong CI/CD | Trunk-Based Development |
| Team with distinct environments | Environment-based branching |
| Regulated or compliance-heavy environment | Git Flow + environment-based branching |
19. Common Mistakes Teams Make
Long-lived feature branches — a branch that lives for two weeks accumulates painful merge conflicts. Keep branches short-lived. Break large features into smaller, mergeable pieces.
Pushing directly to main — without branch protection rules, this can and does happen. Even a small accidental push to main can break production for real users.
Skipping code review under pressure — "We're in a hurry, just merge it." Rushed merges are where most production incidents are born. A 10-minute review often prevents an hour of debugging.
Not merging hotfixes back to develop — the fix goes to production but is overwritten in the next release. Always merge hotfixes back to your integration branch immediately.
Inconsistent branch naming — without conventions, branches become impossible to track. Establish naming standards early and enforce them.
Letting feature flags pile up — flags that are never cleaned up become permanent dead code. Schedule regular flag cleanup as part of your development cycle.
Treating CI failures as optional — a red pipeline that nobody fixes is a pipeline nobody trusts. A failing build should be the team's top priority, not a notification to dismiss.
Ignoring the security basics — no branch protection, no secret scanning, no access controls. These are not optional extras — they are part of a professional Git workflow.
20. Final Thoughts
Branching strategies are not about following rules for their own sake. They exist to answer one practical question: how do we ship good code, safely, as a team?
The specifics will vary. But the underlying principles are consistent across every team and every strategy:
- Protect your production environment
- Review code before it merges
- Keep changes small and frequent
- Automate testing and deployment
- Have a clear plan for when things go wrong
- Treat security as part of the workflow, not an afterthought
Git is not just version control. It is the foundation of modern software delivery. Every pull request, code review, automated test, deployment pipeline, infrastructure change, and production release begins with a Git commit. Understanding Git workflows means understanding how modern software teams build, ship, and maintain reliable systems.
When you join a team and they say "we use trunk-based development with feature flags and deploy to production ten times a day," you will not just nod along. You will understand exactly what they mean, why it works, and how you fit into it.
In the next article, we'll build a complete CI/CD pipeline around these branching strategies using GitHub Actions — so you'll see exactly what happens after you push your code.
Missed the first article? Read Git for Beginners: A Complete Practical Guide to start from the beginning.
Found this helpful? Drop a ❤️ or leave a comment below.
Top comments (0)