Lock-файли змінюються майже при кожній зміні залежностей, і дві гілки, що додали по пакету, гарантовано конфліктують. Розв'язувати такий конфлікт вручну, редагуючи JSON, не можна: у composer.lock є content-hash - хеш вмісту composer.json, і ручне злиття майже завжди дає невідповідність або неузгоджене дерево залежностей.
Правильний спосіб для Composer:
- розв'язати конфлікт у
composer.json- він короткий і зрозумілий людині; - взяти
composer.lockз основної гілки; - повторити зміни своєї гілки командою Composer:
git checkout --theirs composer.lock # при rebase - --ours, див. нижче
composer update vendor/added-package # лише пакети, які додала ваша гілка
# або, якщо змінювали лише composer.json без нових пакетів:
composer update --lock
git add composer.json composer.lock
composer update лише для конкретних пакетів, а не всіх: повний composer update оновить усе дерево, і pull request раптом міститиме десятки чужих оновлень.
Для npm:
git checkout --theirs package-lock.json
npm install # перебудує lock з урахуванням вашого package.json
npm також вміє сам розв'язувати конфлікти в package-lock.json: якщо запустити npm install при конфлікті лише в lock-файлі, він об'єднує обидві версії.
Увага до --ours і --theirs при rebase: під час rebase ролі міняються місцями - --ours означає гілку, на яку переносите (тобто main), а --theirs - ваші коміти. Тому при rebase версія main - це --ours.
Як зменшити кількість конфліктів:
- оновлювати залежності окремими невеликими pull request, а не в гілках задач;
- автоматизовані оновлення (Dependabot, Renovate) з частим злиттям;
- перед роботою над задачею оновити гілку з
main.
Перевірка після розв'язання:
composer validate # чи відповідає lock-файл composer.json
composer install # чи встановлюється дерево
php artisan test
Чого не робити: додавати lock-файли в .gitignore, щоб «не конфліктували». Для застосунку lock-файл - гарантія, що продакшен, CI і колеги отримують однакові версії пакетів.
Докладніше в документації: Composer: розв'язання конфліктів злиття