What Is Git and Git Flow? How To Use It?
February 5, 2023
You're working on a critical feature when a teammate pushes code that breaks everything. Meanwhile, another developer is fixing a production bug, but their changes conflict with yours. This chaos was reality before proper version control strategies.
Git and Git Flow transformed this nightmare into organized collaboration. Let's explore how these tools work and when to use them.
What is Git?
Git is a distributed version control system that fundamentally changed how developers think about code management. Here's where most explanations go wrong - they try to explain Git as a system that tracks file changes. But Git doesn't think about changes at all. Instead, Git thinks in snapshots.
Let's visualize this with a concrete example. Imagine we're building a simple website starting with two files: index.html
and style.css
.
Version 1 Version 2 Version 3
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Project │ │ Project │ │ Project │
│ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │
│ │index.html│ │ + │ │index.html│ │ + │ │index.html│ │
│ │style.css │ │ │ │ (ref v1) │ │ │ │ (ref v1) │ │
│ └──────────┘ │ │ │style.css │ │ │ │style.css │ │
└──────────────┘ │ │ (ref v1) │ │ │ │ (new v3) │ │
│ │about.html│ │ │ │about.html│ │
│ │script.js │ │ │ │ (ref v2) │ │
│ └──────────┘ │ │ │script.js │ │
└──────────────┘ │ │ (ref v2) │ │
│ └──────────┘ │
└──────────────┘
Initial files Add new files Update style.css
Version 1: We create our initial website files - index.html
with our homepage content and style.css
with our initial styling. Git takes a complete snapshot of the project.
Version 2: We expand our website by adding about.html
and script.js
for new functionality. Since index.html
and style.css
are unchanged, Git just references Version 1. Only the new files get stored as fresh content.
Version 3: We modify style.css
to improve the design. index.html
still references Version 1, about.html
and script.js
reference Version 2. Only the updated style.css
gets stored as new content.
Can you see how this is different from tracking individual file changes? Git captures the complete state of your project at each point in time. This is why we can instantly jump to any previous version - Git has the complete picture stored as a snapshot.
The Three States: Where Your Code Lives
In Git, your files can exist in three different states, and understanding this will save you countless headaches.
Working Directory Staging Area (Index) Repository
┌─────────────────┐ ┌────────────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │ Modified │ │ │ │ Staged │ │ │ │ Committed │ │
│ │ Files │ │ │ │ Files │ │ │ │ Snapshots │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │ *.html │ │ │ │ README.md │ │ │ │ v1.0 ────── │ │
│ │ *.css │ │ │ │ style.css │ │ │ │ v1.1 ────── │ │
│ │ *.js │ │ │ │ │ │ │ │ v1.2 ────── │ │
│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │
│ │ │ │ │ │
└─────────────────┘ └────────────────────┘ └─────────────────┘
│ │ │
│ git add <file> │ git commit │
└───────────────────────┼───────────────────────┘
│
"git add ." stages all changes
Working Directory: This is where you actually edit your files. When you open index.html
in your editor and make changes, you're working in the working directory. These changes exist only on your computer until you do something with them.
Index (Git's Staging Area): Think of this as a prep area within Git itself - not to be confused with staging environments like dev/staging/prod. When you're happy with your changes and want to include them in your next snapshot, you add them to the index using git add
. This is like saying "I'm ready to commit these specific changes, but not others."
Repository: This is where Git permanently stores your snapshots. When you run git commit
, Git takes everything in the index and creates a new commit object in the repository.
You might ask "Why have an index at all?" Imagine you've been working on two different features and modified five files. You want to commit the work for Feature A now, but Feature B isn't ready yet. The index lets you selectively choose which changes go into each commit, keeping your project history clean and logical.
What is Git Flow?
Now that we understand how Git works, let's tackle a bigger challenge: How do we organize work when we have multiple developers working on different features, bug fixes, and releases simultaneously?
Consider a typical development scenario:
- One developer is building a new user registration feature
- Another is fixing a critical security bug in production
- You're preparing next month's release
- Your team lead is reviewing and testing features before they go live
How do we prevent these different streams of work from interfering with each other? How do we ensure that urgent bug fixes don't accidentally include half-finished features?
Git Flow provides an answer through a structured branching strategy. It's like having different workspaces for different types of work.
Git Flow Branching Model
Master ●────────●────────●────────●────────●
│ │ │ │ │
│ │ │ │ │
│ │ v1.0 │ v1.1 │ v2.0 │
│ │ │ │ │
│ │ │ │ │
Hotfix │ │ ●────────┘ │
│ │ ╱ │
│ │ ╱ │
│ │ ╱ │
│ │ ╱ │
Release │ ●───╱──────────────────────┘
│ ╱
│ ╱
│ ╱
│ ╱
Develop ●───●────●────●────●────●────●────●
│ │ │ │ │ │ │
│ │ │ │ │ │ │
Feature A │ ●────●────┘ │ │ │
│ ╱ ╱ │ │ │
│ ╱ ╱ │ │ │
Feature B │ ╱ ╱ ●────●────┘
│ ╱ ╱ ╱ ╱
│ ╱ ╱ ╱ ╱
│ ╱ ╱ ╱ ╱
│ ╱ ╱ ╱ ╱
●╱ ╱ ╱ ╱
╱ ╱ ╱
╱ ╱ ╱
╱ ╱ ╱
╱ ╱ ╱
╱ ╱ ╱
╱ ╱ ╱
╱ ╱ ╱
● ╱ ╱
╱ ╱
╱ ╱
╱ ╱
╱ ╱
╱ ╱
╱ ╱
╱ ╱
●────●
Legend:
● = commit/merge point
╱ = branch creation
── = branch continuation
The Five Branch Types: Each with Its Purpose
Let's walk through each branch type in Git Flow and understand when you'd use each one.
Master Branch: Your Production-Ready Code
The master branch represents what's currently running in production. Every commit on master should be stable, tested, and ready for users. Think of it as your "golden copy" - the version that customers actually use. When do we touch master? Only when we're ready to release something to production. We never develop directly on master because we want to keep it stable at all times.
Develop Branch: Where Integration Happens
The develop branch is where we integrate completed features and prepare for the next release. It's like a staging area where we combine different pieces of work to see how they work together. All feature development starts from develop, and when features are complete, they merge back into develop. This branch should generally be stable, but it might occasionally break as we integrate new work.
Feature Branches: Individual Development Workspaces
Here's where the real development happens. When someone starts working on user registration, they create a feature branch called something like feature/user-registration
. This gives them a completely isolated workspace where they can experiment, break things, and iterate without affecting anyone else. Feature branches always branch off from develop and merge back into develop when complete.
Release Branches: Preparing for Production
When we've accumulated enough features in develop and we're ready to prepare a release, we create a release branch like release/1.2.0
. This branch is where we do final testing, bug fixes, and preparation work. Why not release directly from develop? Because while we're preparing release 1.2.0, other developers might be adding features intended for release 1.3.0. The release branch gives us a stable snapshot to polish before going to production.
Hotfix Branches: Emergency Production Fixes
Sometimes production breaks and we need to fix it immediately. We can't wait for the next planned release. That's where hotfix branches come in. Hotfix branches are the only branches that branch directly off master (production). When someone discovers a critical security bug, they create hotfix/security-vulnerability
, fix it, and merge it back to both master and develop.
Your Next Steps
Now that you understand the five branch types and their roles, you have the complete picture of how Git Flow organizes development work. The master and develop branches provide stable foundations, while feature, release, and hotfix branches handle specific types of work without interfering with each other. This structured approach transforms chaotic code collaboration into organized teamwork.
But understanding the theory is just the beginning. The key to successful Git Flow implementation is matching it to your team's specific needs. Use it when you have planned releases, multiple developers, and need to maintain stable production code.
If your team hasn't adopted Git Flow yet, start small - try it on a side project first, then introduce it gradually to your team. Remember, Git Flow is a tool, not a rule. Adapt it to fit your workflow, but ensure everyone on your team understands and follows the same strategy consistently.
Support ExplainThis
If you found this content helpful, please consider supporting our work with a one-time donation of whatever amount feels right to you through this Buy Me a Coffee page, or share the article with your friends to help us reach more readers.
Creating in-depth technical content takes significant time. Your support helps us continue producing high-quality educational content accessible to everyone.