PHP Composer, Git submodules и Assembla
Некоторое время назад я решил навести порядок в списках своих библиотек, подключить всё через Composer, настроить человеческую автозагрузки по PSR-0, и вообще как следует прибраться в коде. Однако не всё шло гладко. В этом посте я расскажу об особенностях работы с Composer внутри Git репозитария с библиотеками, подключаемыми как git submodules.
Проблема с Git Submodules и Composer
В общем, проблема такая. Имеется некоторое количество библиотек в папки vendor. Они туда ставятся Composer’ом и обновляются при помощи
1 |
php composer.phar update |
После этого делаем commit & push. Но вот незадача, когда на другой машине я делаю git pull с этой же ветки, то получаю пустую папку, вместо библиотеки. Может быть это проблема git, может assembla, по идее сабмодули должны по другому отображаться (см. рисунок).
Очень долго копался в проблеме, экспериментально выяснил, что git submodules коммититься совершенно не хотят. Т.е. после каждого обновления кода надо обновлять и папку vendor с библиотеками, что в моём случае неприемлимо. А вдруг оборвётся связь с репозитарием одной из библиотек, а вдруг они там что-то нашаманят, ветку может уберут или ещё что? В общем зависить от всех сторонних репозитариев при деплое на продакшен своего кода не хочется. Поэтому я начал поиск решения.
Решение
Решение нашлось, не скажу, что быстро, но нашлось. Итак. Во-первых нам надо создать скриптик stash_git.sh. Образец был взят с хабра, спасибо хабраюзеру karser. Код немного модифицировал, чтобы скрипт удалял вообще все .git* файлы и папки. Вот исходник:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#!/bin/bash backup_git="stash_git.tar" stash() { echo "Stashing....." tar -czf $backup_git $git_list rm -rf $git_list } apply() { echo "Applying....." tar -xf $backup_git && rm $backup_git } if [ "$1" = "apply" ] then if [ -f $backup_git ] then apply else echo "Nothing to apply" fi else git_list=`find vendor/ -name ".git*"` if [ "$git_list" ] then stash else echo "Nothing to stash." exit 0 fi fi exit 1; |
Этот скриптик можно запускать либо для удаления в архив(tar) всех git файлов и папок:
1 |
./stash_git.sh |
либо для возвращения их обратно
1 |
./stash_git.sh apply |
Порядок действий для починки репозитария
У меня в репозитарии после пуша сабмодулей творилась вообще анархия. Зайдя в assembla я видел вместо папок некие одноименные файлы, которые не открывались, при git pull они принимались кака пустые папки. Нет кода – куча багов. В результате родился такой вот солюшен:
- Переключаемся в дев ветку, говорим коллегам, чтобы пока не пулились.
- Удаляем все библиотеки внутри папки vendor.
- git add . & git add -u .
- git commit -m “Удалили vendor”
- git push origin branch_name
- Убеждаемся через веб-морду или консоль в origin, что папки реально удалены.
- php composer.phar self-update
- php composer.phar update
- ./stash_git.sh (проверьте, чтобы был установлен исполняемый бит на нём)
- rm -rf ./git_stash.tar (он нам нафиг не нужен, т.к. composer при следующем update всё равно всё пересоздаст там)
- git add .
- git add -u .
- git commit -m “Обновили vendor”
- git push origin branch_name
Всё, смотрим детали коммита и видим там, что теперь папки библиотек записались полноценно.
Итого
В качестве плюса такого решения вижу отсутствие зависимости от сторонних репозитариев во время деплоя и разработки, т.е. они реально нужны только при обновлении библиотек. В качестве минусов – немного более затруднённый процесс обновления, однако при любых глюках с Composer самый частый совет на форумах – “удалите библиотеки в vendor и попробуйте снова” 🙂 Если у вас есть более изящное решение – велкам в комменты, буду рад услышать.
У меня была ситуация, когда либа, подключенная с гитхаба имела внутри себя submodule. Понятное дело, что при composer install папочка субмодуля совершенно пустая. Для себя решил это так в composer.json:
“scripts”: {
“post-install-cmd”: [
“cd && git submodule update –init –recursive”
]
}
Это вариант, Антон. Но от зависимости от сторонних реп не избавит(
Дополню немного. cd делаешь в директорию субмодуля, ключ “–recursive” нужен, если есть вложенные субмодули.
О, спасибо!
Как раз столкнулся с такой проблемой. Не понимал – в чём собственно дело и как бороться.
Ваш пост помог. 🙂
Отлично, за этим посты и делаю 🙂
Добавлять папку vendor под версионирование нельзя! Есть файл composer.lock и composer.json, это все что можно от композера добавлять.
Composer.lock файл содержит сылки на все зависимости в “развернутом” виде, то-есть с привязкой к коммиту, и т.д.
Поэтому достаточно просто выполнить composer install, и будет установлены все зависимости с теми же версиями, что и в папке vendor.
Если же вы делаете правки в vendor, то это мягко говоря не очень, переопределяйте поведение, иначе у Вас может поломаться все.
Правки в vendors – ад и Израиль. Конечно не делаем. По поводу выноса vendors из репозитария, composer.lock и composer install – это идеологически верно и первоначальный вариант был именно такой… до той поры, пока не начались сетевые проблемы и деплой продакшена не начал отваливаться по таймауту из-за этого.