Merge Conflict Resolution
Purpose and Scope
Merge conflict resolution in VS Code is the editor workflow for taking a file that Git marked as conflicted and turning it back into a normal, resolved file. The bundled merge-conflict extension supplies the conflict-oriented commands that appear around textual conflict markers, while the bundled Git extension supplies the broader source control integration that detects Git repositories and presents changed resources in the Source Control view. This page focuses on the repository-backed extension surface: how the bundled extension is packaged, which commands it contributes, and how those commands fit into the user task of resolving Git conflicts inside the editor.
Sources: extensions/merge-conflict/README.md, extensions/merge-conflict/package.json, extensions/git/README.md
The product documentation describes conflicts as situations where Git cannot automatically combine changes, commonly because two branches changed the same lines, one side deleted a file changed by another side, or both sides inserted incompatible content at the same location. In that state Git writes conflict markers into files and pauses merge, rebase, pull, or cherry-pick operations until the user resolves them. The repository evidence aligns that user-facing story with a bundled extension named merge-conflict, whose README points readers to VS Code merge conflict documentation rather than treating conflict resolution as a separate installable feature.
Relevant Source Files
- extensions/merge-conflict/README.md - Identifies the extension as bundled with Visual Studio Code, states that it can be disabled but not uninstalled, and directs users to the product merge-conflict documentation.
- extensions/merge-conflict/package.json - Defines the merge-conflict extension manifest: identity, activation, desktop and browser entry points, build scripts, workspace capabilities, commands, and Source Control menu contributions.
- extensions/git/README.md - Identifies the Git extension as bundled with Visual Studio Code and documents that it exposes a Git API for other extensions that need to interact with the built-in Git provider.
Core Concepts
A merge conflict is not a VS Code-specific file format. It is a Git state that becomes visible in the editor through marker regions such as current change, incoming change, and the separator between them. VS Code then layers editor actions on top of those markers so the user can accept the current side, accept the incoming side, accept both sides, compare the sides, or move to the next conflict. The merge-conflict extension is therefore best understood as a focused editor assistant for files that are already in a Git conflict state, not as the component that implements Git itself.
The Git integration is the source-control foundation for this workflow. The Git extension README states that Git support is bundled with VS Code, and it also describes an extension API obtained from the vscode.git extension by calling getAPI after depending on vscode.git. For normal users, this means the conflict commands appear in the same integrated Source Control experience as staging, committing, pulling, and viewing changed files. For extension authors, it clarifies the boundary: Git repository state and SCM modeling belong to the Git extension, while the merge-conflict extension contributes specialized commands for conflict text.
Sources: extensions/git/README.md, extensions/merge-conflict/package.json
System-to-Code Mapping
The merge-conflict extension manifest provides the most concrete source map for this feature. The extension is named merge-conflict, published by vscode, has display and description strings localized through package metadata, and is categorized as Other. Its README uses the standard bundled-extension notice: it is included with Visual Studio Code, can be disabled, and cannot be uninstalled. That packaging choice matters because conflict resolution must be available by default in a fresh VS Code install whenever a user opens a repository with conflicts, without requiring Marketplace discovery or a separate extension-management step.
At runtime, the manifest activates the extension onStartupFinished. That activation event means the contribution is available after workbench startup rather than only after a file-specific activation event. The manifest declares a desktop main entry point at ./out/mergeConflictMain and a browser entry point at ./dist/browser/mergeConflictMain. Combined with virtualWorkspaces set to true and untrustedWorkspaces marked supported, the manifest indicates that the feature is intended to participate across local, web-like, virtual, and restricted-trust workspace contexts. The source evidence does not require users to learn those implementation details, but they explain why conflict commands are treated as built-in editor capabilities rather than platform-specific add-ons.
Sources: extensions/merge-conflict/package.json, extensions/merge-conflict/README.md
Command and Menu Reference
The extension contributes a command family under the merge-conflict command namespace. The core resolution commands are merge-conflict.accept.current, merge-conflict.accept.incoming, merge-conflict.accept.selection, and merge-conflict.accept.both. The whole-file variants are merge-conflict.accept.all-current, merge-conflict.accept.all-incoming, and merge-conflict.accept.all-both. Navigation and inspection are covered by merge-conflict.next, merge-conflict.previous, and merge-conflict.compare. The manifest gives the navigation commands arrow icons and assigns every listed command an enablement expression of !isMergeEditor, which keeps these inline-marker commands out of the separate merge editor context.
| Command | User-facing purpose | Manifest signal |
|---|---|---|
| merge-conflict.accept.current | Keep the current side of one conflict | Enabled when !isMergeEditor |
| merge-conflict.accept.incoming | Keep the incoming side of one conflict | Enabled when !isMergeEditor |
| merge-conflict.accept.selection | Resolve using the current selection | Enabled when !isMergeEditor |
| merge-conflict.accept.both | Keep both sides for one conflict | Enabled when !isMergeEditor |
| merge-conflict.accept.all-current | Keep current changes for all conflicts | Enabled when !isMergeEditor; also contributed to Git merge SCM resource context |
| merge-conflict.accept.all-incoming | Keep incoming changes for all conflicts | Enabled when !isMergeEditor; also contributed to Git merge SCM resource context |
| merge-conflict.accept.all-both | Keep both sides for all conflicts | Enabled when !isMergeEditor |
| merge-conflict.next | Move to the next conflict | Arrow-down icon |
| merge-conflict.previous | Move to the previous conflict | Arrow-up icon |
| merge-conflict.compare | Compare the current conflict | Enabled when !isMergeEditor |
The Source Control menu contribution is narrow and important. The manifest contributes accept-all-current and accept-all-incoming to scm/resourceState/context only when scmProvider == git and scmResourceGroup == merge. This ties bulk conflict actions to Git merge resources instead of showing them for every source-control provider or every resource group. It also reflects the product workflow: the Source Control view can list conflicted files under a merge-oriented group, while opening a file exposes inline commands for individual conflict regions. The menu contribution is intentionally scoped to the Git provider declared by the bundled Git extension.
Sources: extensions/merge-conflict/package.json, extensions/git/README.md
Execution Flow
A typical flow begins outside VS Code when Git pauses an operation because it cannot combine changes. The user opens the workspace in VS Code, where Git integration represents changed resources in the Source Control view. Conflicted files are visible as merge-related resources, and the merge-conflict extension is already available after startup. When the user opens a conflicted file, conflict marker regions can be resolved through inline actions. The user can handle a single region with Accept Current, Accept Incoming, Accept Both, or Compare, then move through the file with Next Conflict and Previous Conflict until no conflict markers remain.
For larger or repetitive conflicts, the extension also exposes all-current, all-incoming, and all-both commands. These commands are useful when the user has reviewed the file or knows one side should win throughout the file. The Source Control context menu entries for all-current and all-incoming make that bulk operation reachable from Git merge resources without first navigating to each individual marker. After resolving the text, the Git workflow continues through staging and committing, which are part of the Git extension and the broader Source Control experience rather than the merge-conflict extension itself.
Sources: extensions/merge-conflict/package.json, extensions/git/README.md
Implementation Details
The extension is built like other bundled VS Code extensions. Its package scripts include compile through gulp compile-extension:merge-conflict, watch through gulp watch-extension:merge-conflict, and web-specific scripts that run bundling and type checking in parallel. The browser bundle is produced by node ./esbuild.browser.mts, while type checking uses tsgo against the extension tsconfig with noEmit. These scripts are not end-user commands, but they matter to contributors because they show the two runtime targets that must stay healthy: the desktop extension output and the web-friendly bundled browser output.
The manifest also documents the extension’s compatibility posture. The vscode engine range is ^1.5.0, and the extension declares virtual workspace support plus support in untrusted workspaces. For a conflict-resolution feature, that is a practical design choice: users may need to inspect conflicts in remote, browser, readonly-like, or restricted contexts, even if final Git writes depend on the environment. The command enablement of !isMergeEditor also signals that the legacy inline conflict commands and the dedicated merge editor are separate UI modes, preventing duplicate or inappropriate actions from appearing inside the merge editor experience.
Sources: extensions/merge-conflict/package.json
Next Steps
If you are resolving a conflict, start in the Source Control view, open each conflicted file, use the inline accept or compare actions, and then return to Git staging and commit operations once the markers are gone. If you are contributing to VS Code, begin with extensions/merge-conflict/package.json to understand the contributed command surface, then inspect the referenced desktop and browser entry points in a local checkout when changing behavior. If you are writing another SCM-related extension, read the Git extension API guidance next so your extension uses the built-in Git provider deliberately instead of duplicating repository-state logic.
Related pages: source-control-overview, git-extension-api, workspaces-and-workspace-trust