PHP Composer, Git submodules и Assembla

Некоторое время назад я решил навести порядок в списках своих библиотек, подключить всё через Composer, настроить человеческую автозагрузки по PSR-0, и вообще как следует прибраться в коде. Однако не всё шло гладко. В этом посте я расскажу об особенностях работы с Composer внутри Git репозитария с библиотеками, подключаемыми как git submodules.

Проблема с Git Submodules и Composer

В общем, проблема такая. Имеется некоторое количество библиотек в папки vendor. Они туда ставятся Composer’ом и обновляются при помощи

php composer.phar update

После этого делаем commit & push. Но вот незадача, когда на другой машине я делаю git pull с этой же ветки, то получаю пустую папку, вместо библиотеки. Может быть это проблема git, может assembla, по идее сабмодули должны по другому отображаться (см. рисунок).

Очень долго копался в проблеме, экспериментально выяснил, что git submodules коммититься совершенно не хотят. Т.е. после каждого обновления кода надо обновлять и папку vendor с библиотеками, что в моём случае неприемлимо. А вдруг оборвётся связь с репозитарием одной из библиотек, а вдруг они там что-то нашаманят, ветку может уберут или ещё что? В общем зависить от всех сторонних репозитариев при деплое на продакшен своего кода не хочется. Поэтому я начал поиск решения.

Решение

Решение нашлось, не скажу, что быстро, но нашлось. Итак. Во-первых нам надо создать скриптик stash_git.sh. Образец был взят с хабра, спасибо хабраюзеру karser. Код немного модифицировал, чтобы скрипт удалял вообще все .git* файлы и папки. Вот исходник:

#!/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 файлов и папок:

./stash_git.sh

либо для возвращения их обратно

./stash_git.sh apply

Порядок действий для починки репозитария

У меня в репозитарии после пуша сабмодулей творилась вообще анархия. Зайдя в assembla я видел вместо папок некие одноименные файлы, которые не открывались, при git pull они принимались кака пустые папки. Нет кода – куча багов. В результате родился такой вот солюшен:

  1. Переключаемся в дев ветку, говорим коллегам, чтобы пока не пулились.
  2. Удаляем все библиотеки внутри папки vendor.
  3. git add . & git add -u .
  4.  git commit -m “Удалили vendor”
  5. git push origin branch_name
  6. Убеждаемся через веб-морду или консоль в origin, что папки реально удалены.
  7. php composer.phar self-update
  8. php composer.phar update
  9. ./stash_git.sh (проверьте, чтобы был установлен исполняемый бит на нём)
  10. rm -rf ./git_stash.tar (он нам нафиг не нужен, т.к. composer при следующем update всё равно всё пересоздаст там)
  11. git add .
  12. git add -u .
  13. git commit -m “Обновили vendor”
  14. git push origin branch_name

Всё, смотрим детали коммита и видим там, что теперь папки библиотек записались полноценно.

Итого

В качестве плюса такого решения вижу отсутствие зависимости от сторонних репозитариев во время деплоя и разработки, т.е. они реально нужны только при обновлении библиотек. В качестве минусов – немного более затруднённый процесс обновления, однако при любых глюках с Composer самый частый совет на форумах – “удалите библиотеки в vendor и попробуйте снова” 🙂 Если у вас есть более изящное решение – велкам в комменты, буду рад услышать.

Ссылки

Использование Сomposer в Git репозитории

7 Comments

  1. У меня была ситуация, когда либа, подключенная с гитхаба имела внутри себя submodule. Понятное дело, что при composer install папочка субмодуля совершенно пустая. Для себя решил это так в composer.json:

    “scripts”: {
    “post-install-cmd”: [
    “cd && git submodule update –init –recursive”
    ]
    }

    1. Это вариант, Антон. Но от зависимости от сторонних реп не избавит(

  2. Дополню немного. cd делаешь в директорию субмодуля, ключ “–recursive” нужен, если есть вложенные субмодули.

  3. О, спасибо!
    Как раз столкнулся с такой проблемой. Не понимал – в чём собственно дело и как бороться.
    Ваш пост помог. 🙂

  4. Добавлять папку vendor под версионирование нельзя! Есть файл composer.lock и composer.json, это все что можно от композера добавлять.
    Composer.lock файл содержит сылки на все зависимости в “развернутом” виде, то-есть с привязкой к коммиту, и т.д.
    Поэтому достаточно просто выполнить composer install, и будет установлены все зависимости с теми же версиями, что и в папке vendor.

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

    1. Правки в vendors – ад и Израиль. Конечно не делаем. По поводу выноса vendors из репозитария, composer.lock и composer install – это идеологически верно и первоначальный вариант был именно такой… до той поры, пока не начались сетевые проблемы и деплой продакшена не начал отваливаться по таймауту из-за этого.

Leave a Comment