GIT.PHP для 1С-Битрикс. Введение.
В рамках статьи не описывается специфика работы с системами контроля версий (и GIT в частности), предполагая что читатель знает что это такое и чем может быть полезно.
Модуль реализует поддержку библиотеки GIT.PHP v.0.2 в 1С-Битрикс. По состоянию на 25.04.2015 это только сама библиотека и набор её классов, без какого-либо специфичного функционала и компонентов.
Подключение модуля.
Для использования модуля на странице или в коде необходимо выполнить:
if (!CModule::IncludeModule("coffeediz.git")) return;
Начало работы (инициация/подключение репозитория).
Для того чтобы начать работу с GIT необходимо создать объект репозитория. Для этого необходимо выполнить одно из действий:
Инициировать новый репозиторий (если он не существует)
Открыть имеющийся репозиторий (если он существует)
Для указания адреса репозитория необходимо указать путь к репозиторию от корня веб сервера (а не относительно корня сайта), например:
Получить путь к корню сайта (в котором выполняется php скрипт) от корня сервера можно с помощью $_SERVER['DOCUMENT_ROOT'].
При этом при указании путей в явном виде можно работать с репозиториями в других сайтов на многосайтовой конфигурации 1С-Битрикс.
Инициация репозиторияАналог команды git init
Открытие репозиторияСтатус репозитория ( git status )
Результат этой команды можно как выводить на печать ( echo $repo->status(); ), так и передавать в переменную для обработки ( $status = $repo->status(); )
Фиксация изменений
Активные пользовали GIT знают, что изменения проходят несколько стадий:
Незафиксированные изменения (файлы изменились, но GIT об этом не знает) -> проиндексированные изменения (GIT записывает во временное хранилище состояние файлов) -> фиксация изменений (коммит, т.е. создание точки в постоянном хранилище) -> обмен с удалённым репозиторием (Push/Pull).
Инденксация ( git add )string GitRepo->add ([ mixed $files = "*" ])
$files может принимать на вход как строку, так и массив. Примеры передаваемых значений:
- $files = '1.php'; //файл
- $files = 'auth/'; // папка
- $files = array("2.php", "quests/"); // массив значений (1 файл и 1 папка)
- $files = array( 0 => ".htaccess", 1 => ".section.php", 2 => "personal/", ); // массив значений с ключами (2 файла и 1 папка, ключи игнорируются, берутся только значения)
- $files = '.'; //регулярное выражение для индексации всех новых или изменившихся (и не проиндексированных) файлов и папок
string GitRepo->commit ([ string $message = "" ])
$message принимает на вход строку. Знак переноса «\n» не работает.
Пример: $message = "Initial commit";
Отправка изменений в удалённый репозиторий ( git push )string GitRepo->push ( string $remote, string $branch )
Поддерживается сложный синтаксис для обоих параметров:
- $repo->push('origin', 'master:example'); // отправка изменений из ветки master в ветку example
- $repo->push('https://login:password@github.com/lexnekr/git', 'example'); // отправка изменений в произвольный репозиторий github.com/lexnekr/git по HTTPS, используя логин и пароль (login:password)
string GitRepo->pull ( string remote, string $branch )
Поддерживается сложный синтаксис для обоих параметров (аналогично Push):
- $repo->pull('origin', 'master:example'); // получение изменений из ветки master в ветку example
- $repo->pull('https://login:password@github.com/lexnekr/git', 'example'); // получение изменений из произвольного репозитория github.com/lexnekr/git по HTTPS, используя логин и пароль (login:password)
В случае необходимости merge (объединения изменений) и возможности автоматического разрешения коллизий, это будет произведено и не будет выдано сообщений об ошибках! В этом случае будет создан новый коммит.
Имейте в виду, что при получении изменений командой
Если вы указываете ветку ОТКУДА берёте изменений. А получены они будут в текущую ветку.
Чтобы этого избежать используйте сложный синтаксис для явного указания обеих веток.
Произвольная команда GIT
К сожалению, модуль имеет классы не для всех команд, предусмотренных в GIT. Однако он снабжён универсальным классом:
string GitRepo->run ( string $command )
Пример (получение статуса, аналог git status, $repo->status();):
Несколько необходимых для начала работы конструкций, для которых не было реализовано отдельных классов:
Имя владельца репозитория ( git config user.name )$repo->run('config user.name "ALEKSEY ZADOINIY"');
Email владельца репозитория ( git config user.email )$repo->run('config user.email a@coffeedoz.ru');
С высокой вероятностью на вашем хостинге/сервере будет недоступна команда « git config --global ». Это правильное и логичное поведение, т.к. GIT на сервере установлен за пределами публичной части сайта и запись из сайта (под пользователем сайта) в системную дирректорию GIT было бы потенциально опасной операцией!
Привязка удалённого репозитория ( git remote add )Если вы не можете настроить обмен с удалённым репозиторием по SSH (т.к. не можете обменяться ключами, например), то вы можете привязать репозиторий по https протоколу. В этом случае вам так же придётся передавать логин и пароль. Я не рекомендую хранить их в явном виде в конфиге, однако вы можете это сделать следующим образом:
$repo->run('remote add origin https://login:password@github.com/lexnekr/git');
История изменений ( git log )
Полная история: $repo->log();
$format (задаёт параметры форматирования, используется для формирования своей маски ответа, например, если ответ предстоит парсить с помощью php)
Примеры скриптов:
1 – создание нового репозитория в имеющемся сайте и его отправка в githubif (!CModule::IncludeModule("coffeediz.git")) return; //подключаем модуль
$repo = Git::create('/home/a/a92661qd/coursera/public_html/'); // создаём репозиторий
$repo->run('config user.name "ALEKSEY ZADOINIY"'); //добавляем имя владельца репозитория $repo->run('config user.email a@coffeedoz.ru'); // добавляем email владельца репозитория
$repo->run('remote add origin https://login:password@github.com/lexnekr/gittest'); //добавляем адрес удалённого репозитория (с логином и паролем для доступа по HTTPS, что НЕ РЕКОМЕНДУЕТСЯ)
$files = '.'; $repo->add($files); //индексируем все новые и изменённые файлы и папки
$message = "1st commit"; $repo->commit($message); //создаём коммит с текстовым комментарием
$repo->push('origin', 'master'); //отправляем в удалённый репозиторий в master ветку
2 – Скрипт создания и отправки бекапаподходит для постановки на Cron, но требует дополнительных првоерок и ограничений прав, чтобы не был использован для DDOS.
if (!CModule::IncludeModule("coffeediz.git")) return; //подключаем модуль
$repo = Git::open('/home/a/a92661qd/coursera/public_html/'); //открываем имеющийся репозиторий
$files = '.'; $repo->add($files); //индексируем все новые и изменённые файлы и папки
$message = date('Y-m-d'); $repo->commit($message); //создаём коммит с комментарием в виде текущей даты
$repo->push('origin', 'master:backup'); //отправляем в удалённый репозиторий (состояние ветки master в ветку backup)
3 – Парсинг лога в массивЧерновой скрипт, который планируется использовать для построения дерева истории
if (!CModule::IncludeModule("coffeediz.git")) return; //подключаем модуль
$repo = Git::open('/home/a/a92661qd/coursera/public_html/'); //открываем репозиторий
$log = ''; // Приводим к 100% JSON формату (добавляем фигурные кавчки и убираем 1й лишний символ "запятую")
$log = json_decode($log, true); // JSON --> Array
foreach ($reversed_log as $hash => &$commit) < // идём по циклу по коммитам $reversed_log[$hash]['PARENTS'] = explode(" ", $reversed_log[$hash]['PARENTS']); // превращаем строку со списком SHA родителей в массив (разделитель между SHA - пробел) if(empty($reversed_log[$hash]['PARENTS'][0])) < //если 1й элемент массива родителей пуст $reversed_log[$hash]['PARENTS'] = array(); // заменяем пустой элемент массива с родителями на пустой массив (для корректной операции Array --> JSON в будущем). Причина - на предыдущем этапе пустая строка (если нет родителей) превратилась в массив с 1 пустым элементом. > >