Files
git-workshop/01-essentials/03-branching-and-merging/README.md
2026-01-15 14:22:11 +01:00

390 lines
9.5 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:
```pwsh
.\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:
```pwsh
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:**
```pwsh
# 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:**
```pwsh
# 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:
1. Create a new branch with the name `my-feature` using `git switch -c my-feature`
2. Check which branch you're on with `git branch`. The `*` shows which branch you're currently on.
### Part 3: Make Commits on Your Branch
1. Create a new file called `DOCS.md` and add some content. What doesn't matter, just something.
2. Add and commit the `DOCS.md` file (use the commands from `01-basics` module).
3. Add some more content to the `DOCS.md` file, add and commit the changes.
4. Now check how the tree is looking with `git log --oneline --graph --all`
**Important:** Changes on your branch don't affect main!
1. Change back to the `main` branch `git switch main`
2. Check the changes you committed before. You'll notice that they're gone!
3. Now edit a file or create a new file and add it and commit it on your `main` branch (hint: `git add .`, `git commit -m`)
- This way we create diverging branches. The `main` branch has changes as well as your new `my-feature` branch.
- Run `git log --oneline --graph --all` to see how the tree is looking
4. Switch back to your branch `git switch my-feature`
5. The changes from the `main` branch are now gone. Check the changes you committed before. You'll notice they're back!
### Part 4: Merge Your Branch
Bring your work into main:
1. Go back to the main branch `git switch main`
2. Run a `git log --oneline --graph --all` to see that the `HEAD` is on your `main` branch
3. It might be wise to first ensure that we're using Visual Studio Code to handle merge messages. If you haven't already set `git config --global core.editor "code --wait"` this sets Visual Studio Code to be the default editor for anything Git related.
4. Let's merge the recently created branch `git merge my-feature`
5. Visual Studio Code should open with a commit message. In order to solidify the commit simply close the window. That tells Git that the commit message has been written and the change should be committed.
6. Now run `git log --oneline --graph --all` and see your changes merge into the `main` branch!
7. Now let's clean up a bit, run `git branch -d my-feature` to remove the recently merged branch.
- If you hadn't merged the branch first this command would fail as Git will warn you that you have changes not merged into the `main` branch
You should see your feature branch merged into main!
### Part 5: Practice More
Create additional branches to practice:
```pwsh
# 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:**
```pwsh
# 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."
```pwsh
# 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
```pwsh
# 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
```pwsh
# 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
```pwsh
# 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
```pwsh
# 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
```pwsh
# 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
```pwsh
# 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!"
```pwsh
# 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:
```pwsh
# 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!"
```pwsh
# Undo the merge
git merge --abort
# Or if already committed:
git reset --hard HEAD~1
```
### "I want to see what changed in a merge!"
```pwsh
# 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:
```pwsh
.\reset.ps1
.\setup.ps1
```
**Need help?** Review the commands above, or run `git status` to see what Git suggests!