You rebase on main and git stops:
CONFLICT (content): Merge conflict in package-lock.json
The usual reflexes are all wrong:
- Hand-editing the markers away gives you a dependency tree no resolver would produce.
- "Accept Both Changes" leaves duplicate JSON keys or invalid TOML/YAML.
- Accepting one side looks fine, but the other branch's new dependencies are silently missing from the lock.
The rule
A lockfile is a build output of the manifest. So:
- Resolve the manifest (
package.json,pyproject.toml,Cargo.toml,go.mod...) by hand. - Give the tool a lockfile it can read.
- Let the tool regenerate the lock.
npm, Yarn and pnpm can read a conflicted lockfile and merge both sides themselves. The others need one clean side first: git checkout --ours -- <lockfile>.
The command table
| Lockfile | Start from | Regenerate with |
|---|---|---|
package-lock.json |
conflicted file | npm install --package-lock-only --ignore-scripts |
yarn.lock (v1) |
conflicted file | yarn install --ignore-scripts |
yarn.lock (berry) |
conflicted file | yarn install --mode=update-lockfile |
pnpm-lock.yaml |
conflicted file | pnpm install --lockfile-only --ignore-scripts |
poetry.lock |
--ours |
poetry lock (Poetry 2) / poetry lock --no-update (Poetry 1) |
uv.lock |
--ours |
uv lock |
Cargo.lock |
--ours |
cargo update --workspace |
go.sum |
--ours |
go mod tidy |
composer.lock |
--ours |
composer update --lock --no-install --no-scripts |
Gemfile.lock |
--ours |
bundle lock |
Pipfile.lock |
--ours |
pipenv lock |
Two gotchas: during a rebase, --ours is the branch you rebase onto, not yours. And for Cargo, skip cargo generate-lockfile: it upgrades everything, which turns a merge into an upgrade.
--ignore-scripts is a deliberate choice: you are regenerating a lockfile, not building, so there is no reason to run install scripts from packages you have not reviewed.
One click in VS Code
I built LockSettle, a free VS Code extension that runs this routine for you. It flags conflicted lockfiles (ten types, monorepos included), refuses and opens the manifest if that is still conflicted, shows you the exact command in a confirmation dialog, runs it as a visible task in the right folder, then checks for leftover markers and offers to stage the file. Every command is overridable. No network, no telemetry, nothing runs in an untrusted workspace.
It also gets its own activity bar icon with a badge, and a Conflicted lockfiles panel with Regenerate and Open manifest buttons.
code --install-extension jaytankdev.locksettle
Source (MIT): github.com/jay-tank/locksettle
Full write-up (why each tool differs, Yarn berry and Poetry 2 details, safety design, FAQ): How to fix package-lock.json merge conflicts the right way
Top comments (0)