Back to core workflows Fix dependency resolution Tune package metadata Jump to monorepo patterns

Fixing pnpm-lock.yaml Merge Conflicts

Exact Symptom

Git halts the merge or rebase operation with standard conflict markers injected into pnpm-lock.yaml:

<<<<<<< HEAD
... pnpm-lock.yaml content ...
=======
... pnpm-lock.yaml content ...
>>>>>>> feature-branch

Root Cause Analysis

The pnpm-lock.yaml file is a strict, deterministic YAML graph mapping exact package versions, integrity hashes, and peer dependency resolutions. Git’s default three-way merge algorithm operates line-by-line and cannot reconcile structural YAML changes when concurrent branches modify dependency trees or transitive resolutions. Unlike package managers that use flat lockfiles, pnpm's content-addressable store and strict peer dependency enforcement cause lockfile topology shifts that trigger unavoidable merge conflicts. Understanding how deterministic resolution interacts with version control is critical for Lockfile Management Strategies.

Diagnostic & Recovery Steps

Do not manually edit conflict markers. Follow this exact sequence to regenerate a valid dependency graph and unblock the pipeline:

  1. Abort the current merge state:
git merge --abort
  1. Checkout the target base branch:
git checkout main
  1. Regenerate a clean baseline lockfile:
pnpm install
  1. Apply feature branch dependency changes: Cherry-pick or manually merge only the package.json modifications from the feature branch into the working tree.
  2. Run deterministic resolution:
pnpm install --lockfile-only
  1. Verify graph integrity:
pnpm install --frozen-lockfile
# Must exit 0 without errors
  1. Commit the regenerated lockfile:
git add pnpm-lock.yaml
git commit -m "chore: resolve pnpm-lock.yaml merge conflict"
  1. Re-attempt the merge:
git merge feature-branch
# Conflicts should now be resolved or isolated to non-lockfile assets

Pipeline Prevention & Configuration

Automate conflict resolution and enforce environment parity across Core JavaScript Package Workflows by applying these repository-level configurations:

.gitattributes (Auto-resolve strategy):

pnpm-lock.yaml merge=ours

.npmrc (Workspace & Peer Dependency Tuning):

auto-install-peers=true
strict-peer-dependencies=false
shared-workspace-lockfile=true

Version Pinning (package.json): Enforce identical pnpm versions across all developer machines and CI runners:

{
 "packageManager": "pnpm@9.0.0"
}

Frequently Asked Questions

Q: Is it safe to manually edit conflict markers inside pnpm-lock.yaml? A: No. Manual edits will almost certainly break YAML syntax, invalidate integrity hashes, and cause pnpm install --frozen-lockfile to fail. Always regenerate the lockfile using pnpm's resolver.

Q: Why does pnpm-lock.yaml change even when package.json remains untouched? A: pnpm resolves transitive dependencies and peer dependencies dynamically. Registry metadata updates, new patch versions, or changes in workspace topology will trigger lockfile updates to maintain exact reproducibility.

Q: How can CI/CD pipelines automatically handle pnpm lockfile conflicts? A: Configure a custom Git merge driver in .gitattributes to auto-resolve lockfile conflicts by favoring the incoming branch, then run a post-merge pnpm install --lockfile-only hook to deterministically reconcile the dependency graph.

Q: Should I commit pnpm-lock.yaml in library packages? A: Yes. Committing the lockfile ensures reproducible builds for contributors and CI. For published libraries, consumers will ignore it, but it remains critical for internal testing and workspace consistency.