Resolve conflicts
Intermediate IntelliJ UI
Why this matters
Conflicts are where people abandon graphical tools. IntelliJ's merge dialog is the reason not to: it shows the base, the version both sides started from, which is exactly the information raw conflict markers hide (lesson 11.2).
The first dialog
A merge, rebase or update that conflicts opens a dialog listing the conflicted files, with three choices per file:
| Choice | Keeps |
|---|---|
| Accept Yours | Your branch's version of the whole file |
| Accept Theirs | The incoming version of the whole file |
| Merge | Opens the three-pane dialog to decide line by line |
The first two are whole-file decisions and are usually wrong for documentation, where both sides normally contain something worth keeping. Merge is the one to use.
The merge dialog
| Pane | Is | Editable |
|---|---|---|
| Left | Your version, on the branch you are on | No |
| Middle | The Result: what will be committed | Yes |
| Right | Theirs, the incoming version | No |
The middle pane starts from the base revision, the last version both sides shared. That is what makes this dialog better than markers: you can see what the sentence said before either person touched it, which usually makes the right resolution obvious.
Between the panes, each changed block has accept and ignore controls, so a resolution is built by taking blocks from either side, or by typing in the middle.
Three helpers:
- Apply All Non-Conflicting Changes takes everything the two sides did not disagree about, leaving only the real conflicts.
- The magic wand on a simple conflict resolves it in one click.
- Resolve using Left / Resolve using Right in the context menu, for one block.
When every conflict is decided, Apply Changes moves to the next file and Accept and Finish completes the merge for all of them.
Finishing, or escaping
| Situation | Action |
|---|---|
| All files resolved | The merge is staged; commit it from the Commit window |
| You want out of a merge | Git → Abort Merge, or the banner in the Git tool window |
| You want out of a rebase | Git → Abort Rebase |
| You resolved wrongly and have not committed | Re-open the conflict from the Commit window, or abort |
Aborting returns you exactly to where you were (lesson 12.6). It is a legitimate choice when the correct resolution needs a conversation with whoever wrote the other side.
Reading the result before committing
After resolving, before committing, read the diff of the merged file in the Commit window. Two problems are visible there and nowhere else:
- A leftover marker, if you edited by hand rather than through the dialog.
- A half-resolved sentence that combines both wordings and says something neither author meant.
Ten seconds, and it is the difference between resolving a conflict and appearing to.
How to do it
The same conflict in commands, for comparison:
$ git status
$ git diff
# edit
$ git add docs/faq.md
$ git commitThe terminal equivalent of IntelliJ's base pane is the better marker style (lesson 11.2):
$ git config --global merge.conflictstyle zdiff3The merge editor has Incoming, Current and Result, and does not show the base by default. See lesson 15.7.
- The conflicts dialog: Accept Yours, Accept Theirs, Merge
- In the merge dialog: Apply All Non-Conflicting Changes, the magic wand, Apply Changes, Accept and Finish
- Git → Abort Merge or Abort Rebase
- Find Action (⇧⌘A) → "Resolve Conflicts"
Simple conflicts can be resolved on the merge request page; anything needing judgement is better done here, and GitLab says so (lesson 11.4).
The same, with a web editor for simple cases.
Common mistakes
- Choosing Accept Yours or Accept Theirs for a whole file to make the dialog go away, silently discarding the other person's work.
- Assuming the left pane is always yours. During a rebase it is not.
- Ignoring the base pane, which is the reason to use this dialog.
- Editing conflict markers by hand in the editor instead of using the dialog, then leaving one behind.
- Committing without reading the merged file.
Try it yourself
Goal: resolve a conflict using the base.
- On your practice project, create two branches that change the same line of
docs/faq.mddifferently, and commit both. - Merge one into the other from the branch popup, and choose Merge in the conflicts dialog.
- Read the middle pane before touching anything: that is the version both sides started from.
- Build the resolution by taking one block from each side, then edit the middle pane so the sentence reads properly.
- Accept and Finish, read the diff in the Commit window, and commit.
Expected result: a resolved conflict whose result is a sentence you wrote, informed by seeing what the line said before either branch changed it.
Show solution
Step 3 is the whole lesson. Raw conflict markers show two versions and hide the third, so you cannot tell which side changed what. The base pane restores it, which is why a conflict that looks like a judgement call in the terminal is often obvious here.