Skip to content
| Marketplace
Sign in
Visual Studio Code>SCM Providers>Git Storm MergeNew to Visual Studio Code? Get it now.
Git Storm Merge

Git Storm Merge

Hassan Ali

|
1 install
| (0) | Free
Branches and stashes, merge conflict previews against master and staging with the reason for each conflict, cherry-picking with a preview and undo, and a three-pane merge editor, in one place.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Git Workbench

One Activity Bar view for the feature-branch workflow where every branch is cut from master and gets a merge request into master and another into staging:

Section What it does
Branches Every local branch with its sync state and whether it is merged into master and staging (squash merges too).
Stashes Every stash with its files; apply, pop or delete.
Merge Preview Whether your branch will conflict with origin/master or origin/staging, which lines, which commits, and why.
Cherry-Pick Tick commits, see an in-memory preview of each, cherry-pick onto a -stg branch, continue/abort, and undo.
Conflicts During a merge, rebase or cherry-pick: the conflicting files and a three-pane merge editor to resolve them.

It replaces three separate extensions (Git Branch Status, Merge Preview and Merge Resolver). Uninstall those before installing this one. While one of them is still installed, the section it overlaps stays off and a warning names it, with Show Extensions and Reload Window. If a section fails to start for another reason, an error says which one and why; Show Log opens the "Git Workbench" log with the details.

Branches and Stashes

Each branch shows ✓ up to date, ↓N need pull, ↑N not pushed, ↑N ↓M diverged, no upstream or upstream gone, and master ✓ / staging ✗ for each target. A branch counts as merged when its tip is in the target, when its commits are there as squash, rebase or cherry-pick copies, or when its changes are there with identical file contents (the tooltip says when the branch itself was never merged). The ☁ button fetches, ⟳ refreshes; … shows while the slower checks run.

Each branch row has two buttons:

  • Check Merge Conflicts runs Merge Preview for that branch, without checking it out.
  • Cherry-Pick Its Commits… opens Cherry-Pick with that branch as the source, onto <branch>-stg.

Stashes list their message, branch and age; expand one for its files (click for a diff), and hover for Apply, Pop and Delete. Deleting asks first.

Merge Preview

git merge-tree --write-tree performs each merge in memory: nothing is checked out and your working tree is never touched. For each conflicting file it finds the clashing lines, blames each side, and classifies the commits against the base branch:

Label Meaning
only on origin/staging Staging changed these lines with commits that are not on master; your master merge request is not affected.
newer on origin/master Master changed them after you cut your branch: update from master and resolve it there.
master ↔ staging drift Not your code: your side is master code and staging has its own version of it.
mixed causes Both kinds of change.

Staging-only commits name the merge request that brought them in (via !4156 (feat/x)). Click a file for the merge result with conflict markers, a conflict to compare both sides, a commit to see it. Copy Report as Markdown gives a summary for a merge request. It re-checks after commits, checkouts and fetches; running the check yourself fetches the targets first.

Choosing what is compared. By default the checked-out branch is checked against gitWorkbench.targets (origin/master, origin/staging). Each repository can choose its own:

  • + on the view title adds a branch to check against: any remote branch (origin/develop, origin/release/2.4, a teammate's origin/feat/x), a local branch, or a tag or commit you type.
  • ✕ on a branch's row stops checking against it (one branch always stays).
  • Reset Branches to Defaults (right-click a branch, or the view's … menu) goes back to gitWorkbench.targets. A note in the view says when a repository uses its own branches.
  • Click the branch row at the top (marked current branch) to check another local branch without checking it out; pick Current branch to follow checkouts again.

These choices are remembered per repository (so ADMIN-API and ADMIN-API2 can differ) and only apply to Merge Preview: Branches and Cherry-Pick keep using gitWorkbench.targets.

Cherry-Pick

On feature-a it offers feature-a's commits onto a new feature-a-stg from origin/staging; on feature-a-stg, feature-a's commits onto the branch you are on. Click From or Onto to change either. Commits already on the destination (also under another SHA) are marked. Every ticked commit is previewed in memory: applies cleanly, conflicts (expand for the file with markers), already applied or after a conflict.

Cherry-Pick Selected confirms with that summary and runs git cherry-pick -x. On conflicts the view shows Continue (refused while conflict markers remain; stages resolved files), Skip and Abort (which also removes a branch it created). Show Conflicts opens them in the Conflicts section. Undo Last Cherry-Pick offers delete or reset while the commits are unpushed, revert otherwise; Revert Cherry-Picked Commits… reverts any cherry-pick -x commit on the current branch.

Conflicts and the merge editor

Clicking a conflicted file anywhere (Source Control's Merge Changes, the Explorer, Quick Open) opens it in the merge editor, once per file and merge; close it to edit the text by hand (mergeResolver.openConflictedFilesInMergeEditor turns this off). The Conflicts section (also in Source Control while there are conflicts) lists each conflicting file with what each side did (Modified ↔ Deleted). Accept Yours / Accept Theirs work on files, selections, folders and repositories. Merge… opens the three-pane editor (Your version | Result | Their version) with colour-coded blocks, word highlights, aligned scrolling, formatting-only conflict detection, and who changed each side and when. Files with conflict markers but no Git conflict get a CodeLens that opens the same editor. Details: docs/merge-resolver/README.md in the source.

Conflicts work as in PhpStorm:

  • Each side of a block has » / « (accept) and ✕ (ignore). Accepting one side of a conflict leaves the other side open: its arrow turns into ↓, which appends that side after the first, or you ✕ it. The conflict is resolved once both sides are handled.
  • Ctrl/Cmd+click an arrow to resolve the conflict with that side alone, or ✕ to ignore both.
  • Right-click a block (or a selection covering several) for Accept Left/Right, Resolve using Left/Right, Ignore Left/Right, Resolve Automatically, Ignore and Revert (back to the base text, unresolved).
  • Conflicts made only of PHP use statements are resolved when the merge opens, as PhpStorm's "Automatically resolve conflicts in import statements" does: the base imports, minus those either side removed, plus those either side added, each once (also with Resolve Automatically and Resolve Simple Conflicts; turn it off in the gear menu or with mergeResolver.resolveImportConflicts).
  • Typing in the Result never resolves a block: the arrows stay, and accepting afterwards replaces what you typed. The magic wand only appears while a simple conflict is untouched. Lines that exist in no version are tinted and counted.

Finishing a merge follows PhpStorm 2026.2's iterative flow:

  • The merge window's bottom bar has Accept Left / Accept Right (the whole file, asking first if you edited the Result), Apply Changes and Save and Close.
  • Apply Changes (Ctrl/⌘+Enter) saves the file and marks it resolved, but does not stage it, then opens the next file. With blocks still open it asks first ("Unprocessed Changes": Save Current Result saves exactly what the Result shows).
  • Save and Close (Escape) keeps your work and goes back to the Conflicts dialog; reopening the file brings the work back. Unlike PhpStorm, blocks still open are written with conflict markers, not the base text, so nothing is silently lost.
  • The Conflicts dialog (opens when a merge, rebase or cherry-pick stops on conflicts, from the Conflicts section title, or with Resolve Conflicts…) lists the files under Unresolved and Resolved, with an n/m badge of the changes merged so far and Yours/Theirs columns.
    • Hover a row for Accept on either side (applies to every selected file).
    • Right-click for Accept 'Yours' / Accept 'Theirs' / Revert Conflict Resolution, which puts the file back to Git's conflict, markers included.
    • Resolve All Simple Conflicts applies non-conflicting changes, simple conflicts and import conflicts in every file not started yet, and reports what is left.
    • Resolve Manually (or Review Changes for resolved files, or double-click a file) opens the merge window for the selection, then the remaining files.
    • Accept and Finish stages every file and commits the merge, or continues the rebase or cherry-pick, in a terminal.
    • Close stages the resolved files and, after asking, discards partly resolved ones.
  • Set mergeResolver.openConflictsDialog to false to not open the dialog by itself.

The toolbar follows PhpStorm 2026.2: Previous/Next Difference, Compare Contents (any two of Base, Left, Middle and Right in VS Code's diff), Collapse Unchanged Fragments, Apply non-conflicting changes: Left · All · Right, Resolve Simple Conflicts, Revert Conflict Resolution, Jump to Source, then the gear (Synchronize Scrolling, Ignore Differences, Highlighting Differences) and Help. Right-clicking outside a block offers Annotate, Show Whitespaces, Show Line Numbers, Show Indent Guides and Use Soft Wraps. Drag a divider to resize the panes. The status reads "2 changes, 1 conflict", then "No changes, No conflicts" with the "All changes have been processed" balloon.

Key (Windows/Linux · macOS) Action
F7 / Shift+F7 Next / previous difference
Ctrl+Alt+R · ⌘⌃→ Accept Left Side (also Alt+Shift+Right)
Ctrl+Alt+A · ⌘⌃← Accept Right Side (also Alt+Shift+Left)
F4 Jump to Source
Ctrl+Shift+D · ⌘⇧D Settings (gear)
Ctrl+Shift+Tab Select the opposite pane
Ctrl+F7 / Ctrl+Shift+F7 (⌘ on macOS) Next / previous conflict (our extra)
Alt+Shift+Delete Ignore the current change
Ctrl+Alt+Shift+A · ⌘⌥⇧A Apply all non-conflicting changes
Ctrl+Enter · ⌘Enter Apply Changes
Escape Save and Close

Settings

Shared by every section:

Setting Default Meaning
gitWorkbench.targets ["origin/master", "origin/staging"] Branches merge requests go into.
gitWorkbench.baseBranch origin/master The branch you cut feature branches from.
gitWorkbench.gitPath (built-in Git's) git executable, 2.38 or later.

If you set mergePreview.targets, gitBranchStatus.targetBranches / gitBranchStatus.remote or mergeResolver.gitPath for the old extensions, those values are used until you set the gitWorkbench.* ones. Each section's own settings keep their names: gitBranchStatus.autoFetchMinutes and detectSquashMerges; mergePreview.fetch and autoCheck; mergePreview.cherryPick.branchSuffix (-stg), defaultFrom and recordOrigin; and the mergeResolver.* merge editor settings.

Development

npm install
npm run build              # dist/: extension, merge editor webview, Monaco worker
npm run test:unit          # vitest: engine, git layers and real fixture repositories
npm run test:integration   # two VS Code runs: the Conflicts suites, then Branches/Preview/Cherry-Pick
npm run package            # git-workbench-<version>.vsix

GW_SUITE=resolver or GW_SUITE=workbench runs one integration suite. Source layout:

Folder Contents
src/common Shared log, Git API connection, settings
src/branches Branches and Stashes views
src/preview Merge Preview and Cherry-Pick (git/ and report/ have no editor code)
src/resolver Conflicts view and merge editor (engine/ is pure, webview/ is the UI)

The history of the three original extensions is in docs/.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft