352 lines
8.9 KiB
Markdown
352 lines
8.9 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 (perhaps GUIDE.md, content of the file doesn't matter) 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
|
|
```
|
|
|
|
### "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!
|