Files
git-workshop/01-essentials/03-branching-and-merging/README.md
2026-01-15 12:51:43 +01:00

421 lines
8.3 KiB
Markdown

# Module 03: Branching and Merging
## Learning Objectives
By the end of this module, you will:
- Understand what branches are and why they're useful
- Create and switch between branches
- Make commits on different branches
- Merge branches together
- Visualize branch history with `git log --graph`
- Understand merge commits and how they work
## Setup
Create the challenge environment:
```bash
.\setup.ps1
```
This creates a repository with a realistic project history showing multiple merged feature branches.
## Overview
**Branching** lets you create independent lines of development. Think of it like parallel universes for your code - you can experiment on one branch without affecting others.
**Merging** combines work from different branches back together.
### Why Use Branches?
- **Experiment safely** - Try new ideas without breaking main code
- **Work in parallel** - Multiple features can be developed simultaneously
- **Organize work** - Each feature/fix gets its own branch
- **Collaborate better** - Team members work on separate branches
## Your Task
### Part 1: Explore the Repository
First, explore the existing history to see what merging looks like:
```bash
cd challenge
git log --oneline --graph --all
```
You'll see a visual graph showing:
- The `main` branch timeline
- Feature branches that split off from main
- Merge points where branches come back together
**Study the graph:**
- Look for the `*` symbols (commits)
- Notice the `|`, `/`, and `\` characters (branch lines)
- Find the merge commits (they have two parent lines converging)
**Explore the branches:**
```bash
# See all branches
git branch --all
# Check which files exist on different branches
git ls-tree --name-only feature-login
git ls-tree --name-only feature-api
git ls-tree --name-only main
```
**View specific merges:**
```bash
# See all merge commits
git log --merges --oneline
# See details of a specific merge
git show <merge-commit-hash>
```
### Part 2: Create Your Own Branch
Now practice creating your own branch:
```bash
# Create and switch to a new branch
git switch -c my-feature
# Verify you're on the new branch
git branch
```
The `*` shows which branch you're currently on.
### Part 3: Make Commits on Your Branch
Add some changes to your branch:
```bash
# Create a new file or modify an existing one
echo "# My Feature" > my-feature.md
# Stage and commit
git add .
git commit -m "Add my feature"
# Make another commit
echo "More details" >> my-feature.md
git add .
git commit -m "Expand feature documentation"
```
**Important:** Changes on your branch don't affect main!
```bash
# Switch to main
git switch main
# Notice your my-feature.md doesn't exist here
ls
# Switch back to your branch
git switch my-feature
# Now it exists again!
ls
```
### Part 4: Merge Your Branch
Bring your work into main:
```bash
# Switch to the branch you want to merge INTO
git switch main
# Merge your feature branch
git merge my-feature
# View the result
git log --oneline --graph --all
```
You should see your feature branch merged into main!
### Part 5: Practice More
Create additional branches to practice:
```bash
# Create another feature
git switch -c another-feature
# Add changes and commits
# ... your work ...
# Merge it
git switch main
git merge another-feature
```
**Verify your work:**
```bash
# From the module directory (not inside challenge/)
.\verify.ps1
```
## Understanding Branches
### What is a Branch?
A **branch** is a lightweight movable pointer to a commit. When you create a branch, Git creates a new pointer - it doesn't copy all your files!
```
main: A---B---C
\
my-feature: D---E
```
- Both branches share commits A and B
- Main has commit C
- My-feature has commits D and E
- They're independent!
### What is HEAD?
`HEAD` points to your current branch. It's Git's way of saying "you are here."
```bash
# HEAD points to main
git switch main
# Now HEAD points to my-feature
git switch my-feature
```
## Understanding Merging
### Types of Merges
**Three-way merge** (most common):
```
Before:
main: A---B---C
\
feature: D---E
After merge:
main: A---B---C---M
\ /
feature: D---E
```
Git creates a merge commit `M` that has two parents (C and E).
**Fast-forward merge**:
```
Before:
main: A---B
\
feature: C---D
After merge:
main: A---B---C---D
```
If main hasn't changed, Git just moves the pointer forward. No merge commit needed!
## Key Commands
### Branching
```bash
# List all branches (* shows current branch)
git branch
# Create a new branch
git branch feature-name
# Create AND switch to new branch
git switch -c feature-name
# Switch to existing branch
git switch branch-name
# Switch to previous branch
git switch -
# Delete a branch (only if merged)
git branch -d feature-name
# Force delete a branch
git branch -D feature-name
```
### Merging
```bash
# Merge a branch into your current branch
git merge branch-name
# Abort a merge if something goes wrong
git merge --abort
# Force a merge commit (even if fast-forward possible)
git merge --no-ff branch-name
```
### Viewing History
```bash
# Visual branch graph
git log --oneline --graph --all
# Compact history
git log --oneline
# Only merge commits
git log --merges
# Show which branches have been merged into main
git branch --merged main
# Show which branches haven't been merged
git branch --no-merged main
```
## Common Workflows
### Creating a Feature
```bash
# Start from main
git switch main
# Create feature branch
git switch -c feature-awesome
# Make changes
echo "cool stuff" > feature.txt
git add .
git commit -m "Add awesome feature"
# More changes...
echo "more cool stuff" >> feature.txt
git add .
git commit -m "Improve awesome feature"
```
### Merging a Feature
```bash
# Switch to main
git switch main
# Merge your feature
git merge feature-awesome
# Delete the feature branch (optional)
git branch -d feature-awesome
```
### Keeping Main Updated While Working
```bash
# You're on feature-awesome
git switch feature-awesome
# Main branch has new commits from others
# Bring those into your feature branch
git switch main
git pull
git switch feature-awesome
git merge main
# Or in one command (more advanced):
git pull origin main
```
## Troubleshooting
### "I'm on the wrong branch!"
```bash
# Switch to the correct branch
git switch correct-branch
# Check current branch anytime
git branch
```
### "I made commits on the wrong branch!"
Don't panic! You can move commits to another branch:
```bash
# Create the correct branch from current state
git branch correct-branch
# Switch to wrong branch and remove the commits
git switch wrong-branch
git reset --hard HEAD~2 # Remove last 2 commits (adjust number)
# Switch to correct branch - commits are there!
git switch correct-branch
```
### "The merge created unexpected results!"
```bash
# Undo the merge
git merge --abort
# Or if already committed:
git reset --hard HEAD~1
```
### "I want to see what changed in a merge!"
```bash
# Show the merge commit
git show <merge-commit-hash>
# Compare two branches before merging
git diff main..feature-branch
```
## Tips for Success
💡 **Branch often** - Branches are cheap! Create one for each feature or experiment.
💡 **Commit before switching** - Always commit (or stash) changes before switching branches.
💡 **Keep branches focused** - One feature per branch makes merging easier.
💡 **Delete merged branches** - Clean up with `git branch -d branch-name` after merging.
💡 **Use descriptive names** - `feature-login` is better than `stuff` or `branch1`.
💡 **Visualize often** - Run `git log --oneline --graph --all` to understand your history.
## What You've Learned
After completing this module, you understand:
- ✅ Branches create independent lines of development
-`git switch -c` creates a new branch
- ✅ Changes in one branch don't affect others
-`git merge` combines branches
- ✅ Merge commits have two parent commits
-`git log --graph` visualizes branch history
- ✅ Branches are pointers, not copies of files
## Next Steps
Ready to continue? The next module covers **merge conflicts** - what happens when Git can't automatically merge changes.
To start over:
```bash
.\reset.ps1
.\setup.ps1
```
**Need help?** Review the commands above, or run `git status` to see what Git suggests!