4. Merge and the merge-conflict game¶
At a glance
Time: 2 periods · Tiers: 0–3 · You need: a printed 5-line poem per pair, two pen colours; your ward-facts repo with branches from Module 3
Before this: Module 3 (branches).
By the end you can: merge a branch, say whether Git did a fast-forward or made a merge commit, and calmly resolve a conflict.
Hook (5 min)¶
Two edits to the same line of the poem. Sita wrote "Rivers flow down to the Terai"; Hari wrote "Rivers rush to the plains". Who wins? Should a computer decide?
Understand it¶
Merging joins two lines of work¶
In Module 3 the history split into branches. Merging brings the work of one branch into another. You always merge into the branch you are on:
git switch main # go to the branch that should receive the work
git merge add-verse # bring add-verse's commits into main
Git can merge in two ways, depending on the shape of the history.
Case 1: fast-forward¶
If main has not moved since the branch was made, there is nothing to combine. Git simply slides the main label forward to the branch's newest commit:
before: c1 -- c2 [main] after: c1 -- c2 -- c3 [main] [add-verse]
\
c3 [add-verse]
No new commit is made. Git prints Fast-forward.
Case 2: merge commit¶
If both branches have new commits, Git makes a new merge commit with two parents — it joins the two lines:
before: c3 [fix-spelling] after: c3 -------.
/ / \
c1 -- c2 --+ c1 -- c2 --+ m [main]
\ \ /
c4 [main] c4 -------'
Git compares both branches with their common ancestor (c2, the last commit they share) and combines the changes automatically — as long as they changed different lines.
Conflicts: when a human must decide¶
If both branches changed the same lines of the same file, Git cannot know which version is right. It stops and marks the file with a conflict:
Mountains stand tall
<<<<<<< HEAD
Rivers flow down to the Terai <- the version on the branch you are on (main)
=======
Rivers rush to the plains <- the version from the branch you are merging
>>>>>>> fix-spelling
The morning is cold
| Marker | Means |
|---|---|
<<<<<<< HEAD |
start of your side (the current branch) |
======= |
divider |
>>>>>>> fix-spelling |
end of their side (the branch being merged) |
To resolve: edit the file so it says what it should say — keep one side, the other, or write a combination — and delete all three marker lines. Then git add the file (meaning "resolved") and git commit to finish the merge.
A conflict is not an error
A conflict is Git politely asking a human for a decision. Nothing is lost: both versions are in the file and in history. If you feel lost, git merge --abort puts everything back to before the merge.
Avoiding conflicts¶
Conflicts are normal in teams, but you can make them rare: merge often (small branches live short lives), split work by file or section, and talk before two people edit the same paragraph.
See it¶
A fast-forward, then a real conflict:
$ git switch main
$ git merge add-verse
Updating c26da4a..f60bbe5
Fast-forward
poem.txt | 1 +
1 file changed, 1 insertion(+)
(now main and fix-spelling both change line 2)
$ git merge fix-spelling
Auto-merging poem.txt
CONFLICT (content): Merge conflict in poem.txt
Automatic merge failed; fix conflicts and then commit the result.
$ git status
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 <file>..." to mark resolution)
both modified: poem.txt
(edit poem.txt: keep "Rivers rush down to the Terai", delete the markers)
$ git add poem.txt
$ git commit --no-edit
$ git log --oneline --graph --all
* 97832b0 (HEAD -> main) Merge branch 'fix-spelling'
|\
| * 3d873e6 (fix-spelling) Change line 2 to rush
* | be9221d Name the Terai in line 2
|/
* f60bbe5 (add-verse) Add sixth line about terraces
* c26da4a Add poem
The merge commit 97832b0 has two parents — you can see both lines joining in the graph.
Unplugged: the paper merge-conflict game (20 min)¶
Pairs share a printed 5-line poem — this is the common ancestor.
- Each partner gets a copy and edits it with their own pen colour: partner A changes lines 1 and 3; partner B changes lines 3 and 5.
- Merge: on a fresh sheet, combine both copies. Lines only one person changed: take that change (Git does this automatically). Line 3, changed by both: write the conflict with markers —
<<<<<<< A, A's line,=======, B's line,>>>>>>> B. - Resolve: the pair discusses and writes the final line 3, crossing out the markers.
- Write the rule on the board: Git can combine changes to different lines, but when both change the same line, a human decides.
PRIMM lab (40 min)¶
- Predict: you merge
add-verse(new lines) intomain. Will there be a conflict? Will it be a fast-forward? Rungit switch main,git merge add-verse. - Investigate:
git log --graph --oneline --all. Was it a fast-forward or a merge commit? How can you tell? - Create a conflict: make sure you have a
poem.txtcommitted onmain. Onfix-spellingchange line 2 and commit; onmainchange line 2 differently and commit. Predict, thengit merge fix-spelling. - Run
git status. Open the file, find the markers, decide the final line, delete the markers,git add poem.txt,git commit. - Investigate: draw the graph. How many parents does the merge commit have? Check with
git log --oneline --graph. - Modify: repeat with your partner changing different lines — no conflict. Then try
git merge --abortin the middle of a conflict and checkgit status. - Make: write a team rule for your pair project: who edits which file, and how often you merge.
Parsons practice (10 min)¶
Order for resolving a conflict: merge · open the file · edit and remove markers · git add · git commit.
Common mistakes¶
| Symptom | Cause | Fix |
|---|---|---|
Markers <<<<<<< left in the file and committed |
forgot to delete them | edit the file, remove markers, commit again; search with git grep "<<<<<<<" |
| Merged in the wrong direction | ran merge on the wrong branch | check git status first; git merge --abort if not finished |
| Vim opens for the merge message | merge commit needs a message | :wq to accept, or git commit --no-edit |
fatal: You have not concluded your merge |
a merge is still in progress | finish (add + commit) or git merge --abort |
| "Git deleted my line!" | you chose the other side | it is still in the branch's commit; git show fix-spelling:poem.txt |
Practise more with free resources¶
| # | Exercise | Tier | Time | Hand in |
|---|---|---|---|---|
| 1 | Learn Git Branching intro3 "Merging in Git". |
1 / 3 | 10 min | goal graph drawing |
| 2 | Software Carpentry Conflicts: do the exercise "Solving Conflicts that You Create". | 1 / 3 | 30 min | your resolved file + log |
| 3 | Pro Git §3.2 Basic Branching and Merging: find the figures for fast-forward and for the three-way merge. Label the common ancestor. | 3 | 20 min | labelled sketch |
| 4 | GitHub Skills Resolve merge conflicts (13+, account, internet). | 3 | 45 min | completed course |
| 5 | Conflict cards (paper): the teacher hands out 6 pairs of edits; decide for each: no conflict / fast-forward / conflict. | 0 | 10 min | answers |
Exit ticket (5 min)¶
- When does a conflict happen?
- What do the markers mean?
- Misconception: "After a conflict my work is lost." True or false?
Key points¶
git merge <branch>brings that branch's work into the current branch.- Fast-forward: the label just moves; merge commit: a new commit with two parents.
- Git merges changes to different lines automatically; the same lines → conflict → a human decides.
- Resolve: edit, remove markers,
git add,git commit. Escape:git merge --abort. - Merge often, split work, talk — fewer conflicts.
New words¶
merge, fast-forward, merge commit, common ancestor, conflict, conflict markers — see the glossary.
Extension quest¶
After a merge commit, run git log --first-parent --oneline. What does it hide? Why might a team like this view?
Teacher notes¶
- Timing: P1: hook 5, understand 15, paper game 20. P2: see it (live on projector) 5, lab 25, Parsons 5, exit 5.
- Students panic at conflicts. Normalise: conflicts are Git asking for a human decision.
git merge --abortreturns to before the merge. Make a conflict on purpose in front of the class and resolve it slowly, thinking aloud. - In VS Code, a conflicted file shows buttons Accept Current / Accept Incoming / Accept Both — fine to use, but students must still understand the markers.
- Conflict cards (exercise 5) answers: same line both sides → conflict; different lines → merge commit, no conflict; only one side changed → fast-forward; one side adds a line at the end, other edits line 1 → no conflict; both add different lines at the end → conflict (same place); one renames the file, other edits it → usually no conflict (Git detects renames).
- Fallback Tier 0: the paper game plus exercise 5.
- Answer key: Exit 1: when both branches changed the same lines (or one deleted a file the other changed). 2: start of current side / divider / end of incoming side. 3: False — both versions are kept until you decide.