GitHub

How to Resolve Conflicts in GitHub Code

How to Resolve Conflicts in GitHub Code

Open the pull request, click Resolve conflicts, edit each marked file and click Commit merge. If the conflict is too awkward for the browser, fix the files locally and push the result. Both routes leave a pull request the Merge pull request button can finish.

Git can’t safely pick a side when two branches change the same line, or when one branch edits a file the other deletes. Until someone settles it, GitHub keeps Merge pull request deactivated (GitHub Docs, as of October 2026).

The web editor deals with competing line changes only, and committing there merges the entire base branch into the head branch. Anything involving a deleted file needs a local clone.

How to resolve merge conflicts in GitHub with the web conflict editor

Everything happens in the browser here, so there’s no clone to set up.

  1. Click Pull requests under the repository name and open the pull request that shows the conflict warning.
  2. Click Resolve conflicts near the bottom of the page. The editor lists every conflicting file on the left.
  3. Decide what stays: your lines, the other branch’s lines, or a new mix of both. Delete the three marker lines.
  4. Scroll to the next set of markers in the same file and repeat.
  5. Click Mark as resolved when the file is clean.
  6. Pick the next file under “conflicting files” and repeat until none are left.
  7. Click Commit merge, answer any branch prompt, then click Merge pull request.

That last click has its own options, since squash and rebase behave differently from a plain merge. This walkthrough on merging branches in GitHub goes through all of them.

What Commit merge does to the head branch

Committing a resolution on GitHub merges the entire base branch into the head branch, not only the files you edited (GitHub Docs, as of October 2026). Make sure that branch is where the commit should land.

If the head branch is the default branch, GitHub lets you update it anyway or create a new head branch for the pull request. A protected head branch can’t take the update, so GitHub prompts for a new one. On any other branch the merge commit simply lands there.

Fix with Copilot

If you have access to Copilot cloud agent and it’s enabled for the repository, the merge box shows a Fix with Copilot button. Per GitHub Docs, it analyzes the conflicting changes and resolves them, then checks the build, plus tests and the linter.

Read its diff before merging. An automated resolution is still a resolution you own.

What do conflict markers mean and how do you read them?

Marker lines fence off each conflicting hunk. The opening line is followed by your side, a divider separates it from the other side, and the closing line ends the hunk. Text outside those lines is unchanged or already merged cleanly.

Why is GitHub the heart of open source?

Uncover GitHub statistics: developer community growth, repository trends, collaboration patterns, and the platform that powers modern software development.

Explore GitHub Data →
MarkerRoleWhat follows
<<<<<<< HEADStart of the conflictYour side
=======DividerThe other side
>>>>>>> branch-nameEnd of the conflictNothing, it closes the other side

When both sides changed the same area, Git can’t pick one at random. It leaves both versions in the file and waits for you (Git documentation, version 2.56.0).

During a local merge, the git diff command shows a three-way diff that highlights changes from both sides. It helps when the markers alone don’t make the right answer obvious.

Keep yours, keep theirs, or write a new version

Keep only your lines if the other change is obsolete, or only the incoming lines if yours is the stale one.

Most of the time, though, the answer is a blend. That’s especially true when two people fixed different parts of the same function.

The fourth marker in diff3 style

Setting merge.conflictStyle to diff3 adds a ||||||| marker followed by the original text from the common ancestor. The default style leaves that text out, which tends to produce smaller conflict regions (Git documentation, version 2.56.0).

Looking to sharpen your Git skills? Branching, merging, rebasing, and everything else you need - including git rebase, git stash, and commit workflows - is on one page in the Git Cheat Sheet.

The zdiff3 style works like diff3 but trims matching lines near the start or end of the region. Seeing the original often shows which side changed the meaning.

What causes a merge conflict in GitHub?

YouTube player

Git hits a conflict when two branches changed the same part of a repository in a way it can’t reconcile alone. Most differences merge automatically, so a conflict means Git ran into a choice it can’t make safely (GitHub Docs, as of October 2026).

The common case is two people editing the same line of the same file on different branches. A file edited on one branch and removed on another also conflicts.

Directory renames are the odd one. If a branch renames a directory while another adds a file inside it, Git reports a conflict for those paths by default.

The git merge command compares both branch tips against their common ancestor. Changes in different areas combine cleanly, and only overlapping areas get markers.

▶ GIT EXPLAINED

If you commit, branch, or merge code every day, it helps to know how Git came to be. This video covers how Linus Torvalds created Git in just 10 days after a license dispute and explains how its data model actually works.

Linus Torvalds Built Git in Days Out of Spite
Built in 10 Days Out of Spite. Git and its data model explained in plain language.

Rename detection has a ceiling. With neither merge.renameLimit nor diff.renameLimit set, Git defaults to 7000 files in the exhaustive part of detection (Git documentation, version 2.56.0).

If a large move produces unexpected delete-versus-edit conflicts, check that setting first.

On the pull request, the Merge pull request button stays deactivated until every conflict between the compare and base branches is resolved.

Why is the Resolve conflicts button disabled?

GitHub deactivates the button when the conflict is too complex for its editor. The web editor handles only conflicts caused by competing line changes, and everything else gets fixed locally (GitHub Docs, as of October 2026).

Conflict typeWeb editorResolve with
Competing line changesYesWeb editor or local clone
One side edits, the other deletesNoCommand line or another Git client
Any other conflict typeNoLocal clone, then push to the pull request branch
Cross-repository pull request with the editor disabled (Enterprise Server)NoCommand line

On GitHub Enterprise Server, a site administrator can switch the conflict editor off for pull requests between repositories (GitHub Enterprise Server docs, version 3.22). A pull request from a fork into its upstream repository is a pull request between repositories, so it falls under that setting.

What to do when the button is gray

GitHub’s own note points to another Git client or Git on the command line. GitHub Desktop is one such client, and the command line handles every conflict type.

A gray button isn’t an error. The pull request just needs a local merge and a push.

How to resolve merge conflicts on the command line

Merge the base branch into your branch, list the unmerged files with git status, fix them, stage each one, then commit and push.

  1. Check out your branch and run git merge BASE-BRANCH. Git stops with “CONFLICT (content)” and “Automatic merge failed”.
  2. Run git status. Files marked “both modified” under “Unmerged paths” need work.
  3. Open each file, search for <<<<<<<, keep the right text and delete every marker line.
  4. Stage each fixed file with git add.
  5. Commit with git commit. The command git merge –continue also works.
  6. Push the branch so the pull request updates.

Edit versus delete conflicts

Git labels these differently in git status, for example “deleted by us”. You decide whether the file stays.

To keep it, run git add FILENAME. To remove it, run git rm FILENAME. Either way, finish with git commit.

Protect uncommitted work first

Git’s documentation warns that git merge –abort cannot always restore uncommitted changes once a merge has started. Commit them first, or shelve them with git stash.

Commands that speed up the edit

git mergetool opens a graphical merge tool. git diff shows the three-way diff for conflicted files, and git log –merge -p PATH shows the diffs from each branch.

For the same workflow in more detail, see this guide to resolving merge conflicts in Git.

Which method should you use: web editor, command line, GitHub Desktop or an IDE?

Small line conflicts in one or two files are fine in the web conflict editor. Go local for everything else, and also whenever the result needs a test run before it reaches the branch. I’d rather catch a broken build on my own machine than on a pull request.

MethodConflict typesSetupBest for
Web conflict editorCompeting line changes onlyNoneSmall fixes in one or two files
Command lineAll typesGit and a cloneEdit-versus-delete, rebases, scripting
GitHub DesktopAll types, edited in your own toolApp and a cloneSyncing branches visually
VS CodeAll types, with inline actions or a 3-way editorEditor and a cloneLarge or tangled conflicts

Web conflict editor

No clone, no install, and every conflicting file is listed beside the editor. The catch is that it handles competing line changes only, per GitHub Docs as of October 2026.

Nothing builds or tests locally before the merge commit lands, which is the part that bothers me most.

Command line

It covers every conflict type, including the edit-versus-delete conflicts the web editor refuses.

You get full control, it’s scriptable, and it works the same on any machine with Git. The price is reading the git status output yourself, with no side-by-side view until you launch git mergetool.

GitHub Desktop

GitHub Desktop warns about conflicts above the merge button and blocks the merge until every conflict is resolved. The editing itself happens in a text editor, the command line or another tool you pick (GitHub Docs, as of October 2026).

You get a clear warning and the push controls in one window. A hard conflict still needs a real editor, though, so Desktop is really a front end for the same work.

VS Code

Conflicted files appear under a Merge Changes section in the Source Control view. Visual Studio Code offers two ways to resolve them, according to its documentation.

The inline actions sit above each conflict and read Accept Current Change, Accept Incoming Change, Accept Both Changes and Compare Changes. The 3-way merge editor puts Incoming on the left, Current on the right and Result at the bottom.

One caveat. Complete Merge stages one file, not the whole operation.

Accept Both doesn’t guarantee valid code, and VS Code’s own docs say so. Read the Result pane even when the unresolved count hits zero.

How do you abort a merge or rebase that went wrong?

Run git merge –abort for a merge and git rebase –abort for a rebase. The first reconstructs the pre-merge state as far as Git can, and the second resets HEAD to where the branch started.

A rebase gives you two more exits. git rebase –skip drops the commit that conflicted and moves on, while git rebase –quit stops the rebase but leaves HEAD, index and working tree untouched.

While a merge is in progress, git merge –abort is equivalent to git reset –merge. A matching git merge –quit forgets the merge without touching any files.

Skipping discards your commit’s changes for that step. Use it only when the base branch already contains the same change.

Abort from VS Code

Open the Command Palette and pick Git: Abort Merge, Git: Abort Rebase or Git: Abort Cherry Pick. These commands do not undo a stash restore (VS Code documentation, as of October 2026).

Aborting throws away the conflict-resolution work you already did, so copy any edits you want to keep first.

Why do rebase conflicts differ from merge conflicts?

A merge resolves all conflicts once, in a single merge commit. A rebase replays commits one by one, so Git can stop at every commit that touches the same area (Git rebase manual, version 2.56.0).

AspectMergeRebase
ResolutionOnce, in the merge commitPer conflicting commit
Finish withgit commitgit rebase –continue
HistoryKeeps the branch, adds a merge commitLinear, commits rewritten
Push afterwardRegular pushForce push

Ours and theirs swap during a rebase

In a rebase, “ours” is the new base plus the commits already replayed, and “theirs” is your own work. VS Code’s documentation describes the same swap with its Current and Incoming labels.

Two independent docs agree, so trust the swap. Compare the content before accepting a side by name.

Reusing resolutions with git rerere

Git rerere records the conflicted result along with your hand resolution, then replays it when the same conflict comes back. Set rerere.enabled and git merge, git commit and git rebase call it automatically.

It leaves the index alone, so you still check with git diff and stage with git add.

Records expire. By default Git prunes unresolved conflicts older than 15 days and resolved ones older than 60 days (Git documentation, version 2.56.0).

Running git rebase –skip or –abort clears the current rerere metadata on its own. And a file that already contains lines resembling conflict markers can make rerere fail to record the resolution.

Rebase and merge on GitHub

GitHub can’t rebase and merge automatically when the pull request has merge conflicts, when rebasing the commits runs into conflicts, or when the rebase is “unsafe”, meaning it would produce a different result than a merge.

The workaround is a local rebase, a command-line conflict fix and a force push, after which the rebase and merge button works (GitHub Docs, as of October 2026).

Squashing has its own trap on long-running branches. The common ancestor stays unchanged after each squash and merge, so you resolve the same conflicts again and again.

How to prevent merge conflicts

Bring the base branch into your feature branch often, keep branches short-lived, and let GitHub require an up-to-date branch before merging. Prevention lowers how often conflicts appear but never removes them.

GuardWhat it doesCost or limit
Update branch buttonMerges the base branch in, or rebases onto itNeeds a conflict-free branch, may be blocked on protected head branches
Require branches to be up to date before mergingBlocks the merge until the branch is currentExtra builds after others merge
Merge queueTests each pull request against the latest target branch and the queueOrg-owned public repos, or Enterprise Cloud private repos

The merge queue gives the same benefit as the up-to-date requirement without making authors update their branch and wait for checks (GitHub Docs, as of October 2026).

Keep branches short-lived

Long-lived branches drift from the base branch, and every drifted file is a conflict waiting to happen. Trunk-based development keeps branches short by design.

Frequent merges into the main branch, as in continuous integration, keep each conflict small. Small pull requests touch fewer files, so fewer files can collide.

Where these guards fall short

Nothing stops two people editing the same line in the same hour. Up-to-date requirements also cost builds on busy repositories.

A merge queue pays off on busy branches with many authors. A small team probably doesn’t need one.

Common Questions About Merge Conflicts in GitHub

How can I tell a pull request has a conflict before I merge it?

GitHub shows a conflict warning in the merge box and deactivates the Merge pull request button until the conflicts are resolved.

Locally, git merge prints “CONFLICT (content)” and git status lists the unmerged paths.

Can Git resolve conflicts automatically?

Git merges non-overlapping changes on its own, so only overlapping edits stop it. The -X ours and -X theirs options go further and auto-resolve every conflicting hunk in favor of one side.

The other side’s conflicting lines are discarded, so read the diff afterward.

Can git pull cause a merge conflict?

Yes. Pulling runs a merge after the fetch, and that merge stops on the same overlapping edits as any other.

Pull with rebase replays your commits one at a time, so it can stop at several of them.

Do merge conflicts only happen during a merge?

No. VS Code’s documentation lists merge, pull, rebase, cherry-pick and stash restore as operations that can conflict.

The finishing step differs. A cherry-pick ends with git cherry-pick –continue, and a stash restore needs no merge commit.

Does a merge queue remove merge conflicts?

No. A merge queue tests each pull request against the latest target branch and the pull requests ahead of it, then merges it once required checks pass.

Conflicts between your branch and the base branch still need your resolution first.

Who can use the Update branch button?

Anyone with write permission to the repository that owns the head branch. The button appears only when the branch is behind the base branch and has no conflicts.

A protected head branch can block it.

Verifying Code After Fixing Merge Conflicts in GitHub

A resolved conflict proves only that the text merges, so build and test the combined branch before anyone merges it. Two correct changes can still break each other once they share a file.

Run the build and tests locally on the resolved branch first. Then push, wait for the required status checks, and approve and merge once they pass.

That order keeps failures private for as long as possible. A local failure never reaches reviewers, while a failed check lands on the pull request.

Check the required-check mode as well. With the up-to-date box unchecked, status checks can pass against a stale base and fail after the merge when the base branch holds incompatible changes (GitHub Docs, as of October 2026).

Once checks pass, the next step is approving the pull request so the merge can proceed.

Bogdan Sandu

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.