Branching & Merging
TL;DR — Quick Summary
- Branches are lightweight pointers to commits — creating one takes milliseconds and copies no files.
- Workflow:
git checkout -b feature/name→ commit →git checkout main→git merge feature/name. - Merge conflicts happen when two branches edit the same lines — resolve by editing the file, staging, and committing.
HEADis Git's pointer to your current location (usually your current branch).
Lesson Overview
🌿 Branches: Parallel Universes for Your Code
A branch in Git is an ultra-lightweight pointer to a specific commit. Creating a branch doesn't copy your files — it just creates a new label that can move independently as you make new commits. This is what makes Git branches so fast and cheap to create.
The default branch is called main (historically master). You should think of main as the source of truth — the stable, working, deployable version of your product.
🧠 Why Branch?
- Isolation: Work on a new feature without touching working code.
- Experimentation: Try a risky idea — if it fails, just delete the branch.
- Parallel work: Multiple developers work on different features simultaneously.
- Clean history: Each branch tells the story of one feature or fix.
🔀 Merging
When your branch is ready, you merge it back into main. Git has two main merge strategies:
- Fast-forward merge: If
mainhasn't changed since you branched off, Git simply moves the pointer forward. No merge commit is created — history is linear. - Three-way merge: If both branches have new commits, Git finds the common ancestor and combines the changes, creating a new merge commit.
⚔️ Merge Conflicts
A merge conflict happens when two branches both changed the same lines of the same file. Git can't automatically decide which version is correct, so it pauses and asks you to resolve it manually.
Conflicts are not errors — they are Git asking for your judgment. Every developer faces them regularly.
Conceptual Deep Dive
main timeline is the official story. When you start a feature, you branch off into a new timeline. In this timeline, you can do whatever you want without affecting the original story. When your timeline's story arc is complete, you merge it back — the two timelines join and move forward as one.
The HEAD pointer is simply Git's way of tracking which branch you're currently on. When you commit, HEAD moves forward with your current branch, leaving all other branches exactly where they were.Implementation Lab
# See all existing branches (* marks the current one)
git branch
# * main
# Create a new branch AND switch to it immediately
git checkout -b feature/user-authentication
# Modern equivalent:
git switch -c feature/user-authentication
# Verify you switched
git branch
# main
# * feature/user-authentication
# Do your work and make commits on this branch
git add auth.js
git commit -m "Add JWT token generation"JWT token generation"
git add login.html
git commit -m "Add login form UI"UI"
# Switch back to main
git checkout main
# (main is untouched — your feature commits are only on the feature branch)
# Merge your feature into main
git merge feature/user-authentication
# Output: Merge made by the 'recursive' strategy.
# Delete the branch (it's been merged — no longer needed)
git branch -d feature/user-authentication
# Force delete a branch (even if NOT merged — be careful!)
git branch -D abandoned-experiment# Attempt a merge that has conflicts
git merge feature/redesign-navbar
# CONFLICT (content): Merge conflict in src/navbar.js
# Automatic merge failed; fix conflicts and then commit.
# Step 1: See which files have conflicts
git status
# both modified: src/navbar.js
# Step 2: Open src/navbar.js — it looks like this:
# <<<<<<< HEAD
# const navHeight = 60;
# =======
# const navHeight = 80;
# >>>>>>> feature/redesign-navbar
# Step 3: Edit the file to keep what you want:
# const navHeight = 80; (you decide 80 is correct)
# Remove ALL the conflict markers (<<<, ===, >>>)
# Step 4: Mark the conflict as resolved by staging
git add src/navbar.js
# Step 5: Complete the merge with a commit
git commit -m "Merge feature/redesign-navbar — use navbar height 80px"
# Tip: abort a conflict mid-resolution to start fresh
git merge --abort# See a text-based graph of branch history
git log --oneline --graph --all
# Output:
# * a4f1e23 (HEAD -> main) Merge feature/user-auth
# |\
# | * c3d2b11 (feature/user-auth) Add login form UI
# | * b2a1f00 Add JWT token generation
# |/
# * 9e8d7c6 Initial project setup
# Useful aliases to add to your git config:
git config --global alias.graph "log --oneline --graph --all --decorate"
# Now just run: git graphPro Tips — Senior Dev Insights
Use git stash to save your uncommitted work before switching branches — then git stash pop to restore it.
Before merging a long-lived feature branch, first update it with git merge main from your feature branch to resolve conflicts in a safe environment.
git diff main...feature/branch shows you exactly what your feature branch changed compared to where it forked from main.
Set up branch protection rules on GitHub so nobody (not even you) can push directly to main — everything must go through a Pull Request.
Common Developer Pitfalls
main for new features — this makes it impossible to review, test, or reject changes without affecting the whole team.fix, test2, johns-branch — use clear names like bugfix/null-pointer-login.main before merging — you might accidentally merge into the wrong branch.git branch -d to keep your branch list readable.Interview Mastery
git merge combines two branches by creating a new merge commit, preserving the full history of both branches. git rebase moves your branch's commits to the tip of another branch, rewriting them with new hashes, resulting in a linear history. Merge is safer for shared branches; rebase is preferred for cleaning up local feature branches before merging. Golden rule: never rebase a branch others are working on.
A merge conflict occurs when two branches both modified the same lines of the same file and Git can't automatically determine the correct version. To resolve: (1) run git status to find conflicted files, (2) open each file and look for conflict markers (<<<<<<<, =======, >>>>>>>), (3) edit the file to keep the correct content and remove all markers, (4) git add the resolved file, (5) git commit to complete the merge.
HEAD is a special pointer that tells Git where you currently are in the repository — typically pointing to your current branch. When you make a commit, that branch's pointer (and HEAD) moves forward to the new commit. When you git checkout a different branch, HEAD moves to point at that branch. A 'detached HEAD' state means HEAD points directly to a commit, not a branch.
Real-World Blueprint
feature/payment-gateway, Developer B is on feature/dark-mode, Developer C is on bugfix/checkout-crash. All three work simultaneously. When C's bugfix is done, it gets merged to main and deployed as a hotfix within minutes — without waiting for A or B to finish their features. Branching made this instant, independent deployment possible.Hands-on Lab Exercises
main, then create a feature/hello branch, add 2 commits, and merge back into main.Intentionally create a merge conflict: edit the same line of a file on two different branches, then merge them and resolve the conflict.
git log --oneline --graph --all after merging to visualize your branch history.git switch -c → work → commits → git switch main → git merge → git branch -d.Real-World Practice Scenarios
You're halfway through a feature on your branch when your manager asks you to urgently fix a production bug. How do you handle this without losing your feature work?
README.md on different branches. When you merge, you get a conflict. Walk through exactly what you'd do.main without branching. What problems might this cause for the rest of the team?main by 40 commits. What's your strategy for merging without massive conflicts?Branching & Merging
TL;DR — Quick Summary
- Branches are lightweight pointers to commits — creating one takes milliseconds and copies no files.
- Workflow:
git checkout -b feature/name→ commit →git checkout main→git merge feature/name. - Merge conflicts happen when two branches edit the same lines — resolve by editing the file, staging, and committing.
HEADis Git's pointer to your current location (usually your current branch).
Overview
🌿 Branches: Parallel Universes for Your Code
A branch in Git is an ultra-lightweight pointer to a specific commit. Creating a branch doesn't copy your files — it just creates a new label that can move independently as you make new commits. This is what makes Git branches so fast and cheap to create.
The default branch is called main (historically master). You should think of main as the source of truth — the stable, working, deployable version of your product.
🧠 Why Branch?
- Isolation: Work on a new feature without touching working code.
- Experimentation: Try a risky idea — if it fails, just delete the branch.
- Parallel work: Multiple developers work on different features simultaneously.
- Clean history: Each branch tells the story of one feature or fix.
🔀 Merging
When your branch is ready, you merge it back into main. Git has two main merge strategies:
- Fast-forward merge: If
mainhasn't changed since you branched off, Git simply moves the pointer forward. No merge commit is created — history is linear. - Three-way merge: If both branches have new commits, Git finds the common ancestor and combines the changes, creating a new merge commit.
⚔️ Merge Conflicts
A merge conflict happens when two branches both changed the same lines of the same file. Git can't automatically decide which version is correct, so it pauses and asks you to resolve it manually.
Conflicts are not errors — they are Git asking for your judgment. Every developer faces them regularly.
Deep Dive Analysis
Think of branches like parallel timelines in a movie. The <code>main</code> timeline is the official story. When you start a feature, you branch off into a new timeline. In this timeline, you can do whatever you want without affecting the original story. When your timeline's story arc is complete, you merge it back — the two timelines join and move forward as one. The <code>HEAD</code> pointer is simply Git's way of tracking <em>which branch you're currently on</em>. When you commit, <code>HEAD</code> moves forward with your current branch, leaving all other branches exactly where they were.
Implementation Reference
# See all existing branches (* marks the current one)
git branch
# * main
# Create a new branch AND switch to it immediately
git checkout -b feature/user-authentication
# Modern equivalent:
git switch -c feature/user-authentication
# Verify you switched
git branch
# main
# * feature/user-authentication
# Do your work and make commits on this branch
git add auth.js
git commit -m "Add JWT token generation"
git add login.html
git commit -m "Add login form UI"
# Switch back to main
git checkout main
# (main is untouched — your feature commits are only on the feature branch)
# Merge your feature into main
git merge feature/user-authentication
# Output: Merge made by the 'recursive' strategy.
# Delete the branch (it's been merged — no longer needed)
git branch -d feature/user-authentication
# Force delete a branch (even if NOT merged — be careful!)
git branch -D abandoned-experiment# Attempt a merge that has conflicts
git merge feature/redesign-navbar
# CONFLICT (content): Merge conflict in src/navbar.js
# Automatic merge failed; fix conflicts and then commit.
# Step 1: See which files have conflicts
git status
# both modified: src/navbar.js
# Step 2: Open src/navbar.js — it looks like this:
# <<<<<<< HEAD
# const navHeight = 60;
# =======
# const navHeight = 80;
# >>>>>>> feature/redesign-navbar
# Step 3: Edit the file to keep what you want:
# const navHeight = 80; (you decide 80 is correct)
# Remove ALL the conflict markers (<<<, ===, >>>)
# Step 4: Mark the conflict as resolved by staging
git add src/navbar.js
# Step 5: Complete the merge with a commit
git commit -m "Merge feature/redesign-navbar — use navbar height 80px"
# Tip: abort a conflict mid-resolution to start fresh
git merge --abort# See a text-based graph of branch history
git log --oneline --graph --all
# Output:
# * a4f1e23 (HEAD -> main) Merge feature/user-auth
# |\
# | * c3d2b11 (feature/user-auth) Add login form UI
# | * b2a1f00 Add JWT token generation
# |/
# * 9e8d7c6 Initial project setup
# Useful aliases to add to your git config:
git config --global alias.graph "log --oneline --graph --all --decorate"
# Now just run: git graphCommon Pitfalls
- •Committing directly to <code>main</code> for new features — this makes it impossible to review, test, or reject changes without affecting the whole team.
- •Naming branches vaguely: <code>fix</code>, <code>test2</code>, <code>johns-branch</code> — use clear names like <code>bugfix/null-pointer-login</code>.
- •Forgetting to switch back to <code>main</code> before merging — you might accidentally merge into the wrong branch.
- •Leaving merged branches around indefinitely — clean up with <code>git branch -d</code> to keep your branch list readable.
Key Takeaways
Hands-on Practice
- ✓Create a repo with 2 commits on <code>main</code>, then create a <code>feature/hello</code> branch, add 2 commits, and merge back into <code>main</code>.
- ✓Intentionally create a merge conflict: edit the same line of a file on two different branches, then merge them and resolve the conflict.
- ✓Run <code>git log --oneline --graph --all</code> after merging to visualize your branch history.
- ✓Practice the full cycle: <code>git switch -c</code> → work → commits → <code>git switch main</code> → <code>git merge</code> → <code>git branch -d</code>.
Expert Pro Tips
Interview Preparation
Q: What is the difference between git merge and git rebase?
Master Answer:
<code>git merge</code> combines two branches by creating a new <strong>merge commit</strong>, preserving the full history of both branches. <code>git rebase</code> moves your branch's commits to the tip of another branch, rewriting them with new hashes, resulting in a <strong>linear history</strong>. Merge is safer for shared branches; rebase is preferred for cleaning up local feature branches before merging. Golden rule: <em>never rebase a branch others are working on</em>.
Q: What is a merge conflict and how do you resolve one?
Master Answer:
A merge conflict occurs when two branches both modified the same lines of the same file and Git can't automatically determine the correct version. To resolve: (1) run <code>git status</code> to find conflicted files, (2) open each file and look for conflict markers (<code><<<<<<<</code>, <code>=======</code>, <code>>>>>>>></code>), (3) edit the file to keep the correct content and remove all markers, (4) <code>git add</code> the resolved file, (5) <code>git commit</code> to complete the merge.
Q: What does HEAD mean in Git?
Master Answer:
<code>HEAD</code> is a special pointer that tells Git <em>where you currently are</em> in the repository — typically pointing to your current branch. When you make a commit, that branch's pointer (and HEAD) moves forward to the new commit. When you <code>git checkout</code> a different branch, HEAD moves to point at that branch. A 'detached HEAD' state means HEAD points directly to a commit, not a branch.
Industrial Blueprint
"At a tech company, the team uses a branch-per-feature workflow. Developer A is on <code>feature/payment-gateway</code>, Developer B is on <code>feature/dark-mode</code>, Developer C is on <code>bugfix/checkout-crash</code>. All three work simultaneously. When C's bugfix is done, it gets merged to <code>main</code> and deployed as a hotfix within minutes — without waiting for A or B to finish their features. Branching made this instant, independent deployment possible."
Simulated Scenarios
© 2026 DevHub Engineering • All Proprietary Rights Reserved
Generated on March 7, 2026 • Ver: 4.0.2
Document Class: Master Education
Confidential Information • Licensed to User