Why this session kills the fear
Ask ten builders what scares them about git and nine say "merge conflicts". The fear comes from one wrong belief: that a conflict means you broke something. You did not. A conflict is git being honest - it hit two edits to the same line, it will not silently pick one, so it stops and asks. That is a feature. Once you have resolved five of them the panic is gone and it becomes a 30-second reflex. By the end of today you will manufacture a conflict on purpose, resolve it, and understand exactly when to merge versus rebase.
<<<<<<< ======= >>>>>>> markers on sight, a clean resolve-add-commit reflex, the abort escape hatch when you want out, and a clear rule for merge versus rebase (plus stash and cherry-pick as surgical tools) - so conflicts stop being scary and become routine.
Why conflicts happen and how to read them 5 min live
A conflict happens for exactly one reason: two branches changed the same lines of the same file, and git cannot know which version you want. For every other change - different files, different lines - git merges automatically and you never notice. When it truly cannot choose, it does the responsible thing: it writes both versions into the file, wrapped in markers, and pauses so you can decide. Read the markers top to bottom: your side (HEAD) is above, their side (incoming) is below.
LiveThe three marker lines, decoded3 min▶
<<<<<<< HEAD- everything below this until the divider is your version, the branch you are currently on.=======- the fence. Above it is yours, below it is theirs. It marks nothing itself; it just separates the two sides.>>>>>>> branch-name- everything from the divider up to here is the incoming version, from the branch you are merging in.- Conflicts are normal and safe. Git did not lose anything - it paused with both versions visible.
git statuslists every file still to resolve under "Unmerged paths".
Self-studyWhy most merges have zero conflicts2 min read▶
Git merges at the line level, not the file level. Two people editing the same file rarely conflict - they conflict only when they touch the same lines. Different functions, different sections, different files all merge cleanly and automatically. This is why active teams merge dozens of branches a day and see conflicts only occasionally.
The practical takeaway: the way to reduce conflicts is not to avoid branching - it is to keep branches short-lived and pull main often, so your line and their line rarely drift apart before you combine them.
Resolve it, in editor or on the web 4 min live
Resolving is four moves: open the file, choose the right combination, delete all three marker lines, then stage and commit. The choice is not always "mine or theirs" - very often the right answer is both, edited together into one coherent line. Editors help: VS Code and the GitHub web editor both show accept-current / accept-incoming / accept-both buttons above each conflict.
LiveThe resolve loop, and the abort escape hatch2 min▶
- Pick the combination, not a side. Read both versions, write the line you actually want - often a blend. There is no rule that says you must keep one intact.
- Delete every marker line. The
<<<<<<<,=======, and>>>>>>>lines must all be gone. If a build later complains about "unexpected<<<", you left a marker in. - Stage, then finish.
git addthe resolved file (that tells git "this one is handled"), thengit commitfor a merge, orgit merge --continue/git rebase --continuedepending on what you were doing. - Want out?
git merge --abort. It resets you cleanly to the moment before the merge, as if you never started. No damage. Panic button, fully safe.
Every engineer remembers their first conflict - it looks like the terminal caught fire and it can eat 20 minutes of pure dread. The tenth one takes 30 seconds. Conflict resolution is pure pattern recognition; the only way through is reps. And the tempting mistake - avoiding branches so you never hit a conflict - backfires badly: it produces giant, weeks-old merges that conflict on everything at once. Small, frequent merges are how teams stay conflict-light.
Self-studyResolving in the GitHub web editor2 min read▶
When a PR reports "This branch has conflicts that must be resolved", GitHub offers a web conflict editor right in the browser - no local checkout needed. It shows the same markers with the same accept buttons, and a "Mark as resolved" then "Commit merge" flow. It is perfect for a small text conflict (a README, a config line) you want to clear without switching context.
For anything with logic - code that has to actually run after the merge - resolve locally in your editor where you can run the tests before you commit. The web editor cannot run your build.
Merge vs rebase, and two surgical tools 6 min live
There are two ways to bring one branch's work into another. Merge ties the two histories together with a merge commit that has two parents - it preserves exactly what happened, when. Rebase lifts your commits off your branch and replays them one by one on top of the latest main - a clean, linear history, but it rewrites your commit hashes. Both are correct; they optimize for different things.
LiveThe golden rule, and when to reach for each3 min▶
- Merge for shared branches. Bringing a finished feature into
main, or integrating a long-lived branch for a release - use merge. The merge commit documents when and where the integration happened, and it never rewrites anyone's history. - Rebase for tidying your own local work. Before you open a PR, rebase your messy local branch onto the latest
mainfor a clean, linear story. Fine, because those commits are still yours alone. git stash- shelve dirty work. Mid-edit and need to switch branches urgently?git stashtucks your uncommitted changes away,git stash popbrings them back. A clean pocket, not a commit.git cherry-pick <hash>- grab one commit. Want just one bugfix from another branch without merging all of it? Cherry-pick copies that single commit onto your current branch by its hash.
Self-studyInteractive rebase to polish before a PR advanced2 min read▶
git rebase -i main opens an interactive editor listing your local commits, and lets you squash several messy commits into one, reword unclear messages, or drop a commit entirely before you open the PR - so reviewers see a clean, deliberate story instead of "wip", "fix", "fix again". It is the single best way to make your history read well. This is advanced and strictly for your own unpushed commits - the golden rule still applies: never interactive-rebase anything you have already shared.
Manufacture and resolve a conflict ★ 10 min · everyone types
The fastest way to lose the fear is to cause a conflict on purpose in a safe place. We do exactly that in your my-project repo.
On main, edit line 1 of README.md to something like # My Project - a tagline. Then git add README.md and git commit -m "Add tagline to README".
Make the colliding branch from an earlier point: git switch -c conflict-demo HEAD~1. Edit the same line 1 differently - # My Project - built in public - then git add README.md and git commit -m "Reword README heading".
Go back and merge it in: git switch main, then git merge conflict-demo. Git stops and reports a conflict in README.md - this is the moment. Run git status and read "Unmerged paths".
Open README.md. Find the three markers, keep the combination you actually want (try blending both), and delete the <<<<<<<, =======, and >>>>>>> lines.
git add README.md, then git commit to finish the merge. Finally git log --graph --oneline --all - see the merge commit tie both lines together. You just did the scary thing. It was fine.
Merge, rebase, or neither? ★ 6 min · everyone sorts
Now cement the judgment. Drag each situation to the right way of combining work. Green means correct - if you are unsure, guess and read the "why".
The stash drill ★ 6 min · everyone types
Stash is the tool you did not know you needed until an urgent hotfix lands while your working tree is a mess. Feel it shelve and restore.
On any branch of my-project, make a dirty edit - change a line in notes.md but do not commit it. Run git status and see it modified.
git stash. Run git status again - your working tree is clean, the edit is shelved. It did not disappear; it is in the stash.
git switch main (or any other branch), do a quick imaginary hotfix, then git switch back to where you were.
git stash pop. Your dirty edit is restored exactly as it was. That is the whole loop: shelve, switch, restore.
Optional cherry-pick: run git log --oneline conflict-demo, copy one commit hash, then on main run git cherry-pick <hash> to graft just that one commit across.
git stash list shows every shelved change; git stash pop takes the most recent, git stash apply stash@{1} takes a specific one. It is a stack, so you can shelve more than one thing.
This week ◐ 25 min total
- Cause and resolve three conflicts on a throwaway repo - not my-project, somewhere you can be reckless. Reps are what kill the fear; by the third one it is muscle memory.
- Rebase a local branch onto
mainbefore your next PR and watch the history go linear. Confirm the commits are still local first. - Read the interactive-rebase self-study card and try
git rebase -i mainon a branch with a couple of throwaway commits - squash two into one. - Optional deep end: the official Resolve merge conflicts Skills exercise (github.com/skills/resolve-merge-conflicts) - a full guided conflict in a real repo.
Three questions before you go 🎯 ◐ 90 seconds
1 · In a conflict, what does the ======= line separate?
The divider fences the two versions: everything above it is HEAD (your current branch), everything below it up to the >>>>>>> marker is the branch you are merging in.
2 · What is the golden rule of rebase?
Rebase rewrites history and gives commits new hashes. If others already have the old commits, rebasing shared history hands everyone conflicting copies. Rebase your local work only.
3 · What does git merge --abort do?
It is the fully safe escape hatch - it undoes the in-progress merge and returns your working tree to exactly where you were before, as if nothing happened.
Official GitHub Skills coverage
This session maps to GitHub's own free CLI-based Skills exercises. Here is what today covers in full, and what the official exercises add.
Session 4 cheat sheet · pin this
<<<<<<< HEAD = yours (above) · ======= = divider · >>>>>>> branch = theirs (below).git add → git commit.git merge --abort resets you to before the merge. Fully safe.git stash / stash pop to shelve dirty work · git cherry-pick <hash> for one commit.