# Module 03: Branching and Merging ## About This Module Welcome to Module 03! This module is different from the others - it uses a **checkpoint system** that lets you work through three related concepts in one continuous repository: 1. **Branching Basics** - Create and work with feature branches 2. **Merging Branches** - Combine branches together 3. **Resolving Merge Conflicts** - Fix conflicts when Git can't merge automatically Instead of three separate modules, you'll progress through checkpoints in a single Git repository, building on each previous section. You can jump between checkpoints, skip ahead, or restart any section at any time! ### Why Checkpoints? Branching, merging, and conflict resolution are naturally connected - you can't understand merging without branches, and you can't master conflicts without trying to merge. The checkpoint system lets you learn these concepts as a continuous workflow, just like real development. ## Quick Start ### Setup Create the challenge environment: ```bash .\setup.ps1 ``` This creates a complete Git repository with all checkpoints ready. ### Working with Checkpoints **View available checkpoints:** ```bash .\reset.ps1 ``` **Jump to a specific checkpoint:** ```bash .\reset.ps1 start # Checkpoint 1: Branching Basics .\reset.ps1 merge # Checkpoint 2: Merging Branches .\reset.ps1 merge-conflict # Checkpoint 3: Resolving Conflicts ``` **Verify your progress:** ```bash .\verify.ps1 # Verify all checkpoints complete .\verify.ps1 start # Verify Checkpoint 1 only .\verify.ps1 merge # Verify Checkpoint 2 only .\verify.ps1 merge-conflict # Verify Checkpoint 3 only ``` ### Recommended Workflow Complete checkpoints in order: 1. Start with Checkpoint 1 (Branching Basics) 2. Progress to Checkpoint 2 (Merging) 3. Finish with Checkpoint 3 (Merge Conflicts) Or skip to any checkpoint if you already know the earlier concepts! --- ## Checkpoint 1: Branching Basics ### Learning Objectives - Understand what a branch is in Git - Create new branches with `git switch -c` - Switch between branches with `git switch` - View all branches with `git branch` - Understand that branches are independent lines of development ### Your Task Create a feature branch called `feature-login`, add a `login.py` file, and make commits to demonstrate that branches allow independent development. **Steps:** 1. Navigate to the challenge directory: `cd challenge` 2. Create a new branch: `git switch -c feature-login` 3. Create a file: `login.py` (with any content you like) 4. Commit your file: `git add login.py && git commit -m "Add login module"` 5. Make another change to `login.py` and commit it 6. Switch back to main: `git switch main` 7. Notice that `login.py` doesn't exist on main! 8. Switch back to your feature: `git switch feature-login` 9. Notice that `login.py` exists again! **Verify:** Run `.\verify.ps1 start` to check your solution. ### What is a Branch? A **branch** in Git is an independent line of development. Think of it as a parallel universe for your code - you can make changes without affecting the main timeline. **Visual representation:** ``` main: A---B---C \ feature-login: D---E ``` - Both branches share commits A and B - Branch `main` continues with commit C - Branch `feature-login` goes in a different direction with commits D and E - Changes in one branch don't affect the other! ### Why Use Branches? Branches let you: - **Experiment safely** - Try new ideas without breaking main - **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 ### Key Concepts - **Branch**: A lightweight movable pointer to a commit - **HEAD**: A pointer showing which branch you're currently on - **main**: The default branch (formerly called "master") - **Feature branch**: A branch created for a specific feature or task ### Useful Commands ```bash # View all branches (current branch marked with *) git branch # Create a new branch git branch feature-login # Switch to a branch git switch feature-login # Create AND switch in one command git switch -c feature-login # Switch back to previous branch git switch - # Delete a branch (only if merged) git branch -d feature-login # Force delete a branch git branch -D feature-login ``` ### Understanding HEAD `HEAD` is Git's way of saying "you are here." It points to your current branch. When you run `git switch main`, HEAD moves to point to main. When you run `git switch feature-login`, HEAD moves to point to feature-login. --- ## Checkpoint 2: Merging Branches **Prerequisites:** Complete Checkpoint 1 OR run `.\reset.ps1 merge` ### Learning Objectives - Understand what merging means in Git - Merge a feature branch back into main - Use `git merge` to combine branches - Understand merge commits - Visualize merged branches with `git log --graph` ### Your Task You've completed work on your `feature-login` branch. Now merge it back into `main` to include the login functionality in your main codebase. **Scenario:** - You created the `feature-login` branch and added login functionality - Meanwhile, development continued on `main` (README and app.py were added) - Now you need to merge your login feature into main **Steps:** 1. Make sure you're in the challenge directory: `cd challenge` 2. Check which branch you're on: `git branch` 3. Switch to main if needed: `git switch main` 4. View the branch structure: `git log --oneline --graph --all` 5. Merge feature-login into main: `git merge feature-login` 6. View the result: `git log --oneline --graph --all` **Verify:** Run `.\verify.ps1 merge` to check your solution. ### What is Merging? **Merging** is the process of combining changes from one branch into another. Think of it like combining two streams into one river - all the water (code) flows together. #### Before Merging You have two branches with different work: ``` main: A---B---C---D \ feature-login: E---F ``` - Main branch progressed with commits C and D - Feature-login branch has commits E and F - They diverged at commit B #### After Merging You bring the feature branch into main: ``` main: A---B---C---D---M \ / feature-login: E-----F ``` - Commit M is a **merge commit** - it combines both branches - Main now has all the work from both branches - Your login feature is now part of main! ### How to Merge Merging is simple - just two steps: **1. Switch to the branch you want to merge INTO:** ```bash git switch main ``` This is the branch that will receive the changes. **2. Merge the other branch:** ```bash git merge feature-login ``` This brings changes from `feature-login` into `main`. **That's it!** Git automatically combines the changes. ### Understanding Merge Commits When you merge, Git creates a special commit called a **merge commit**. **What makes it special?** - It has TWO parent commits (one from each branch) - It represents the point where branches come back together - The message typically says "Merge branch 'feature-login'" **See your merge commit:** ```bash git log --oneline ``` Look for the merge commit at the top - it will say something like: ``` abc1234 Merge branch 'feature-login' ``` ### Types of Merges **Three-way merge** (what you just did): - Both branches have new commits - Git creates a merge commit - History shows both branches clearly **Fast-forward merge**: - Main hasn't changed since the branch was created - Git just moves the main pointer forward - No merge commit needed! ``` # Before (fast-forward merge) main: A---B \ feature: C---D # After (main just moves forward) main: A---B---C---D ``` ### Visualizing Branches The `--graph` flag is your best friend: ```bash git log --oneline --graph --all ``` **What the graph shows:** - `*` = A commit - `|` = A branch line - `/` and `\` = Branches splitting/joining - Branch names in parentheses **Example output:** ``` * a1b2c3d (HEAD -> main) Merge branch 'feature-login' |\ | * e4f5g6h (feature-login) Add password validation | * i7j8k9l Add login module * | m1n2o3p Add README documentation * | q4r5s6t Add app.py entry point |/ * u7v8w9x Add main functionality * y1z2a3b Initial commit ``` ### Useful Commands ```bash # Merge a branch into your current branch git merge # Abort a merge if something goes wrong git merge --abort # View merge commits only git log --merges # View branch structure git log --oneline --graph --all # See which branches have been merged into main git branch --merged main # See which branches haven't been merged git branch --no-merged main ``` --- ## Checkpoint 3: Resolving Merge Conflicts **Prerequisites:** Complete Checkpoint 2 OR run `.\reset.ps1 merge-conflict` ### Learning Objectives - Understand what merge conflicts are and why they occur - Identify merge conflicts in your repository - Read and interpret conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) - Resolve merge conflicts manually - Complete a merge after resolving conflicts ### Your Task You have an `update-config` branch that modified `config.json`, and the main branch also modified `config.json` in a different way. When you try to merge, Git can't automatically combine them - you'll need to resolve the conflict manually. **Your mission:** 1. Attempt to merge the `update-config` branch into `main` 2. Git will tell you there's a conflict - don't panic! 3. Resolve the conflict by keeping BOTH settings (timeout AND debug) 4. Complete the merge **Steps:** 1. Make sure you're in challenge directory: `cd challenge` 2. Verify you're on main: `git branch` 3. Try to merge: `git merge update-config` 4. Git will report a conflict! 5. Open `config.json` in your text editor 6. Follow the resolution guide below 7. Save the file 8. Stage the resolved file: `git add config.json` 9. Complete the merge: `git commit` **Verify:** Run `.\verify.ps1 merge-conflict` to check your solution. ### What Are Merge Conflicts? A **merge conflict** occurs when Git cannot automatically combine changes because both branches modified the same part of the same file. **Example scenario:** ``` main branch: changes line 5 to: "timeout": 5000 update-config: changes line 5 to: "debug": true ``` Git doesn't know which one you want (or if you want both)! So it asks you to decide. **When do conflicts happen?** - ✅ Two branches modify the same lines in a file - ✅ One branch deletes a file that another branch modifies - ✅ Complex changes Git can't merge automatically - ❌ Different files are changed (no conflict!) - ❌ Different parts of the same file are changed (no conflict!) **Don't fear conflicts!** They're a normal part of collaborative development. Git just needs your help to decide what the final code should look like. ### Step-by-Step: Resolving Your First Conflict #### Step 1: Attempt the Merge ```bash cd challenge git merge update-config ``` **You'll see:** ``` Auto-merging config.json CONFLICT (content): Merge conflict in config.json Automatic merge failed; fix conflicts and then commit the result. ``` **Don't panic!** This is normal. Git is just asking for your help. #### Step 2: Check What Happened ```bash git status ``` **You'll see:** ``` On branch main You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add ..." to mark resolution) both modified: config.json ``` This tells you that `config.json` needs your attention! #### Step 3: Open the Conflicted File Open `config.json` in your text editor. You'll see special **conflict markers**: ```json { "app": { "name": "MyApp", "version": "1.0.0", "port": 3000, <<<<<<< HEAD "timeout": 5000 ======= "debug": true >>>>>>> update-config } } ``` #### Step 4: Understand the Conflict Markers ``` <<<<<<< HEAD "timeout": 5000 ← Your current branch (main) ======= "debug": true ← The branch you're merging (update-config) >>>>>>> update-config ``` **What each marker means:** - `<<<<<<< HEAD` - Start of your changes (current branch) - `=======` - Separator between the two versions - `>>>>>>> update-config` - End of their changes (branch being merged) #### Step 5: Decide What to Keep You have three options: **Option 1: Keep ONLY your changes (timeout)** ```json "timeout": 5000 ``` **Option 2: Keep ONLY their changes (debug)** ```json "debug": true ``` **Option 3: Keep BOTH changes** ← This is what we want! ```json "timeout": 5000, "debug": true ``` For this challenge, choose **Option 3** - keep both settings! #### Step 6: Edit the File Delete ALL the conflict markers and keep both settings: **Before (with conflict markers):** ```json { "app": { "name": "MyApp", "version": "1.0.0", "port": 3000, <<<<<<< HEAD "timeout": 5000 ======= "debug": true >>>>>>> update-config } } ``` **After (resolved):** ```json { "app": { "name": "MyApp", "version": "1.0.0", "port": 3000, "timeout": 5000, "debug": true } } ``` **Important:** - Remove `<<<<<<< HEAD` - Remove `=======` - Remove `>>>>>>> update-config` - Keep both the timeout and debug settings - Ensure valid JSON syntax (notice the comma after timeout!) #### Step 7: Save the File Save `config.json` with your changes. #### Step 8: Stage the Resolved File Tell Git you've resolved the conflict: ```bash git add config.json ``` #### Step 9: Check Status ```bash git status ``` **You'll see:** ``` On branch main All conflicts fixed but you are still merging. (use "git commit" to conclude merge) ``` Perfect! Git confirms the conflict is resolved. #### Step 10: Complete the Merge Commit the merge: ```bash git commit ``` Git will open an editor with a default merge message. You can accept it or customize it. **Done!** Your merge is complete! ### Common Mistakes to Avoid ❌ **Forgetting to remove conflict markers** ```json <<<<<<< HEAD ← Don't leave these in! "timeout": 5000, "debug": true >>>>>>> update-config ← Don't leave these in! ``` This breaks your code! Always remove ALL markers. ❌ **Committing without staging** ```bash git commit # Error! You didn't add the file ``` Always `git add` the resolved file first! ❌ **Keeping only one side when both are needed** If you delete one setting, you lose that work. For this challenge, you need BOTH! ❌ **Breaking syntax** ```json "timeout": 5000 ← Missing comma! "debug": true ``` Always verify your file is valid after resolving! ### Aborting a Merge Changed your mind? You can abort the merge anytime: ```bash git merge --abort ``` This returns your repository to the state before you started the merge. No harm done! ### Useful Commands ```bash # Attempt a merge git merge # Check which files have conflicts git status # Abort the merge and start over git merge --abort # After resolving conflicts: git add git commit # View conflicts in a different style git diff --ours # Your changes git diff --theirs # Their changes git diff --base # Original version ``` ### Pro Tips 💡 **Prevent conflicts** - Pull changes frequently: `git pull` - Communicate with your team about who's working on what - Keep branches short-lived and merge often 💡 **Make conflicts easier** - Work on different files when possible - If you must edit the same file, coordinate with teammates - Make small, focused commits 💡 **When stuck** - Read the conflict markers carefully - Look at `git log` to understand what each side changed - Ask a teammate to review your resolution - Use a merge tool: `git mergetool` --- ## Complete Command Reference ### Branching ```bash git branch # List all branches git branch feature-name # Create a new branch git switch branch-name # Switch to a branch git switch -c feature-name # Create and switch git switch - # Switch to previous branch git branch -d feature-name # Delete branch (if merged) git branch -D feature-name # Force delete branch ``` ### Merging ```bash git merge branch-name # Merge a branch into current branch git merge --no-ff branch-name # Force a merge commit git merge --abort # Abort a merge in progress git log --merges # View only merge commits ``` ### Viewing History ```bash git log --oneline --graph --all # Visual branch structure git log --oneline # Compact commit list git log --graph --decorate --all # Detailed branch view git log main..feature-login # Commits in feature not in main git diff main...feature-login # Changes between branches ``` ### Conflict Resolution ```bash git status # See conflicted files git diff # View conflicts git add resolved-file # Mark file as resolved git commit # Complete the merge git merge --abort # Give up and start over ``` ### Checkpoint Commands (This Module) ```bash .\reset.ps1 # Show available checkpoints .\reset.ps1 start # Jump to Checkpoint 1 .\reset.ps1 merge # Jump to Checkpoint 2 .\reset.ps1 merge-conflict # Jump to Checkpoint 3 .\verify.ps1 # Verify all complete .\verify.ps1 start # Verify Checkpoint 1 .\verify.ps1 merge # Verify Checkpoint 2 .\verify.ps1 merge-conflict # Verify Checkpoint 3 ``` --- ## Troubleshooting ### "I'm on the wrong branch!" ```bash git switch main # Switch to main git branch # Verify current branch ``` ### "I made commits on the wrong branch!" Don't panic! You can move them: ```bash # You're on main but should be on feature-login git switch feature-login # Switch to correct branch git merge main # Bring the commits over git switch main git reset --hard HEAD~1 # Remove from main (careful!) ``` Or use cherry-pick (covered in a later module). ### "The merge created a mess!" Abort and try again: ```bash git merge --abort git status # Verify you're back to clean state ``` ### "I want to start this checkpoint over!" Use the reset script: ```bash .\reset.ps1 start # Go back to Checkpoint 1 ``` This resets your repository to the beginning of that checkpoint. ### "I can't find my branch!" List all branches: ```bash git branch --all # Shows all branches including remote ``` The branch might have been deleted after merging (this is normal!). ### "How do I know which checkpoint I'm on?" ```bash .\reset.ps1 # Shows current checkpoint git log --oneline --graph --all --decorate # Shows all tags/branches ``` --- ## Real-World Workflow Example Here's how professional developers use these skills: **Day 1: Start a new feature** ```bash git switch main git pull # Get latest changes git switch -c feature-dark-mode # New feature branch # ... make changes ... git add . git commit -m "Add dark mode toggle" ``` **Day 2: Continue work** ```bash git switch feature-dark-mode # Resume work # ... make more changes ... git add . git commit -m "Add dark mode styles" ``` **Day 3: Ready to merge** ```bash git switch main git pull # Get latest main git switch feature-dark-mode git merge main # Bring main's changes into feature # Resolve any conflicts git switch main git merge feature-dark-mode # Merge feature into main git push # Share with team git branch -d feature-dark-mode # Clean up ``` **This is exactly what you just practiced!** --- ## What You've Learned By completing all three checkpoints, you now understand: ### Checkpoint 1: Branching Basics - ✅ Branches create independent lines of development - ✅ `git switch -c` creates and switches to a new branch - ✅ Changes in one branch don't affect others - ✅ Branches are lightweight and easy to create ### Checkpoint 2: Merging Branches - ✅ Merging combines work from two branches - ✅ Merge commits have two parent commits - ✅ `git merge` brings changes into your current branch - ✅ Three-way merges create a merge commit ### Checkpoint 3: Resolving Merge Conflicts - ✅ Conflicts happen when the same lines are changed differently - ✅ Conflict markers show both versions - ✅ You choose what the final code should look like - ✅ Conflicts are normal and easy to resolve with practice --- ## Next Steps **Completed the module?** Great work! You're ready to move on. **Want more practice?** Jump to any checkpoint and try again: ```bash .\reset.ps1 start # Practice branching .\reset.ps1 merge # Practice merging .\reset.ps1 merge-conflict # Practice conflict resolution ``` **Ready for the next module?** Continue to Module 04 to learn about cherry-picking specific commits! --- **Need help?** Review the relevant checkpoint section above, or run `git status` to see what Git suggests!