Advanced Git Concepts
From the quiz curriculum
TL;DR
You'll learn how to rewrite Git history for cleaner projects, manage complex merges with strategies, and effectively use stashing for temporary changes. These advanced techniques help you maintain a tidy repository and streamline your workflow. Mastering them will make you a more efficient and impactful developer.
1. The Mental Model
Think of Git as a series of snapshots, not just changes. Advanced Git lets you rearrange, combine, or even remove these snapshots, giving you more control over your project's story. It also provides tools to temporarily shelve work or resolve intricate branching situations.
2. The Core Material
2.1 Rewriting History with rebase -i

Photo by Suzy Hazelwood on Pexels
Interactive rebase (git rebase -i) is your superpower for cleaning up commits before sharing them. It lets you "replay" commits onto a new base, with the ability to edit, squash, reorder, or drop them. This is crucial for keeping your branch's history linear and clean.
Imagine you've made several small commits while working on a feature, some of which fix typos or add debugging statements. Before merging to main, you'd want to combine these into a single, meaningful commit.
# First, find a good base commit (e.g., where your feature branch diverged from main)
# Or, if you want to rebase the last N commits on your current branch:
git rebase -i HEAD~3 # Rewrites the last 3 commits
This opens an editor showing your last N commits. You'll see lines like:
pick f7f3f6d feat: add user authentication
pick 3a1b0c9 fix: typo in login message
pick d2e8a7b chore: update dependencies
You can change pick to squash, reword, edit, drop, or fixup.
- squash (or s): Combines the commit into the previous one, allowing you to edit the combined commit message.
- fixup (or f): Similar to squash, but discards the commit's message, keeping only the previous one.
- reword (or r): Changes the commit message.
- edit (or e): Stops the rebase process to let you amend the commit (e.g., add/remove files).
- drop (or d): Removes the commit entirely.
2.2 Merge Strategies

Photo by Leeloo The First on Pexels
When merging branches, Git uses different strategies to combine changes. While recursive is the default and usually works well, understanding others can help in complex scenarios.
recursive(default for 3-way merges): The most common, handles simple merges well.ours: When mergingfeatureintomain, this strategy completely ignores changes fromfeatureand keeps everything frommain. Useful when you absolutely want to discard a branch's changes during a merge.theirs: The opposite ofours. When mergingfeatureintomain, this strategy ignores changes frommainand keeps everything fromfeature.subtree: Useful when a subdirectory of one repository is a subdirectory of another.
# Example: Using the 'ours' strategy
git merge -s ours feature-branch
2.3 Stashing Changes

Photo by Leeloo The First on Pexels
git stash is a lifesaver when you're working on something, but suddenly need to switch branches or pull updates without committing your incomplete work. It temporarily saves your uncommitted changes (both staged and unstaged) and reverts your working directory to a clean state.
graph TD
A["Working on Feature X"] --> B{Need to switch branches or pull?};
B -- Yes --> C["git stash"];
C --> D["Working Directory Clean"];
D --> E["Switch branches / Pull updates"];
E --> F["git stash pop (or apply)"];
F --> A;
B -- No --> A;
git stash save "message": Stashes changes with a descriptive message.git stash list: Shows all stashed changes.git stash apply [stash@{n}]: Applies stashed changes but keeps them in the stash list.git stash pop [stash@{n}]: Applies stashed changes and removes them from the stash list.git stash drop [stash@{n}]: Deletes a specific stash entry.git stash clear: Removes all stash entries.
3. Worked Example
Let's say you're working on feature-branch. You've made three commits:
1. "Add user settings UI"
2. "Fix button alignment" (small UI tweak)
3. "Implement dark mode toggle"
You realize the "Fix button alignment" commit is too minor to stand alone and should be part of the "Add user settings UI" commit.
- First, make sure you're on
feature-branch. - Run
git log --onelineto see your recent commits. Assume they areabc1234,def5678,ghi9012. - You want to rebase the last three commits:
bash git rebase -i HEAD~3 - Git opens an editor (e.g., Vim) with:
```
pick abc1234 Add user settings UI
pick def5678 Fix button alignment
pick ghi9012 Implement dark mode toggle
# Rebase 6b19a77..ghi9012 onto 6b19a77 (3 commands)
# ...
5. Change the line for "Fix button alignment" to `fixup` or `squash`:
pick abc1234 Add user settings UI
fixup def5678 Fix button alignment # Or 'squash'
pick ghi9012 Implement dark mode toggle
``
6. Save and close the editor.
- If you usedfixup, Git automatically combines the commits.
- If you usedsquash`, Git will open another editor for you to write the new combined commit message. You'd combine "Add user settings UI" and "Fix button alignment" into one clear message.
7. After the rebase completes, your branch history will be cleaner, with the alignment fix integrated into the UI commit.
Important: Never rebase commits that have already been pushed to a shared remote repository unless you absolutely know what you're doing and are prepared to force push (git push --force-with-lease). Rewriting shared history can cause problems for collaborators.
4. Key Takeaways
- Use
git rebase -ito clean up your local commit history before sharing. squashandfixupare great for combining small, related commits into larger, more meaningful ones.- Understand different merge strategies like
oursandtheirsfor specific merging needs, thoughrecursiveis usually sufficient. git stashis your tool for temporarily saving incomplete work, allowing you to switch contexts cleanly.- Always be cautious when rewriting history; avoid rebasing commits that others have already pulled.
- A clean commit history makes debugging and understanding project evolution much easier.
- Advanced Git commands give you granular control over your repository's narrative.
Common Mistakes
- Rebasing public history: Never rewrite commits that have already been pushed to a shared branch (like
main) and pulled by others without extreme caution. It causes divergent histories and headaches. - Forgetting to
git stash pop: Accidentally leaving changes in the stash list when you meant to apply and remove them. - Incorrectly resolving rebase conflicts: Not understanding whose changes to keep can lead to lost work or bad merges.
- Over-rebasing: Constantly rebasing small changes can make the history hard to follow, sometimes a few small commits are okay.
- Not understanding the parent/child relationship in rebase:
fixupandsquashalways combine into the previous commit in the rebase list.
5. Now Try It
You're working on a new feature.
1. Create a new branch: git checkout -b my-feature
2. Create a file test.txt and add "First line." Commit it: git commit -m "feat: initial feature commit"
3. Add "Second line." to test.txt. Commit it: git commit -m "fix: typo in first line"
4. Add "Third line." to test.txt. Commit it: git commit -m "chore: add more content"
5. Now, use git rebase -i HEAD~3 to squash the "fix: typo" commit into the "feat: initial" commit. Your final history should show two commits: one for the initial feature (combining the first two commits) and one for "chore: add more content".
What success looks like:
After running git log --oneline, you should see only two commits, and the first commit's message should reflect the combination of "feat: initial feature commit" and "fix: typo in first line" (or just "feat: initial feature commit" if you used fixup). Your test.txt should contain all three lines.
Frequently asked about Advanced Git Concepts
Study this next
Get the full quiz curriculum
Clone the complete plan to your dashboard for unlimited AI-generated notes, practice quizzes, and a personalised revision schedule.
Save this course free