When working in a Git-based development team, especially in real-world projects, understanding how to manage branches and history is essential. This post explains the practical use of merge
, rebase
, and squash
, as well as how to use demo
or staging
branches for safer and more flexible workflows.
A git merge
preserves full commit history by combining branches using a new merge commit. This creates a non-linear history with visible branch structure.
* Merge branch 'feature/login'
|\
| * Add login UI
| * Hook up auth
* | Update README
|/
* Initial commit
git rebase
moves your feature branch commits on top of the latest main
, effectively rewriting history to make it look like your work was created linearly.
* Add login UI
* Hook up auth
* Update README
* Initial commit
Squashing combines all your commits into a single one during merge (e.g. GitHub's "Squash and merge").
* Add login feature (squashed)
* Update README
* Initial commit
When main
has moved ahead and your feature branch is behind, you must resolve conflicts before merging.
main
into your feature branchgit checkout feature/login
git merge origin/main
✅ Safe, preserves history
❌ Will create a merge commit
main
git checkout feature/login
git rebase origin/main
✅ Cleaner history
⚠️ Requires force-push if already pushed
Always resolve conflicts inside your feature branch, not on
main
.
Git has no way to know if your conflict resolution is logically wrong. If you accidentally delete part of a previously merged feature during rebase/merge, Git will accept it as valid. That’s why it's important to:
git diff
/ git log -p
)demo
or staging
BranchMany teams use a branch like demo
, staging
, or dev
as an intermediate testing environment.
main
git checkout demo
git merge feature/login
git merge feature/auth
If a feature is later rejected, you can simply reset demo
:
git checkout demo
git reset --hard origin/main
✅ Keeps main
clean
✅ Allows testing in parallel
demo
back into main
main
from their respective branchesStrategy | History | Keeps Commits? | Clean? | Safe on Shared Branch? |
---|---|---|---|---|
Merge | Non-linear | ✅ Yes | ❌ | ✅ Yes |
Rebase | Linear | ✅ Yes | ✅ | ⚠️ Risky if shared |
Squash | Linear | ❌ No | ✅✅ | ✅ Yes |
When used wisely, these strategies give you the best of both worlds: clean, readable history and safe, flexible workflows.
If you're managing features across multiple environments, introducing a demo
or staging
branch lets you test without polluting your production history.
Use merge
for safety, rebase
for clarity, and squash
for simplicity. Just be deliberate — and communicate with your team.