Git: Beginner to Advanced
Merging
Bring branches together and resolve conflicts.
Lesson 5 of 12
Reading: about 7 min
Lesson + practice: about 15 min
Difficulty: Intermediate
On this page5 sections
Bring branches together and resolve conflicts. Follow the animated example, then use the sections below to review each idea.
Visual walkthrough
Use the player controls or jump menu to inspect each step. The diagram changes as the example moves forward.
The player shows one focused example. The sections below explain the ideas behind each topic.
Merging brings the work from one branch into another. You switch to the branch that should receive the work, usually main, and run git merge with the name of the branch to bring in.
Git handles three situations: it can move main forward, create a merge commit that joins two lines of work, or stop and ask you to settle a conflict. This lesson walks through all three on the study planner project. Commit IDs in your repository will differ.
Fast-forward merges
If main has not changed since the branch started, the branch's commits sit directly on top of it. Git does not need to combine anything: it moves main forward to the branch's latest commit. This is a fast-forward.
Merge a branch when main has not moved
The output says Fast-forward. No new commit is created, and the graph stays a straight line: main now points at Fix README wording.
git switch main
git merge fix-typo
git log --oneline --graph --all$ git switch main
Switched to branch 'main'
$ git merge fix-typo
Updating 66db61f..bc92f4a
Fast-forward
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git log --oneline --graph --all
* bc92f4a Fix README wording
* 66db61f Describe the project
* 5b0bb3a Add README and appMerge commits
When both branches have new commits, main cannot simply move forward. Git combines the two lines of work and records the result in a merge commit, a commit with two parents.
Join two lines of work
Here main gained Add start instructions while search gained Add search. They changed different files, so Git merges them automatically. --no-edit accepts Git's default message instead of opening an editor.
git log --oneline --graph --all
git merge search --no-edit$ git log --oneline --graph --all
* bb8560f Add start instructions
| * d92b725 Add search
|/
* bc92f4a Fix README wording
* 66db61f Describe the project
* 5b0bb3a Add README and app
$ git merge search --no-edit
Merge made by the 'ort' strategy.
search.js | 1 +
1 file changed, 1 insertion(+)
create mode 100644 search.jsRead the merged history
The two lines meet again at Merge branch 'search'. Its two parents are the previous tip of main (bb8560f) and the tip of search (d92b725).
git log --oneline --graph
git log -1 --format="%h %s (parents: %p)"$ git log --oneline --graph
* 48f925c Merge branch 'search'
|\
| * d92b725 Add search
* | bb8560f Add start instructions
|/
* bc92f4a Fix README wording
* 66db61f Describe the project
* 5b0bb3a Add README and app
$ git log -1 --format="%h %s (parents: %p)"
48f925c Merge branch 'search' (parents: bb8560f d92b725)Once a branch is merged, you can delete its name. The commits stay in history; only the label goes. git branch -d checks that the work is merged before deleting:
$ git branch -d search
Deleted branch search (was d92b725).Conflict markers
A conflict happens when both branches changed the same lines differently. Git cannot know which version you want, so it stops part-way through the merge and asks you to decide. Nothing is lost: both versions are kept in the file.
In this example, main reworded the start line to “Start with npm start.” while docs changed it to “Run npm run dev to begin.”
Git pauses on a conflict
git status says the merge is unfinished and lists the conflicted file under “Unmerged paths”. It also tells you the two ways forward: fix the conflicts and commit, or abort.
git merge docs
git status$ git merge docs
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
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: README.md
no changes added to commit (use "git add" and/or "git commit -a")Read the markers
Everything outside the markers merged cleanly. Between <<<<<<< HEAD and ======= is your branch's version (main). Between ======= and >>>>>>> docs is the incoming branch's version.
cat README.md# Study planner
Track your study sessions.
<<<<<<< HEAD
Start with npm start.
=======
Run npm run dev to begin.
>>>>>>> docs| Marker | Meaning |
|---|---|
| <<<<<<< HEAD | Start of the version on the branch you are on |
| ======= | Divider between the two versions |
| >>>>>>> docs | End of the version from the branch being merged in |
Resolve and verify a merge
To resolve, edit the file into the version you actually want. That can be one side, the other, or a mix. Then delete all three marker lines.
- Open the conflicted file and decide on the final text.
- Remove every
<<<<<<<,=======and>>>>>>>line. - Run
git diff --checkto catch any marker you missed. - Stage the file with
git addto tell Git it is resolved. - Run
git committo finish the merge.
A missed marker is easy to catch
Run this before staging. It lists any leftover marker lines; once the file is clean, it prints nothing.
git diff --checkREADME.md:3: leftover conflict marker
README.md:5: leftover conflict marker
README.md:7: leftover conflict markerHere the final line becomes “Run npm run dev to start.”, keeping the dev command from docs with clearer wording.
Stage the fix and finish the merge
M in the first column means the resolved file is staged. git commit --no-edit creates the merge commit with Git's default message. The graph shows the two lines joined, and the file holds the text you chose.
git add README.md
git status --short
git commit --no-edit
git log --oneline --graph -4
cat README.md$ git add README.md
$ git status --short
M README.md
$ git commit --no-edit
[main b2255c7] Merge branch 'docs'
$ git log --oneline --graph -4
* b2255c7 Merge branch 'docs'
|\
| * 8509eff Use dev command
* | da031b3 Reword start line
|/
* 48f925c Merge branch 'search'
|\
$ cat README.md
# Study planner
Track your study sessions.
Run npm run dev to start.main has not changed since you created the branch feature. What does git merge feature do?
Reveal answer
It fast-forwards: main moves to the tip of feature, and no merge commit is created. The history stays a straight line.
Halfway through resolving a conflict you realise you merged the wrong branch. How do you get back to where you started?
Reveal answer
Run git merge --abort. It cancels the merge and restores your files to how they were before you ran git merge, provided you had no uncommitted edits when you started.
Your progress
Reveal the check answer or reach the end to complete this lesson.