Resolve in the terminal; continue or abort
Intermediate Git CLI
Why this matters
Every conflict, in every tool, is the same four steps. Doing them once in the terminal makes every graphical merge tool obvious afterwards, because you will know what its buttons are for.
The four steps
- Find the conflicted files.
git status, orgit diff --name-only --diff-filter=Ufor just the list. - Edit each one to the text you want, deleting every marker line.
- Mark it resolved:
git add <file>. This is what tells Git you have decided. - Finish:
git commitfor a merge,git rebase --continuefor a rebase.
That is the whole procedure. Everything below is what each step looks like.
Step 1: find them
$ git statusOn branch main
Your branch and 'origin/main' have diverged,
and have 1 and 1 different commits each, respectively.
(use "git pull" if you want to integrate the remote branch with yours)
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: docs/faq.md
no changes added to commit (use "git add" and/or "git commit -a")both modified under Unmerged paths is the conflict. Files that merged cleanly are already staged and are not shown here.
Step 2: edit
Open the file in your editor and turn the marker block into the text you want:
<<<<<<< HEAD
Yes. It is a practice project and costs nothing.
||||||| b6ae751
Yes. It is a practice project for the Git Course and can be used, changed and shared freely.
=======
Yes. It is free for everyone, including commercial use.
>>>>>>> e3e760c6c090dbae77da2af1ffc203d5550dfae5Yes. It is free for everyone, including commercial use, and costs nothing.Three things about that: the result is neither side, which is normal and often best; every marker line is gone, including the ||||||| and the ancestor text; and nothing outside the block was touched.
You are not limited to editing by hand. To take one side wholesale:
$ git checkout --ours docs/faq.md # your version
$ git checkout --theirs docs/faq.md # theirsAnd to start the file over if you make a mess of it:
$ git checkout --merge docs/faq.mdThat restores the conflicted state with the markers back, as if you had not started.
Step 3: mark it resolved
$ git add docs/faq.md
$ git statusOn branch main
Your branch and 'origin/main' have diverged,
and have 1 and 1 different commits each, respectively.
(use "git pull" if you want to integrate the remote branch with yours)
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: docs/faq.md"All conflicts fixed but you are still merging" is the sentence to wait for. Until it appears, at least one file is still unresolved.
Step 4: finish
$ git commit[main 628abe1] Merge branch 'main' of https://gitlab.com/northwind-trails/trailguideGit supplies the merge message itself and opens your editor with it pre-filled; save and close to accept. --no-edit skips the editor. There is no need to describe the resolution in the message, though a line about a non-obvious decision helps reviewers.
$ git log --oneline --graph -4* 628abe1 Merge branch 'main' of https://gitlab.com/northwind-trails/trailguide
|\
| * e3e760c docs: clarify licence answer (#41)
* | bc7b919 docs: shorten licence answer (#41)
|/
* b6ae751 feat: add difficulty filter docs (#21)The fork and join show both versions of the work preserved, with your resolution in the merge commit. Then push.
The escape hatches
| Situation | Command | Effect |
|---|---|---|
| Changed your mind entirely | git merge --abort |
Everything back to before the merge |
| Made a mess of one file | git checkout --merge <file> |
That file back to the conflicted state |
| Staged too early | git reset <file> then re-edit |
Un-marks it as resolved |
| Mid-rebase instead of merge | git rebase --abort |
Lesson 11.5 |
git merge --abort is safe and complete: it restores the working tree and the index to the state before the merge started. Use it freely; nothing is lost, and you can start again whenever you like.
Do and don't
Do
- Read both sides before deciding; the answer is often a combination.
- Search the file for
<<<after editing, every time. - Run the tests or the preview after resolving, before staging.
- Use
git merge --abortwhenever you want to think again.
Don't
- Don't stage a file you have not re-read.
- Don't resolve someone else's area by guessing; ask, or keep their side.
- Don't edit outside the marker block while you are there.
- Don't leave a merge half-finished overnight; abort and redo it fresh instead.
Common mistakes
- Committing a marker line. Search for
<<<; some editors highlight them, and many linters fail on them. - Forgetting
git add.git committhen refuses:error: Committing is not possible because you have unmerged files. - Resolving by deleting the whole block, losing both sides. If the section should be gone, that is a decision worth a note in the merge request.
- Using
--oursduring a rebase expecting your own work. The sides are swapped there (lesson 11.5). - Pulling again mid-conflict. Finish or abort first; Git refuses while a merge is in progress.
Try it yourself
Goal: resolve a real conflict end to end.
- Recreate the conflict: on
main, change the first FAQ answer one way and commit; on a branchdocs/conflict-democreated from before that change, change the same line another way and commit; then frommain,git merge docs/conflict-demo. git statusand note "both modified".- Open the file, write a resolution that keeps the meaning of both, delete every marker line.
git add docs/faq.md, thengit statusand read "All conflicts fixed but you are still merging".git commit --no-edit, thengit log --oneline --graph -3.
Expected result: the graph shows a merge commit joining the two lines, and the FAQ contains your combined sentence with no markers.
Show solution
If step 5 refuses with "Committing is not possible because you have unmerged files", step 4 did not happen for every conflicted file; git status lists what remains. If you want to try a different resolution, git reset --hard HEAD~1 on this practice merge removes it, or start over with git merge --abort before committing.