GIT.PHP для 1С-Битрикс. Введение.

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 = '.'; //регулярное выражение для индексации всех новых или изменившихся (и не проиндексированных) файлов и папок
Фиксация/коммит изменений ( git commit -av -m )

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)
Получение изменений из удалённого репозитория ( git pull )

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 – создание нового репозитория в имеющемся сайте и его отправка в github

if (!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 пустым элементом. > >

📎📎📎📎📎📎📎📎📎📎