Lesson 3 of 7 in Branching & Merging
Merge commits
Story: Two timelines that both moved on can't just be lined up. Juno will show you how to join them.
A fast-forward only works while your branch hasn't moved since the other one split off. Often both have: you committed on main while contact was still in progress. The branches have diverged: each has commits the other doesn't.
A merge commit joins two branches
git merge contact can't fast-forward then. Instead, git makes a merge commit: a new commit on the branch you're on, with two parents, your branch's commit and the other branch's. Its files combine the changes made on both sides since they split.
$ git merge contact
Merge made by the 'ort' strategy.
contact.html | 1 +
1 file changed, 1 insertion(+)
create mode 100644 contact.html
ort is the name of the method git uses to combine the changes; you can ignore it. Below it, git sums up what the merge brought into your files.
A merge commit gets a ready-made message, Merge branch 'contact'. On your own computer, git first opens your text editor with that message, so you can change it; saving it as it is is fine.
Only the branch you're on moves. contact still points at its own commit, which is now in main's history too, so git branch -d contact can delete it.
When both branches changed the same lines of the same file, git can't combine them by itself. That's a merge conflict, and it's the next Lesson. In this one, the branches always change different files.
Reading a merge in the history
git log --oneline --graph draws the two lines of history and where they join:
* 1c0c498 (HEAD -> main) Merge branch 'contact'
|\
| * 5b2a470 (contact) Add a contact page
* | a6b0f1b Make the heading purple
|/
* a4b8d97 Style the heading
* ab89288 Add the home page
* 37d7cf7 Add a README
A merge commit on purpose: --no-ff
When a merge can fast-forward, git merge does, and afterwards nothing in the history shows that those commits were ever on a branch of their own. git merge --no-ff <branch> ("no fast-forward") makes a merge commit anyway. Many teams merge finished work this way: the work's commits stay grouped behind one merge commit, which is easy to find later.
When the branches have diverged, --no-ff changes nothing: git makes a merge commit either way.
| Command | What it does |
|---|---|
git merge <branch> |
Fast-forwards when it can. When the branches have diverged, makes a merge commit that joins them. |
git merge --no-ff <branch> |
Always makes a merge commit, even when git could fast-forward. |
New commands
git merge --no-ff
Explainer: A merge commit joins two lines of history
Graph as text
project: your repo, you are here
- HEAD → main at 8018408 "Merge branch 'footer'"
Branches and tags
- contact at 5b2a470 "Add a contact page"
- footer at 0d0f228 "Add a footer"
- main at 8018408 "Merge branch 'footer'"
Commits, newest first
- 8018408 "Merge branch 'footer'"; parents 1c0c498 and 0d0f228; refs: HEAD → main
- 0d0f228 "Add a footer"; parent 1c0c498; refs: footer
- 1c0c498 "Merge branch 'contact'"; parents a6b0f1b and 5b2a470
- a6b0f1b "Make the heading purple"; parent a4b8d97
- 5b2a470 "Add a contact page"; parent a4b8d97; refs: contact
- a4b8d97 "Style the heading"; parent ab89288
- ab89288 "Add the home page"; parent 37d7cf7
- 37d7cf7 "Add a README"; no parent
Challenge 1 of 3
Story: Both timelines moved on while you were away, Agent. Join them.
Since contact-page was made, both it and main have a new commit: a contact page on contact-page, and a purple heading on main. Merge contact-page into main, so main has both. You're on main.
Unlocks after Basics.
Terminal
Unlocks after Basics.
This Lesson can be played once Basics is complete. Its text and Explainer are open to everyone.