composer.json says what you want: “league/commonmark, any 2.x version”. composer.lock says what you got: “league/commonmark version 2.10.3, from this exact source, plus these other 7 packages at these exact versions”.
Why a lock file exists
Without it, two people running composer install on different days could get different versions of the same package, and a bug could appear on one machine only. The lock file makes every install identical.
composer install # reads composer.lock, installs exactly what it lists
What is inside
A long JSON list with, for each package, its name, exact version, download source and a hash. You never edit it by hand. Composer writes it when you run composer require, composer update or composer remove.
A trimmed example:
{
"_readme": ["This file locks the dependencies of your project to a known state"],
"content-hash": "9d1c3b4f...",
"packages": [
{
"name": "league/commonmark",
"version": "2.10.3",
"source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", "reference": "..." }
}
],
"packages-dev": [],
"minimum-stability": "stable",
"prefer-stable": false,
"platform": []
}
The content-hash lets Composer warn you when composer.json has changed but the lock file was not updated.
Commit it?
| Project type | Commit composer.lock? |
|---|---|
| Application or website | Yes. Every server and teammate then runs the same versions |
| Library meant to be installed by others | Usually no. Users resolve their own versions |
The normal workflow
- Someone runs
composer require xorcomposer update. The lock file changes. - They commit
composer.jsonandcomposer.lock. - Everyone else, and the production server, run
composer install.
When the two files disagree
If composer.json changed and composer.lock is out of date, composer install warns you:
Warning: The lock file is not up to date with the latest changes in composer.json.
Run composer update (or composer update --lock to refresh only the hash) and commit the new lock file.
Merge conflicts
If two branches both changed composer.lock, do not merge it by hand. Take one version, then run composer update for the packages in question, or composer update --lock, and commit the result.
Security
A lock file can pin a version that later gets a security fix. Update on purpose from time to time, and run composer audit to see which locked versions have known problems.
composer.lock is for repeatability
composer.json as your shopping list, and composer.lock as the receipt. You can always rebuy the same items from the receipt.