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

GIT.PHP для 1С-Битрикс

Эта статья описывает функции базового уровня, которые вы можете использовать сразу после установки модуля GIT.PHP

В настоящий момент модуль находится на модерации и доступен для установке по прямой ссылке сайт.ру/bitrix/admin/update_system_partner.php?addmodule=coffeediz.git

После прохождения модерации модуль будет доступен в Маркетплейсе 1С-Битрикс по ссылке marketplace.1c-bitrix.ru/solutions/coffeediz.git/

 

В рамках статьи не описывается специфика работы с системами контроля версий (и GIT в частности), предполагая что читатель знает что это такое и чем может быть полезно.

Модуль реализует поддержку библиотеки GIT.PHP v.0.2 в 1С-Битрикс. По состоянию на 25.04.2015 это только сама библиотека и набор её классов, без какого-либо специфичного функционала и компонентов.

 

Подключение модуля.

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

if (!CModule::IncludeModule("coffeediz.git"))
     return;

 

Начало работы (инициация/подключение репозитория).

Для того чтобы начать работу с GIT необходимо создать объект репозитория. Для этого необходимо выполнить одно из действий:

  • Инициировать новый репозиторий (если он не существует)

  • Открыть имеющийся репозиторий (если он существует)

Важно!

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

/u00/app/bitrix/Apache/htdocs/site/ru/

Получить путь к корню сайта (в котором выполняется php скрипт) от корня сервера можно с помощью $_SERVER['DOCUMENT_ROOT'].

При этом при указании путей в явном виде можно работать с репозиториями в других сайтов на многосайтовой конфигурации 1С-Битрикс.

Инициация репозитория

$repo = Git::create('/home/a/a92661qd/coursera/public_html/');

Аналог команды git init

Открытие репозитория

$repo = Git::open('/home/a/a92661qd/coursera/public_html/');

Статус репозитория (git status)

$repo->status();

Результат этой команды можно как выводить на печать (echo $repo->status();), так и передавать в переменную для обработки ($status = $repo->status();)

 

 

 

Фиксация изменений

Активные пользовали GIT знают, что изменения проходят несколько стадий:

Незафиксированные изменения (файлы изменились, но GIT об этом не знает) -> проиндексированные изменения (GIT записывает во временное хранилище состояние файлов) -> фиксация изменений (коммит, т.е. создание точки в постоянном хранилище) -> обмен с удалённым репозиторием (Push/Pull).

Инденксация (git add)

string GitRepo->add ([ mixed $files = "*" ])

$repo->add($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 = "" ])

$repo->commit($message);

$message принимает на вход строку. Знак переноса «\n» не работает.

Пример: $message = "Initial commit";

 

Отправка изменений в удалённый репозиторий (git push)

string GitRepo->push ( string $remote, string $branch )

$repo->push('origin', 'master');

Поддерживается сложный синтаксис для обоих параметров:

  • $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 )

$repo->pull('origin', 'master');

Поддерживается сложный синтаксис для обоих параметров (аналогично 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 (объединения изменений) и возможности автоматического разрешения коллизий, это будет произведено и не будет выдано сообщений об ошибках! В этом случае будет создан новый коммит.

Важно!

Имейте в виду, что при получении изменений командой

$repo->pull('origin', 'new');

Если вы указываете ветку ОТКУДА берёте изменений. А получены они будут в текущую ветку.

Чтобы этого избежать используйте сложный синтаксис для явного указания обеих веток.

 

 

 

 

Произвольная команда GIT

К сожалению, модуль имеет классы не для всех команд, предусмотренных в GIT. Однако он снабжён универсальным классом:

string GitRepo->run ( string $command )

Пример (получение статуса, аналог git status, $repo->status();):

$repo->run('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)

$repo->run('remote add origin git@github.com:lexnekr/git.git');

Важно!

Если вы не можете настроить обмен с удалённым репозиторием по SSH (т.к. не можете обменяться ключами, например), то вы можете привязать репозиторий по https протоколу. В этом случае вам так же придётся передавать логин и пароль. Я не рекомендую хранить их в явном виде в конфиге, однако вы можете это сделать следующим образом:

$repo->run('remote add origin https://login:password@github.com/lexnekr/git');

История изменений (git log)

Полная история: $repo->log();

Возможные параметры:

  • $format (задаёт параметры форматирования, используется для формирования своей маски ответа, например, если ответ предстоит парсить с помощью php)

  • $limit

  • $offset

  • $searchString

Примеры скриптов:

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 = $repo->log($format=',"%h":{"HASH":"%h","PARENTS":"%p","AUTHOR_NAME":"%cn","SUBJECT":"%s","NOTES":"%N","DATE":"%ai","DECOR":"%d"}'); // читаем лог ВСЕХ веток в близкий JSON формат

$log = '{'.substr($log, 1).'}'; // Приводим к 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 пустым элементом.
   }
}

 


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

<p> Эта статья описывает функции базового уровня, которые вы можете использовать сразу после установки модуля GIT.PHP </p> <p> </p> <table border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td> <p> В настоящий момент модуль находится на модерации и доступен для установке по прямой ссылке сайт.ру/bitrix/admin/update_system_partner.php?addmodule=coffeediz.git </p> <p> После прохождения модерации модуль будет доступен в Маркетплейсе 1С-Битрикс по ссылке <!--noindex--><a rel="nofollow" target="_blank" href="http://marketplace.1c-bitrix.ru/solutions/coffeediz.git/">marketplace.1c-bitrix.ru/solutions/coffeediz.git/</a><!--/noindex--></p> </td> </tr> </tbody> </table> <p>   </p> <p> В рамках статьи не описывается специфика работы с системами контроля версий (и GIT в частности), предполагая что читатель знает что это такое и чем может быть полезно. </p> <p> Модуль реализует поддержку библиотеки GIT.PHP v.0.2 в 1С-Битрикс. По состоянию на 25.04.2015 это только сама библиотека и набор её классов, без какого-либо специфичного функционала и компонентов. </p> <p>   </p> <h2>Подключение модуля.</h2> <p> Для использования модуля на странице или в коде необходимо выполнить: </p> <p> <code> if (!CModule::IncludeModule("coffeediz.git")) <br>      return;</code> </p> <p>   </p> <h2>Начало работы (инициация/подключение репозитория).</h2> <p> Для того чтобы начать работу с GIT необходимо создать объект репозитория. Для этого необходимо выполнить одно из действий: </p> <p> </p> <ul> <li> <p> Инициировать новый репозиторий (если он не существует) </p> </li> <li> <p> Открыть имеющийся репозиторий (если он существует) </p> </li> </ul> <p> </p> <table border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td> <p> Важно! </p> <p> Для указания адреса репозитория необходимо указать путь к репозиторию от корня веб сервера (а не относительно корня сайта), например: </p> <p> /u00/app/bitrix/Apache/htdocs/site/ru/ </p> <p> Получить путь к корню сайта (в котором выполняется php скрипт) от корня сервера можно с помощью $_SERVER['DOCUMENT_ROOT']. </p> <p> При этом при указании путей в явном виде можно работать с репозиториями в других сайтов на многосайтовой конфигурации 1С-Битрикс. </p> </td> </tr> </tbody> </table> <h3>Инициация репозитория</h3> <p> <code>$repo = Git::create('/home/a/a92661qd/coursera/public_html/');</code> </p> <p> Аналог команды <code>git init</code> </p> <h3>Открытие репозитория</h3> <p> <code>$repo = Git::open('/home/a/a92661qd/coursera/public_html/');</code> </p> <p> </p> <h2>Статус репозитория (<code>git status</code>)</h2> <p> <code>$repo-&gt;status();</code> </p> <p> Результат этой команды можно как выводить на печать (<code>echo $repo-&gt;status();</code>), так и передавать в переменную для обработки (<code>$status = $repo-&gt;status();</code>) </p> <p>   </p> <p>   </p> <p>   </p> <h2>Фиксация изменений</h2> <p> Активные пользовали GIT знают, что изменения проходят несколько стадий: </p> <p> Незафиксированные изменения (файлы изменились, но GIT об этом не знает) -&gt; проиндексированные изменения (GIT записывает во временное хранилище состояние файлов) -&gt; фиксация изменений (коммит, т.е. создание точки в постоянном хранилище) -&gt; обмен с удалённым репозиторием (Push/Pull). </p> <h3>Инденксация (<code>git add</code>)</h3> <p> string GitRepo-&gt;add ([ mixed $files = "*" ]) </p> <p> <code>$repo-&gt;add($files);</code> </p> <p> $files может принимать на вход как строку, так и массив. Примеры передаваемых значений: </p> <p> </p> <ul> <li> <code>$files = '1.php'; //файл</code> </li> <li> <code>$files = 'auth/'; // папка</code> </li> <li> <code>$files = array("2.php", "quests/"); // массив значений (1 файл и 1 папка)</code> </li> <li> <code>$files = array( <br>     0 =&gt; ".htaccess", <br>     1 =&gt; ".section.php", <br>     2   =&gt; "personal/", ); // массив значений с ключами (2 файла и 1 папка, ключи игнорируются, берутся только значения)</code> </li> <li> <code> $files = '.'; //регулярное выражение для индексации всех новых или изменившихся (и не проиндексированных) файлов и папок </code> </li> </ul> <p>   </p> <h3>Фиксация/коммит изменений (<code>git commit -av -m</code>)</h3> <p> string GitRepo-&gt;commit ([ string $message = "" ]) </p> <p> <code>$repo-&gt;commit($message);</code> </p> <p> $message принимает на вход строку. Знак переноса «\n» не работает. </p> <p> Пример: <code>$message = "Initial commit";</code> </p> <p>   </p> <h3>Отправка изменений в удалённый репозиторий (<code>git push</code>)</h3> <p> string GitRepo-&gt;push ( string $remote, string $branch ) </p> <p> <code>$repo-&gt;push('origin', 'master');</code> </p> <p> Поддерживается сложный синтаксис для обоих параметров: </p> <p> </p> <ul> <li> <code>$repo-&gt;push('origin', 'master:example'); // отправка изменений из ветки master в ветку example</code> </li> <li> <code> $repo-&gt;push('<a href="https://login:password@github.com/lexnekr/git">https://login:password@github.com/lexnekr/git</a>', 'example'); // отправка изменений в произвольный репозиторий github.com/lexnekr/git по HTTPS, используя логин и пароль (login:password) </code> </li> </ul> <p> </p> <p>   </p> <h3>Получение изменений из удалённого репозитория (<code>git pull</code>)</h3> <p> string GitRepo-&gt;pull ( string remote, string $branch ) </p> <p> <code>$repo-&gt;pull('origin', 'master');</code> </p> <p> Поддерживается сложный синтаксис для обоих параметров (аналогично Push): </p> <p> </p> <ul> <li> <code> $repo-&gt;pull('origin', 'master:example'); // получение изменений из ветки master в ветку example </code> </li> <li> <code> $repo-&gt;pull('<a href="https://login:password@github.com/lexnekr/git">https://login:password@github.com/lexnekr/git</a>', 'example'); // получение изменений из произвольного репозитория github.com/lexnekr/git по HTTPS, используя логин и пароль (login:password) </code> </li> </ul> <p> </p> <p> В случае необходимости merge (объединения изменений) и возможности автоматического разрешения коллизий, это будет произведено и не будет выдано сообщений об ошибках! В этом случае будет создан новый коммит. </p> <b> </b> <table border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td> <b> </b> <p> <b> Важно!</b> </p> <p> Имейте в виду, что при получении изменений командой </p> <p> <code> $repo-&gt;pull('origin', 'new');</code> </p> <p> Если вы указываете ветку ОТКУДА берёте изменений. А получены они будут в текущую ветку. </p> <p> Чтобы этого избежать используйте сложный синтаксис для явного указания обеих веток. </p> </td> </tr> </tbody> </table> <p>   </p> <p>   </p> <p>   </p> <p>   </p> <h2>Произвольная команда GIT</h2> <p> К сожалению, модуль имеет классы не для всех команд, предусмотренных в GIT. Однако он снабжён универсальным классом: </p> <p> string GitRepo-&gt;run ( string $command ) </p> <p> Пример (получение статуса, аналог git status, $repo-&gt;status();): </p> <p> <code>$repo-&gt;run('status');</code> </p> <p> Несколько необходимых для начала работы конструкций, для которых не было реализовано отдельных классов: </p> <h3>Имя владельца репозитория (<code>git config user.name</code>)</h3> <p> <code>$repo-&gt;run('config user.name "ALEKSEY ZADOINIY"');</code> </p> <h3>Email владельца репозитория (<code>git config user.email</code>)</h3> <p> <code>$repo-&gt;run('config user.email a@coffeedoz.ru');</code> </p> <b> </b> <table border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td> <b> </b> <p> <b> Важно!</b> </p> <p> С высокой вероятностью на вашем хостинге/сервере будет недоступна команда «<code>git config --global</code>». Это правильное и логичное поведение, т.к. GIT на сервере установлен за пределами публичной части сайта и запись из сайта (под пользователем сайта) в системную дирректорию GIT было бы потенциально опасной операцией! </p> </td> </tr> </tbody> </table> <h3>Привязка удалённого репозитория (<code>git remote add</code>)</h3> <code>$repo-&gt;run('remote add origin git@github.com:lexnekr/git.git');</code> <p> </p> <b> </b> <table border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td> <b> </b> <p> <b> Важно!</b> </p> <p> Если вы не можете настроить обмен с удалённым репозиторием по SSH (т.к. не можете обменяться ключами, например), то вы можете привязать репозиторий по https протоколу. В этом случае вам так же придётся передавать логин и пароль. Я не рекомендую хранить их в явном виде в конфиге, однако вы можете это сделать следующим образом: </p> <p> <code>$repo-&gt;run('remote add origin https://login:password@github.com/lexnekr/git');</code><br> </p> </td> </tr> </tbody> </table> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p> <h2>История изменений (<code>git log</code>)</h2> <p> Полная история: <code>$repo-&gt;log();</code> </p> <p> Возможные параметры: </p> <p> </p> <ul> <li> <p> $format (<i>задаёт параметры форматирования, используется для формирования своей маски ответа, например, если ответ предстоит парсить с помощью php</i>) </p> </li> <li> <p> $limit </p> </li> <li> <p> $offset </p> </li> <li> <p> $searchString </p> </li> </ul> <p> </p> <p> </p> <h2>Примеры скриптов:</h2> <h3>1 – создание нового репозитория в имеющемся сайте и его отправка в github</h3> <div> <code> if (!CModule::IncludeModule("coffeediz.git")) <br>     return; //подключаем модуль <br><br> $repo = Git::create('/home/a/a92661qd/coursera/public_html/'); // создаём репозиторий <br><br> $repo-&gt;run('config user.name "ALEKSEY ZADOINIY"'); //добавляем имя владельца репозитория <br> $repo-&gt;run('config user.email <a href="mailto:a@coffeedoz.ru">a@coffeedoz.ru</a>'); // добавляем email владельца репозитория <br><br> $repo-&gt;run('remote add origin <a href="https://login:password@github.com/lexnekr/gittest">https://login:password@github.com/lexnekr/gittest</a>'); //добавляем адрес удалённого репозитория (с логином и паролем для доступа по HTTPS, что НЕ РЕКОМЕНДУЕТСЯ) <br><br> $files = '.'; <br> $repo-&gt;add($files); //индексируем все новые и изменённые файлы и папки <br><br> $message = "1st commit"; <br> $repo-&gt;commit($message); //создаём коммит с текстовым комментарием <br><br> $repo-&gt;push('origin', 'master'); //отправляем в удалённый репозиторий в master ветку </code> </div> <p>   </p> <h3>2 – Скрипт создания и отправки бекапа</h3> <p> подходит для постановки на Cron, но требует дополнительных првоерок и ограничений прав, чтобы не был использован для DDOS. </p> <div> <code> if (!CModule::IncludeModule("coffeediz.git")) <br>     return; //подключаем модуль <br><br> $repo = Git::open('/home/a/a92661qd/coursera/public_html/'); //открываем имеющийся репозиторий <br><br> $files = '.'; <br> $repo-&gt;add($files); //индексируем все новые и изменённые файлы и папки <br>   <br> $message = date('Y-m-d'); <br> $repo-&gt;commit($message); //создаём коммит с комментарием в виде текущей даты <br>   <br> $repo-&gt;push('origin', 'master:backup'); //отправляем в удалённый репозиторий (состояние ветки master в ветку backup) </code> </div> <p>   </p> <h3>3 – Парсинг лога в массив</h3> <p> Черновой скрипт, который планируется использовать для построения дерева истории </p> <div> <code> if (!CModule::IncludeModule("coffeediz.git")) <br>     return; //подключаем модуль <br><br> $repo = Git::open('/home/a/a92661qd/coursera/public_html/'); //открываем репозиторий <br><br> $log = $repo-&gt;log($format=',"%h":{"HASH":"%h","PARENTS":"%p","AUTHOR_NAME":"%cn","SUBJECT":"%s","NOTES":"%N","DATE":"%ai","DECOR":"%d"}'); // читаем лог ВСЕХ веток в близкий JSON формат <br><br> $log = '{'.substr($log, 1).'}'; // Приводим к 100% JSON формату (добавляем фигурные кавчки и убираем 1й лишний символ "запятую") <br><br> $log = json_decode($log, true); // JSON --&gt; Array <br><br> foreach ($reversed_log as $hash =&gt; &amp;$commit) { // идём по циклу по коммитам <br>    $reversed_log[$hash]['PARENTS'] = explode(" ", $reversed_log[$hash]['PARENTS']); // превращаем строку со списком SHA родителей в массив (разделитель между SHA - пробел) <br>    if(empty($reversed_log[$hash]['PARENTS'][0])){ //если 1й элемент массива родителей пуст <br>       $reversed_log[$hash]['PARENTS'] = array(); // заменяем пустой элемент массива с родителями на пустой массив (для корректной операции Array --&gt; JSON в будущем). Причина - на предыдущем этапе пустая строка (если нет родителей) превратилась в массив с 1 пустым элементом. <br>    } <br> } </code> </div> <p> </p> <p>   </p>

Возврат к списку

Яндекс.Метрика