Every so often someone proposes gitignoring composer.lock or package-lock.json “because they cause conflicts.” That trades a small recurring cost for a large hidden one: without the lockfile, every machine resolves dependencies independently, and “works on my machine” becomes structural.
Why the lockfile is committed#
composer.json says what you allow; composer.lock says what you got - exact versions, exact hashes. Committing it means CI, staging, production, and every laptop install the same dependency set. Your CI pipeline relies on this: composer install and npm ci read the lockfiles, which is why a green PR means something.
Without them, a package author publishing a patch release between your test and your deploy is an unreviewed code change in production.
When they conflict#
Two branches both ran composer update or npm install, and now the lockfiles conflict on merge. The rule is: never resolve a lockfile conflict by hand-editing. Regenerate instead:
git merge main
# conflicts in composer.lock
git checkout --theirs composer.lock # or ours; the content hardly matters
composer update --lock # regenerate a valid lockfile
git add composer.lock
The regenerated file is consistent by construction; a hand-merged one is two inconsistent halves glued together. Then run the test suite, because the merge may have combined two dependency sets that each passed alone.
For package-lock.json the same shape: take one side, npm install, commit the result.
The habits that keep it rare#
- One person upgrades dependencies per branch; upgrades go in their own PR, never smuggled inside a feature.
- Merge or rebase frequently - short-lived branches shrink the window where two lockfiles diverge.
- When you do upgrade, read the lockfile diff in the PR. It is the one diff that lists exactly what new code will run on your server.
The lockfile is the receipt for your dependencies. Keep it in Git, regenerate it instead of hand-merging, and dependency conflicts drop to a minor chore.
Share this post
Keep reading
Annotating Commits with git notes: Metadata Without Rewriting History
Some things belong on a commit but not in it: review links, benchmark results, the ticket nobody remembered to reference. git notes adds them after the fact, no rebase required.
Backing Up Your Git Server So It Actually Restores
Every clone is a partial backup - but hooks, config and server state live outside the repo. Mirror, bundle, copy off-site, and rehearse the restore.
Cherry-Picking: One Commit Without the Branch
Cherry-pick copies a single commit onto your branch and leaves the rest behind. Right for hotfixes across release branches, wrong as a sync strategy.