refactor: split out merge strategies from essentials
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
# Module 04: Merging
|
||||
# Module 04: Merging Branches
|
||||
|
||||
## Learning Objectives
|
||||
|
||||
In this module, you will:
|
||||
- Understand what merging means in Git
|
||||
- Perform a fast-forward merge
|
||||
- Perform a three-way merge
|
||||
- Understand when merge commits are created
|
||||
- Merge divergent branches together
|
||||
- Understand merge commits and their purpose
|
||||
- Use `git merge` to combine branches
|
||||
- Visualize merge history with `git log --graph`
|
||||
|
||||
## Challenge
|
||||
|
||||
@@ -19,72 +19,217 @@ Run the setup script to create your challenge environment:
|
||||
.\setup.ps1
|
||||
```
|
||||
|
||||
This will create a `challenge/` directory with a Git repository that has a main branch and a feature branch ready to merge.
|
||||
This will create a `challenge/` directory with a Git repository that has two divergent branches ready to merge.
|
||||
|
||||
### Your Task
|
||||
|
||||
This challenge has two parts that teach you about the two types of merges in Git:
|
||||
You have two branches that have diverged - both `main` and `feature-login` have new commits since they split. Your task is to merge them back together.
|
||||
|
||||
**Part 1: Fast-Forward Merge**
|
||||
1. Merge the existing `feature-api` branch into main
|
||||
2. Observe that this is a "fast-forward" merge (no merge commit created)
|
||||
**Scenario:**
|
||||
- You're working on a team project
|
||||
- You created a `feature-login` branch to add login functionality
|
||||
- While you were working, your teammate added documentation to `main`
|
||||
- Now you need to merge your login feature back into main
|
||||
|
||||
**Part 2: Three-Way Merge**
|
||||
3. Create a new branch called `feature-ui`
|
||||
4. Make commits on the feature-ui branch
|
||||
5. Switch back to main and make a commit there too (creates divergence)
|
||||
6. Merge feature-ui into main
|
||||
7. Observe that this creates a merge commit (three-way merge)
|
||||
|
||||
**Suggested Approach:**
|
||||
**Steps:**
|
||||
|
||||
1. Navigate to the challenge directory: `cd challenge`
|
||||
2. Check current branch: `git branch` (should be on main)
|
||||
3. View existing branches: `git branch -a`
|
||||
4. Merge feature-api: `git merge feature-api`
|
||||
5. View the log: `git log --oneline --graph`
|
||||
6. Create feature-ui branch: `git switch -c feature-ui`
|
||||
7. Create a new file `ui.py` and commit it
|
||||
8. Make another commit on feature-ui (modify ui.py)
|
||||
9. Switch back to main: `git switch main`
|
||||
10. Make a change on main (modify api.py) and commit it
|
||||
11. Merge feature-ui: `git merge feature-ui`
|
||||
12. View the merge history: `git log --oneline --graph --all`
|
||||
3. View the branch structure: `git log --oneline --graph --all`
|
||||
4. Merge the feature-login branch: `git merge feature-login`
|
||||
5. View the merge result: `git log --oneline --graph --all`
|
||||
6. Examine the merge commit: `git show HEAD`
|
||||
|
||||
> **Important Notes:**
|
||||
> - A **fast-forward merge** happens when main hasn't changed since the feature branch was created
|
||||
> - A **three-way merge** creates a merge commit when both branches have diverged
|
||||
> - You can see merge commits with `git log --merges`
|
||||
> - The `--graph` option helps visualize the branch history
|
||||
> - After merging, the feature branch still exists but you can delete it with `git branch -d`
|
||||
> - When both branches have new commits, Git creates a **merge commit**
|
||||
> - The merge commit has TWO parent commits (one from each branch)
|
||||
> - Git will open an editor for you to write a merge commit message
|
||||
> - You can use the default message or customize it
|
||||
> - The `--graph` option helps visualize how branches merged
|
||||
|
||||
## Key Concepts
|
||||
|
||||
- **Merge**: Combining changes from different branches into one branch.
|
||||
- **Fast-Forward Merge**: When the target branch hasn't changed, Git simply moves the branch pointer forward. No merge commit is created.
|
||||
- **Three-Way Merge**: When both branches have new commits, Git creates a merge commit that has two parent commits.
|
||||
- **Merge Commit**: A special commit with two (or more) parent commits, representing the point where branches were merged.
|
||||
- **Divergent Branches**: Branches that have different commits since they split from a common ancestor.
|
||||
### What is Merging?
|
||||
|
||||
**Merging** combines changes from different branches into one branch. When you merge, you're telling Git: "Take all the changes from branch X and incorporate them into my current branch."
|
||||
|
||||
### Divergent Branches
|
||||
|
||||
When two branches have different commits since they split, they are **divergent**:
|
||||
|
||||
```
|
||||
main: A---B---C
|
||||
\
|
||||
feature: D---E
|
||||
```
|
||||
|
||||
- Both branches split from commit B
|
||||
- `main` has commit C
|
||||
- `feature` has commits D and E
|
||||
- They have **diverged** - each has unique work
|
||||
|
||||
### The Merge Commit
|
||||
|
||||
When you merge divergent branches, Git creates a special **merge commit**:
|
||||
|
||||
```
|
||||
Before merge:
|
||||
main: A---B---C
|
||||
\
|
||||
feature: D---E
|
||||
|
||||
After merge (on main):
|
||||
main: A---B---C-------M
|
||||
\ /
|
||||
feature: D---E---/
|
||||
```
|
||||
|
||||
**Merge commit (M)** is special because:
|
||||
- It has **two parent commits**: C and E
|
||||
- It represents the point where branches came back together
|
||||
- It contains the combined changes from both branches
|
||||
|
||||
### How Git Merges
|
||||
|
||||
Git uses a **three-way merge** algorithm:
|
||||
|
||||
1. **Common ancestor** (B) - Where the branches split
|
||||
2. **Your branch** (C) - Latest commit on main
|
||||
3. **Their branch** (E) - Latest commit on feature
|
||||
|
||||
Git compares all three to figure out what changed on each branch and combines them intelligently.
|
||||
|
||||
## Understanding Merge Output
|
||||
|
||||
When you run `git merge feature-login`, you'll see:
|
||||
|
||||
```
|
||||
Merge made by the 'ort' strategy.
|
||||
login.py | 25 +++++++++++++++++++++++++
|
||||
1 file changed, 25 insertions(+)
|
||||
create mode 100644 login.py
|
||||
```
|
||||
|
||||
**What this means:**
|
||||
- **"Merge made by the 'ort' strategy"** - Git used its merge algorithm to combine changes
|
||||
- The summary shows what files changed in the merge
|
||||
- A new merge commit was created
|
||||
|
||||
### The Merge Commit Message
|
||||
|
||||
Git will open your editor with a default message:
|
||||
|
||||
```
|
||||
Merge branch 'feature-login'
|
||||
|
||||
# Please enter a commit message to explain why this merge is necessary,
|
||||
# especially if it merges an updated upstream into a topic branch.
|
||||
```
|
||||
|
||||
**Tips for merge messages:**
|
||||
- The default message is usually fine for simple merges
|
||||
- For important merges, explain WHY you're merging
|
||||
- Example: "Merge feature-login - adds user authentication system"
|
||||
|
||||
## Visualizing Merges
|
||||
|
||||
Use `git log --graph` to see the branch structure:
|
||||
|
||||
```bash
|
||||
git log --oneline --graph --all
|
||||
```
|
||||
|
||||
**Example output:**
|
||||
```
|
||||
* a1b2c3d (HEAD -> main) Merge branch 'feature-login'
|
||||
|\
|
||||
| * e5f6g7h (feature-login) Implement login validation
|
||||
| * h8i9j0k Add login form
|
||||
* | k1l2m3n Update README with setup instructions
|
||||
|/
|
||||
* n4o5p6q Initial project structure
|
||||
```
|
||||
|
||||
**Reading the graph:**
|
||||
- `*` = A commit
|
||||
- `|` = Branch line continuing
|
||||
- `/` and `\` = Branch splitting or merging
|
||||
- `(HEAD -> main)` = Current branch position
|
||||
- The merge commit has two lines coming into it
|
||||
|
||||
## Useful Commands
|
||||
|
||||
### Merging
|
||||
|
||||
```bash
|
||||
git merge <branch> # Merge branch into current branch
|
||||
git log --oneline --graph # View merge history visually
|
||||
git log --graph --all # View all branches and merges
|
||||
git log --merges # Show only merge commits
|
||||
git branch -d <branch> # Delete a merged branch (optional)
|
||||
git merge <branch> # Merge branch into current branch
|
||||
git merge --abort # Cancel a merge in progress
|
||||
```
|
||||
|
||||
### Viewing Merge History
|
||||
|
||||
```bash
|
||||
git log --oneline --graph # Simple graph view
|
||||
git log --oneline --graph --all # Show all branches
|
||||
git log --merges # Show only merge commits
|
||||
git show <commit> # View details of a merge commit
|
||||
```
|
||||
|
||||
### Branch Management
|
||||
|
||||
```bash
|
||||
git branch # List local branches
|
||||
git branch -a # List all branches (including remote)
|
||||
git branch -d <branch> # Delete a merged branch
|
||||
```
|
||||
|
||||
## Common Questions
|
||||
|
||||
### "What if the merge fails?"
|
||||
|
||||
Sometimes Git can't automatically merge changes (this is called a **merge conflict**). Don't worry! We'll cover this in the next module (Module 05: Merge Conflicts).
|
||||
|
||||
If you see a conflict and want to cancel:
|
||||
```bash
|
||||
git merge --abort
|
||||
```
|
||||
|
||||
### "Can I undo a merge?"
|
||||
|
||||
Before you've pushed to remote:
|
||||
```bash
|
||||
git reset --hard HEAD~1 # Undo the merge commit
|
||||
```
|
||||
|
||||
We'll cover more advanced undoing in later modules.
|
||||
|
||||
### "Should I delete the feature branch after merging?"
|
||||
|
||||
It's common practice to delete feature branches after merging:
|
||||
|
||||
```bash
|
||||
git branch -d feature-login # Safe delete (only works if merged)
|
||||
```
|
||||
|
||||
This cleans up your branch list. The commits are still in the history - the branch pointer is just removed.
|
||||
|
||||
### "What does 'ort strategy' mean?"
|
||||
|
||||
Git uses different merge algorithms:
|
||||
- **ort** (default in Git 2.34+) - Newer, faster merge algorithm
|
||||
- **recursive** (older) - Traditional merge algorithm
|
||||
|
||||
You don't need to worry about this - Git picks the best one automatically!
|
||||
|
||||
## Verification
|
||||
|
||||
Once you've completed both merges, verify your solution:
|
||||
Once you've completed the merge, verify your solution:
|
||||
|
||||
```powershell
|
||||
.\verify.ps1
|
||||
```
|
||||
|
||||
The verification script will check that you've successfully merged both feature branches and understand the different merge types.
|
||||
The verification script will check that you've successfully merged the feature branch.
|
||||
|
||||
## Need to Start Over?
|
||||
|
||||
@@ -95,3 +240,9 @@ If you want to reset the challenge and start fresh:
|
||||
```
|
||||
|
||||
This will remove the challenge directory and run the setup script again, giving you a clean slate.
|
||||
|
||||
## What's Next?
|
||||
|
||||
Now that you understand basic merging, the next module covers **Merge Conflicts** - what happens when Git can't automatically merge changes and how to resolve them manually.
|
||||
|
||||
**Advanced Topic:** In Module 06 (Advanced section), you'll learn about different merge strategies including fast-forward merges and when to use `--no-ff`.
|
||||
|
||||
Reference in New Issue
Block a user