Learning outcomes

  • Explain the relationship between local repository, remote and remote-tracking branch

  • Resolve a merge conflict and verify the result

  • Explain why a conflict is a normal event and not a failure

  • Recover from the common broken states — diverged branches, rejected push, accidental commit on main

  • Resolve a conflict and a rejected push in IntelliJ, and name the git command behind every step

Local, remote, and the copy in between

git remotes

origin/main is not the remote. It is your local note of where the remote’s main was when you last fetched. git pull is git fetch followed by git merge — one command doing two things, which is why its failures confuse.

git remote -v            # which remotes exist
git fetch                # update the notes, change nothing else
git status               # ahead / behind / diverged
git pull                 # fetch + merge
git push                 # send your commits

Conflicts

A conflict happens when two branches changed the same lines and git cannot decide which version wins. That is not a failure of git — it is git refusing to guess.

<<<<<<< HEAD
    return members.size() / groups;
=======
    return groups == 0 ? 0 : members.size() / groups;
>>>>>>> feature/guard-empty-groups

Resolving it means: read both sides, decide what the code should do, delete the markers, and test. Then git add the file and continue the merge.

git merge feature/guard-empty-groups   # conflict reported
git status                             # which files conflict
# edit, remove all <<<<<<< ======= >>>>>>> markers
git add Attendance.java
git commit                             # completes the merge
git merge --abort                      # or: get out and think again

The two rules that prevent most conflicts: short-lived branches, and small changes. The rule that makes them harmless: resolve them yourself, at the moment they appear, on your own branch — never in a hurry on main.

Common broken states

Symptom What it means and what to do

! [rejected] main → main (fetch first)

the remote has commits you do not have — git pull, resolve, push again

Your branch and 'origin/main' have diverged

both sides have new commits — merge them; do not force-push

You committed to main by accident

git switch -c feature/x (takes the commits with you), then git switch main && git reset --hard origin/main

git push --force is suggested online

do not, on a shared branch. It deletes other people’s commits

The same work in IntelliJ

Day to day you will do most of this in IntelliJ, and for conflicts that is the better tool: three panes side by side show more than three marker lines. Every button is still one of the commands above — and in the examination, and when you ask for help, you name the command, not the button.

Situation In IntelliJ Underneath

update the notes

Git | Fetch, or the fetch icon in the VCS widget

git fetch

bring the remote’s commits in

Git | Update Project (Ctrl+T, macOS Cmd+T), strategy Merge

git fetch + git merge

send your commits

Git | Push (Ctrl+Shift+K, macOS Cmd+Shift+K)

git push

merge a branch into the current one

branch name in the title bar → the branch → Merge '…' into 'main'

git merge <branch>

see where things stand

Commit tool window (Alt+0) and the Log tab of the Git tool window (Alt+9)

git status, git log --graph

The VCS widget in the title bar shows a blue arrow next to the branch when the remote has commits you have not merged, and a green one when you have commits not yet pushed — `git status’s "behind" and "ahead", as icons. Both are only as fresh as the last fetch.

Resolving a conflict

A merge that hits a conflict opens the Files Merged with Conflicts dialog. It lists the conflicted files — the "Unmerged paths" of git status — and offers three buttons per file:

Button What it does

Accept Yours

takes your branch’s version of the whole file and marks it resolved (git checkout --ours + git add)

Accept Theirs

takes the incoming branch’s version of the whole file (git checkout --theirs + git add)

Merge…

opens the three-pane merge tool — the one to use

The first two are the "take my side wholesale" pitfall, built in as a single click. Use them only for a file you have read and know one side to be right, such as a generated file.

git intellij merge
Figure 1. The merge tool: two read-only sides, one editable result

Work through it in this order:

  1. Apply Non-Conflicting Changes in the toolbar. It takes over everything git could merge on its own — the changes only one side made. What is still highlighted red afterwards is the real conflict, and usually it is small.

  2. Read both sides of each red block. >> and << copy one side into the result, the cross discards it. Often the right answer is neither side alone: type the combination into the middle pane.

  3. Finish the file (Apply, or Accept and Finish). IntelliJ marks it resolved, which is git add — there are no markers to forget, the result pane never contained any.

  4. Build and test. The tool proves the file is free of conflicts, not that the code is right.

  5. Commit the merge if IntelliJ has not done it yet: the Commit tool window then holds the merge with a prefilled Merge branch … message. The Log tab shows afterwards whether the merge commit exists — check it there, not by memory.

Closing the dialog does not end the merge. The conflicts stay, as a Merge Conflicts node in the Commit tool window, until you resolve them or choose Abort Merge — which is git merge --abort. A conflict produced on the command line shows up in the same node, so you can start in the terminal and resolve in the IDE.

A rejected push

When the remote has commits you do not have, Git | Push ends in the Push Rejected dialog with two choices, Merge and Rebase. In this course choose Merge: it is git pull followed by git push, the same repair as on the command line, and a conflict on the way opens the dialog above.

The push dialog can also force a push. The rule does not change because the command is behind a drop-down: not on a shared branch.

Decisions

  • Nobody force-pushes a shared branch. If a history really must be rewritten, the team does it together, on purpose, once.

  • Conflicts are resolved on the feature branch, before the pull request is merged.

  • git pull before you start working, and before you push.

  • A resolved conflict is only resolved once the build passes — the markers being gone proves nothing.

  • Conflicts may be resolved in IntelliJ’s merge tool, and usually should be. You still have to be able to say which git commands it ran.

Pitfalls

  • Resolving a conflict by taking "your" side wholesale. Half the time the other side contained the fix.

  • Leaving a stray ======= in the file. It compiles in some languages, which is worse than a syntax error.

  • Believing git fetch changed your files. It updates the remote-tracking branch only — that is what makes it the safe command.

  • Pulling with uncommitted changes and then being unable to explain the state. Commit or stash first.

  • Clicking Accept Yours in IntelliJ’s conflict dialog because it is the first button. It throws away the other side of the whole file, including the parts git could have merged on its own.

  • Closing IntelliJ’s conflict dialog and assuming the merge is over. It is still in progress until every file is resolved and the merge is committed — or aborted.

Terminology

Deutsch English

Konflikt

conflict

Gegenstelle, entferntes Repository

remote

holen / zusammenführen / senden

fetch / merge / push

auseinandergelaufen

diverged

Konfliktmarkierung

conflict marker

Zusammenführungswerkzeug

merge tool

Further reading