Как разрешить конфликты слияния в Composer
Конфликты слияния в Composer и их разрешение


Конфликты слияния в Composer

Работая в команде над одним и тем же проектом в Composer, можно столкнуться с ситуацией, когда несколько человек добавляют, обновляют или удаляют что-то в файлах composer.json и composer.lock в разных ветках. Когда эти ветки в конечном итоге будут сливаться, возникнут конфликты слияния. Разрешить эти конфликты слияния не так просто, как в случае с другими файлами, особенно в случае с файлом composer.lock.

Примечание: Возможно не сразу становится очевидным, почему объединение на основе текстовых данных невозможно для файлов блокировок, поэтому давайте представим следующий пример, в котором мы хотим объединить две ветви;

  • Ветвь 1 добавила пакет A, который требует пакет B. Пакет B заблокирован на версии 1.0.0.
  • Ветвь 2 добавила пакет C, который конфликтует со всеми версиями пакета B ниже 1.2.0.

В результате слияния, основанного на тексте, будет получен пакет A версии 1.0.0, пакет B версии 1.0.0 и пакет C версии 1.0.0. Это некорректный результат, поскольку конфликт пакета C не был учтен и потребует обновления пакета B.

Повторное внедрение изменений в Composer

Наиболее безопасным методом объединения файлов в Composer является принятие версии из одной ветки и применение изменений из другой ветки.

Пример, когда у нас есть две ветки:

  1. Добавлен пакет 'A'
  2. Пакет 'B' был удален и добавлен пакет 'C'.

Чтобы разрешить конфликт при слиянии этих двух ветвей:

  • Мы выбираем ветку, в которой произошло больше всего изменений, и принимаем файлы composer.json и composer.lock из этой ветки. В данном случае мы выбираем файлы Composer из ветки 2.
  • Мы повторно применяем изменения из другой ветки (ветки 1). В этом случае необходимо снова запустить composer require package/A.

Проверка правильности объединенных файлов в Composer

Перед коммитом убедитесь, что полученные файлы composer.json и composer.lock являются корректными. Для этого выполните следующие команды:

php composer.phar validate
php composer.phar install [--dry-run]

Автоматизация разрешения конфликтов слияния с помощью git

Некоторое улучшение в разрешении конфликтов в git можно получить, используя собственный драйвер слияния git.

Пример такого драйвера можно найти в balbuf composer git merge driver.

Важные моменты

Следует помнить, что при конфликтах слияния в файле блокировок теряется информация о том, на какую именно версию были замкнуты новые пакеты для одной из ветвей. Если пакет A в ветке 1 ограничен как ^1.2.0 и заблокирован как 1.2.0, то при использовании ветки 2 в качестве базовой и выполнении новой команды composer require package/A:^1.2.0 он может быть обновлен, так как в этом случае будет использоваться самая последняя версия, которую позволяет ограничение, если это возможно. Возможно, к этому моменту уже доступна версия 1.3.0 для этого пакета, которая и будет использована.

Правильный выбор ограничений по версии и соблюдение семантической версионности пакетов при использовании операторов следующего значимого релиза должны гарантировать, что слияние веток не приведет к повреждению пакета из-за случайного обновления зависимости.

Восстановление после некорректно разрешенных конфликтов слияния в Composer

Если вышеописанные действия не были выполнены, а текстовые слияния все равно были произведены, то проект Composer может оказаться в состоянии, когда наблюдается неожиданное поведение, поскольку файл composer.lock не полностью синхронизирован с файлом composer.json.

Здесь могут произойти две вещи:

  1. В секции require или require-dev файла composer.json находятся пакеты, которые отсутствуют в файле блокировки и, как следствие, никогда не устанавливаются.
    • Примечание: Начиная с версии Composer 2.5, наличие пакетов, которые требуются, но отсутствуют в composer.lock, приводит к ошибке при выполнении install.
  2. В файле composer.lock присутствуют пакеты, которые не являются прямой или косвенной зависимостью ни одного из требуемых пакетов. В результате пакет устанавливается, несмотря на то, что при запуске composer why vendor/package указано, что он не требуется.

Существует несколько способов решения этих проблем.

Начать с начала

Самым простым, но наиболее затратным вариантом является запуск composer update для восстановления корректного состояния с нуля.

Недостатком этого способа является то, что ранее заблокированные версии пакетов теперь обновляются, поскольку информация о предыдущих версиях пакетов была утрачена. Если все ваши зависимости следуют семантической версионности, а ограничения версий используют операторы следующего значимого релиза, это не должно быть проблемой, в противном случае вы можете случайно испортить свое приложение.

Восстановление из истории git

Вариант, который, вероятно, не очень реален во многих ситуациях, но заслуживает отдельного упоминания.

Можно восстановить правильное состояние пакета, вернувшись в историю git и найдя последний корректный файл composer.lock, и перепрошить новые зависимости оттуда.

Устранение проблем вручную

Существует возможность восстановить несоответствие между файлами composer.json и composer.lock, не копаясь в истории git и не начиная работу с нуля. Для этого необходимо решить проблему 1 и 2 по отдельности.

Обнаружение и исправление отсутствующих необходимых пакетов

Для обнаружения необходимого, но не установленного пакета можно просто выполнить команду:

php composer.phar validate

Если есть пакеты, которые требуются, но не установлены, вы должны получить результат, подобный этому:

./composer.json is valid but your composer.lock has some errors
# Lock file errors
- Required package "vendor/package-name" is not present in the lock file.
This usually happens when composer files are incorrectly merged or the composer.json file is manually edited.
Read more about correctly resolving merge conflicts https://getcomposer.org/doc/articles/resolving-merge-conflicts.md
and prefer using the "require" command over editing the composer.json file directly https://getcomposer.org/doc/03-cli.md#require

Чтобы исправить ошибку, просто запустите composer update vendor/package-name для каждого из перечисленных выше пакетов. После этого для каждого пакета, указанного в данном списке, повторный запуск composer validate должен привести к отсутствию ошибок файла блокировки:

./composer.json is valid

Обнаружение и устранение лишних пакетов

Для обнаружения и исправления пакетов, которые заблокированы, но не являются прямой/непрямой зависимостью, можно выполнить следующую команду:

php composer.phar remove --unused

Если заблокированных пакетов, не являющихся зависимостью, нет, то команда выдаст следующий результат:

No unused packages to remove

Если есть пакеты, которые необходимо почистить, то вывод будет следующим:

vendor/package-name is not required in your composer.json and has not been removed
./composer.json has been updated
Running composer update vendor/package-name
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 0 updates, 1 removal
  - Removing vendor/package-name (1.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Nothing to install, update or remove

Перевод с английского официальной документации Composer:
https://getcomposer.org/doc/articles/resolving-merge-conflicts.md

Заберите ссылку на статью к себе, чтобы потом легко её найти!
Раз уж досюда дочитали, то может может есть желание рассказать об этом месте своим друзьям, знакомым и просто мимо проходящим?
Не надо себя сдерживать! ;)

Старт! Горячий старт на просторы интернета
Старт! Горячий старт на просторы интернета
Старт! Меню