Part 2: Branching, Stash, Merge & Team Collaboration
A Practical Tutorial for Beginners to Advanced Users

In Part 1, we learned the basic Git workflow:
Edit
↓
git status
↓
git add
↓
git commit
↓
git push
That workflow is enough when you're working alone.
But real software development is rarely a one-person job.
A team may have several developers working on different features at the same time. Someone may be fixing a production bug while another developer is building a new feature.
This is where Git branches become extremely important.
In Part 2, we'll learn how to work with branches, temporarily store unfinished work, synchronize with remote repositories, and combine changes safely.
1. Why Do We Need Branches?
Imagine your team is working on a web application.
The current production version is:
main
│
A
│
B
│
C
Now three developers start different tasks:
feature/login
/
main ── A ── B
\
feature/payment
Instead of everyone changing main directly, each developer can work independently.
For example:
main
│
├── feature/login
│
├── feature/payment
│
└── bugfix/database
This reduces the risk of unfinished work affecting the main codebase.
2. What Is a Branch?
A branch is essentially a separate line of development.
Suppose we have:
A ─── B ─── C
Create a feature branch:
A ─── B ─── C
\
D ─── E
D and E are commits made on the feature branch.
The main branch can continue independently.
This gives developers a safe place to experiment, develop, and test changes.
3. Check Your Current Branch
Use:
git branch
Example:
feature/login
* master
The * indicates your current branch.
You can also see local and remote branches:
git branch -a
Example:
* master
feature/login
remotes/origin/master
remotes/origin/feature/login
This distinction becomes important when working with GitHub.
4. Create a New Branch
The modern command for creating and switching to a branch is:
git switch -c feature/login
The -c means:
Create a new branch.
You can verify:
git branch
You might now see:
* feature/login
master
You're now working on feature/login.
5. Switch Between Branches
To move to an existing branch:
git switch master
Then:
git switch feature/login
This is a very common operation.
For example:
Currently:
feature/login
Production issue arrives.
↓
git switch master
Fix production issue.
↓
git switch feature/login
Continue feature development.
But what happens if you have unfinished changes?
That's where git stash becomes useful.
6. git stash — Temporarily Store Your Work
Imagine you're working on a new feature.
You've modified several files, but your work isn't ready to commit.
Suddenly your manager says:
"There's a production issue. Please investigate it immediately."
You don't want to commit unfinished work like:
temporary changes
WIP
test
fix later
Instead:
git stash
Git temporarily stores your uncommitted changes.
Your working directory becomes clean.
Now you can switch branches:
git switch master
Work on the urgent issue.
When you're ready to return:
git switch feature/login
Check your saved work:
git stash list
Example:
stash@{0}: WIP on feature/login
Restore it:
git stash pop
Your unfinished changes return.
7. The Stash Workflow
The whole process looks like this:
Working on feature
│
│ unfinished changes
↓
git stash
│
↓
Working directory becomes clean
│
↓
Switch to another branch
│
↓
Fix urgent issue
│
↓
Return to feature branch
│
↓
git stash pop
│
↓
Continue your work
This is especially useful for developers and DevOps engineers who frequently need to switch between tasks.
8. git fetch — See What's Happening on the Remote
Your local repository and GitHub repository can change independently.
For example:
Your computer:
A ─── B
GitHub:
A ─── B ─── C
Your local repository doesn't automatically have commit C.
Run:
git fetch origin
Git downloads information about the remote changes.
Importantly, fetch does not automatically change your current working branch.
This makes it useful when you want to inspect remote changes before deciding what to do.
9. git pull — Bring Remote Changes Into Your Work
If you're ready to update your current branch:
git pull
Conceptually:
git pull
=
fetch + integrate
For example:
GitHub
│
│ git pull
↓
Your local branch
A common workflow is:
git pull
# make changes
git add .
git commit -m "update configuration"
git push
10. git push for a New Branch
When you create a branch locally:
git switch -c feature/login
the branch doesn't automatically exist on GitHub.
Push it:
git push -u origin feature/login
The -u establishes an upstream relationship.
After that, you can usually just use:
git push
and Git knows where the branch should be pushed.
11. Local Branch vs Remote Branch
This is an important concept.
You might have:
Local:
feature/login
and:
Remote:
origin/feature/login
They are related, but they aren't the same thing.
Think of it as:
Your Computer
│
│
feature/login
│
│ git push
↓
GitHub
│
origin/feature/login
This is why:
git branch
and:
git branch -a
can show different information.
12. Merging a Branch
Suppose you've finished your feature.
Your history looks like:
D ─── E
/
A ─── B ─── C
You want to bring the feature into master.
First switch to master:
git switch master
Then:
git merge feature/login
Git combines the feature branch with master.
The result may look like:
A ─── B ─── C ─── D ─── E
or Git may create a merge commit depending on the branch history and merge strategy.
13. Why Do We Merge Into the Target Branch?
This is an easy mistake for beginners.
If you want:
feature/login
↓
master
you must first switch to:
master
Then run:
git merge feature/login
In other words:
The branch you are currently on is the branch receiving the changes.
So:
git switch master
git merge feature/login
means:
"Merge
feature/loginintomaster."
14. What Is a Merge Conflict?
Sometimes Git cannot automatically combine two branches.
For example, master contains:
server_port=8080
and the feature branch contains:
server_port=9090
Both branches changed the same line.
Git doesn't know which value is correct.
So:
git merge feature/login
may produce a conflict.
Git might put something like this into the file:
<<<<<<< HEAD
server_port=8080
=======
server_port=9090
>>>>>>> feature/login
This is Git saying:
Your current branch
↓
<<<<<<< HEAD
server_port=8080
=======
Incoming branch
↓
server_port=9090
>>>>>>> feature/login
Git needs a human to decide the correct result.
We'll cover conflict resolution in detail in Part 3.
15. git merge --squash
Sometimes a feature branch has many small commits:
add login
fix login
fix validation
fix typo
fix validation again
final fix
You may not want all of these development commits appearing individually in your main branch.
You can use:
git merge --squash feature/login
This collects the changes from the feature branch without creating the normal merge commit.
Then you create one clean commit:
git commit -m "add login functionality"
The result is a cleaner history.
Conceptually:
Before:
A
\
B
C
D
E
F
After squash:
A ─── G
where G represents the complete feature.
16. Why Squash Can Be Useful
During development, it's normal to create messy commits:
test
fix
oops
fix again
update
final
really final
That's okay.
Your feature branch is your workspace.
But the main branch may benefit from a cleaner history:
add authentication
add payment processing
fix database connection
improve monitoring
This makes the project history easier to understand.
17. A Realistic Team Workflow
Let's imagine you're working on a DevOps project.
The main branch contains the stable infrastructure configuration.
You receive a task:
Add system optimization configuration.
Start from the latest master:
git switch master
git pull
Create your feature branch:
git switch -c feature/system-optimization
Create your file:
kernel_tuning.txt
Check:
git status
Stage:
git add kernel_tuning.txt
Commit:
git commit -m "add kernel tuning notes"
Push:
git push -u origin feature/system-optimization
Now the branch exists on GitHub.
After review, you can merge it into master.
18. What GUI Users Are Actually Doing
Suppose you're using GitHub Desktop.
You click:
Create Branch
Equivalent concept:
git switch -c feature/system-optimization
You click:
Commit
Equivalent:
git add .
git commit -m "add kernel tuning notes"
You click:
Push
Equivalent:
git push
You click:
Merge
Equivalent concept:
git merge feature/system-optimization
Understanding these commands makes Git GUI tools much less mysterious.
19. A Simple Branching Strategy
For a small or medium-sized team, you might see something like:
main
│
├── feature/login
├── feature/payment
├── feature/monitoring
└── bugfix/database
The important principle is:
Keep the main branch stable and use branches for isolated work.
Teams may use different Git strategies—GitHub Flow, Git Flow, trunk-based development, etc.—depending on their environment.
The commands remain largely the same.
20. The Commands You Should Practice
For this part, don't just read the commands.
Create a small practice repository and run:
git branch
git branch -a
git switch -c feature/test
git switch master
git stash
git stash list
git stash pop
git fetch
git pull
git push -u origin feature/test
git merge feature/test
And finally:
git merge --squash feature/test
Don't worry if some of these commands don't make complete sense yet.
The goal is to become familiar with the workflow.
21. Part 2 Cheat Sheet
Command | Purpose |
|---|---|
| List local branches |
| List local and remote branches |
| Switch branches |
| Create and switch to a branch |
| Temporarily save unfinished changes |
| View saved stashes |
| Restore a stash |
| Download remote information |
| Fetch and integrate remote changes |
| Send commits to remote |
| Push a new branch and set upstream |
| Merge another branch |
| Combine branch changes for one clean commit |
Final Thoughts
Branches are one of the reasons Git became so powerful for team development.
Instead of everyone working directly on the same codebase:
Everyone → main
we can work independently:
feature/login
/
main ────────┼── feature/payment
\
bugfix/database
Each person can develop, test, review, and eventually integrate their work.
And when you need to temporarily stop one task and work on another:
git stash
becomes your safety net.
The most important workflow to remember from this part is:
git pull
↓
git switch -c feature/my-task
↓
Make changes
↓
git status
↓
git add
↓
git commit
↓
git push -u origin feature/my-task
↓
Code Review
↓
Merge
Once you understand this workflow, you're no longer just using Git to save files.
You're using Git to collaborate safely with a team.
Coming Next: Part 3 — When Git Goes Wrong
Everything is easy when Git works perfectly.
But sooner or later, you'll see:
CONFLICT
or accidentally reset the wrong commit, lose track of a branch, or find yourself wondering:
"Where did my commit go?"
Don't panic.
In Part 3, we'll learn the Git commands that every developer and DevOps engineer should know for troubleshooting and recovery:
git merge conflicts → git log --graph → git log -p → git show → git blame → git reset → git reflog
That's where Git gets really interesting.