# 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 ``` ### Part 2: Create Your Own Branch Now practice creating your own branch: ```pwsh # 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: Create or edit a file then add and commit ```pwsh # Create a new file or modify an existing one. # Stage and commit git status # see the files that are untracked or changed git add . git commit -m "Add my feature" # Create or edit another file # Make another commit git status # see the files that are untracked or changed git add . git commit -m "Expand feature documentation" git log --oneline --graph --all # see how your branch is moving forward from main ``` **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 notive 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 # 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!