Hands-on Lab TP3 — Branches, Merge & Conflict Resolution
Hands-on Lab 60 min Module 02
Objectives
By the end of this lab, you will have:
- Created and managed multiple branches
- Performed fast-forward and 3-way merges
- Intentionally created and resolved a merge conflict
- Used interactive rebase to clean up history
- Applied a Git workflow to a simulated project
Part 1: Branch Management
mkdir git-tp3-branches
cd git-tp3-branches
git init
Create app.py with the initial content:
class ShoppingCart:
def __init__(self):
self.items = []
def add_item(self, name, price):
self.items.append({"name": name, "price": price})
def total(self):
return sum(item["price"] for item in self.items)
Create README.md:
# Shopping Cart App
Simple shopping cart implementation in Python.
git add .
git commit -m "feat: initial shopping cart class"
Create Feature Branches
git switch -c feature/discounts
git branch # Verify you're on feature/discounts
Add these methods to app.py (inside the class):
def apply_discount(self, percent):
"""Apply a percentage discount to the total."""
return self.total() * (1 - percent / 100)
def apply_coupon(self, code):
"""Apply a coupon code."""
coupons = {"SAVE10": 10, "SAVE20": 20}
percent = coupons.get(code, 0)
return self.apply_discount(percent)
git add app.py
git commit -m "feat(cart): add percentage discount method"
git add app.py
git commit -m "feat(cart): add coupon code support"
git switch main
git switch -c feature/tax
Add these tax methods to app.py:
def calculate_tax(self, rate=0.20):
"""Calculate tax amount on total."""
return self.total() * rate
def total_with_tax(self, rate=0.20):
"""Get total including tax."""
return self.total() + self.calculate_tax(rate)
git add app.py
git commit -m "feat(cart): add tax calculation methods"
View Branch Structure
git log --oneline --graph --all
# Should show: main, feature/discounts, feature/tax
Part 2: Fast-Forward Merge
git switch main
git merge feature/tax
git log --oneline --graph --all
# Notice: no merge commit, linear history
git branch -d feature/tax
git log --oneline --graph --all
Part 3: Three-Way Merge
Add this to README.md:
## Installation
```bash
pip install -r requirements.txt
```bash
git add README.md
git commit -m "docs: add installation instructions"
git merge feature/discounts
git log --oneline --graph --all
# You can see the merge commit with 2 parents
Part 4: Intentional Conflict
git switch -c branch-alice
Replace the entire app.py with Alice's version:
class ShoppingCart:
def __init__(self, currency="USD"):
self.items = []
self.currency = currency # Alice adds currency
def add_item(self, name, price):
self.items.append({"name": name, "price": price})
def total(self):
return sum(item["price"] for item in self.items)
def format_total(self):
symbols = {"USD": "$", "EUR": "€", "GBP": "£"}
symbol = symbols.get(self.currency, "$")
return f"{symbol}{self.total():.2f}"
git add app.py
git commit -m "feat: Alice adds currency support"
git switch main
git switch -c branch-bob
Replace app.py with Bob's version:
class ShoppingCart:
def __init__(self, owner="anonymous"):
self.items = []
self.owner = owner # Bob adds owner
def add_item(self, name, price, quantity=1):
self.items.append({"name": name, "price": price, "qty": quantity})
def total(self):
return sum(item["price"] * item["qty"] for item in self.items)
def summary(self):
return f"Cart for {self.owner}: ${self.total():.2f}"
git add app.py
git commit -m "feat: Bob adds owner and quantity support"
git switch main
git merge branch-alice
# Now merge Bob's work: CONFLICT!
git merge branch-bob
cat app.py
git status
Resolve the Conflict
Edit app.py to combine both features:
class ShoppingCart:
def __init__(self, owner="anonymous", currency="USD"):
self.items = []
self.owner = owner # From Bob
self.currency = currency # From Alice
def add_item(self, name, price, quantity=1):
self.items.append({"name": name, "price": price, "qty": quantity})
def total(self):
return sum(item["price"] * item["qty"] for item in self.items)
def format_total(self):
symbols = {"USD": "$", "EUR": "€", "GBP": "£"}
symbol = symbols.get(self.currency, "$")
return f"{symbol}{self.total():.2f}"
def summary(self):
return f"Cart for {self.owner}: {self.format_total()}"
git add app.py
git commit -m "merge: combine Alice's currency and Bob's owner/quantity features"
git branch -d branch-alice
git branch -d branch-bob
git log --oneline --graph --all
Part 5: Interactive Rebase
git switch -c feature/checkout
Create checkout.py:
def start_checkout(cart):
print("Starting checkout...")
git add checkout.py
git commit -m "WIP checkout"
echo " cart.validate()" >> checkout.py
git add checkout.py
git commit -m "add validation"
echo " process_payment(cart)" >> checkout.py
git add checkout.py
git commit -m "add payment"
echo " print('Done!')" >> checkout.py
git add checkout.py
git commit -m "typo fix"
echo "# Payment processing module" >> checkout.py
git add checkout.py
git commit -m "forgot comment"
git log --oneline
# Shows 5 messy commits
Clean Up History with Interactive Rebase
git rebase -i HEAD~5
# In the editor, change to:
# pick <first> WIP checkout
# squash <second> add validation
# squash <third> add payment
# squash <fourth> typo fix
# squash <fifth> forgot comment
# Write the new combined commit message:
# feat(checkout): add complete checkout flow with validation and payment
git log --oneline
# Now shows only 1 clean commit
git switch main
git merge feature/checkout
git branch -d feature/checkout
Validation Checklist
-
git log --oneline --graph --allshows a clean history - At least one fast-forward merge was performed
- At least one 3-way merge commit is visible in the history
- The conflict was resolved by combining both features
- Interactive rebase cleaned up the messy commits
- All feature branches are deleted
Bonus Challenges
- Hotfix simulation: Create a
hotfix/critical-bugfrommain, fix the bug, merge back, then rebase your feature branch to include the fix git cherry-pick: Create a separate branch, make 3 commits, then cherry-pick only the second commit onto main- Rebase strategy: Compare
git log --graphafter a merge vs after a rebase of the same branch
Summary
You've practiced the complete branching workflow:
- Feature branches isolate work cleanly
- Fast-forward merges create linear history
- 3-way merges preserve full context
- Conflicts are normal — resolve them thoughtfully
- Interactive rebase cleans history before sharing
Ready for Module 03 — GitHub & Remotes!