Начало работы
Установка
Установите Pitmaster с помощью Composer:
composer require pitmaster/pitmaster
Требования
- PHP 8.2+ с классами readonly, перечислениями и продвижением аргументов конструктора
- ext-zlib для сжатия и распаковки объектов (встроен в большинство установок)
- ext-json для файлов состояния операций и данных Git LFS API
- ext-mbstring, указанный в
composer.json, поэтому Composer требует его при установке - ext-ctype для проверки хешей (включён в большинство сборок PHP, но не указан в
composer.json)
Для основных операций с репозиторием не требуются двоичный файл git, FFI или внешние вспомогательные средства. У дополнительных функций есть дополнительные требования к среде выполнения: для выполнения хуков используется proc_open(), а транспорт SSH использует ext-ssh2, если он загружен, и в противном случае запускает системный двоичный файл ssh через proc_open().
Открытие существующего репозитория
use Pitmaster\Pitmaster;
$repo = Pitmaster::open('/path/to/project');
Открывает репозиторий по указанному пути. Pitmaster находит каталог .git (или разрешает файл .git для связанных рабочих деревьев) и инициализирует базу объектов, базу ссылок и конфигурацию.
open(), init() и clone() принимают массив параметров в качестве последнего аргумента:
// Do not run .git/hooks scripts for this handle
$repo = Pitmaster::open('/path/to/project', ['hooks' => false]);
// Do not start any process: no hooks, no fsmonitor hook, no clone/fetch/push, no SSH
$repo = Pitmaster::open('/path/to/project', Pitmaster::processFreeOptions());
По умолчанию хуки выполняются. Pitmaster::processFreeOptions() возвращает ['processes' => false, 'hooks' => false]; локальные операции чтения и записи для такого дескриптора продолжают работать.
Проверка, является ли путь репозиторием
if (Pitmaster::isRepository('/path/to/project')) {
$repo = Pitmaster::open('/path/to/project');
}
Инициализация нового репозитория
$repo = Pitmaster::init('/path/to/new-project');
Создаёт структуру каталогов .git с объектами, ссылками, HEAD (указывающим на refs/heads/main) и конфигурацией по умолчанию.
Чтобы создать репозиторий SHA-256, передайте формат объектов вторым аргументом:
$repo = Pitmaster::init('/path/to/new-project', 'sha256');
Идентификаторы объектов в таком репозитории состоят из 64 шестнадцатеричных символов, а в конфигурации записан extensions.objectformat = sha256. При последующем открытии репозитории формат определяется по этой записи конфигурации.
Чтение коммита HEAD
$head = $repo->head();
echo "Commit: {$head->id->hex}\n";
echo "Author: {$head->author}\n";
echo "Message: {$head->message}\n";
Метод head() разрешает HEAD (следуя символьным ссылкам) и возвращает объект Commit.
Список веток и тегов
// All branch names
$branches = $repo->branches();
// ['main', 'feature/login', 'bugfix/typo']
// Current branch name (null if detached)
$current = $repo->branch();
// 'main'
// All tag names
$tags = $repo->tags();
// ['v1.0.0', 'v1.1.0']
Просмотр истории коммитов
// Last 20 commits from HEAD
$commits = $repo->log(20);
foreach ($commits as $commit) {
echo substr($commit->id->hex, 0, 7) . " {$commit->message}\n";
}
Также можно начать с определённого коммита:
$from = $repo->resolve('feature/login');
$commits = $repo->log(10, $from);
Проверка состояния рабочего дерева
use Pitmaster\Status\FileStatus;
$entries = $repo->status();
foreach ($entries as $entry) {
if ($entry->index === FileStatus::Untracked) {
echo "?? {$entry->path}\n";
} elseif ($entry->index === FileStatus::Modified) {
echo "M {$entry->path}\n";
} elseif ($entry->worktree === FileStatus::Modified) {
echo " M {$entry->path}\n";
}
}
Добавление файлов в индекс и создание коммита
// Stage specific files
$repo->add('src/Feature.php', 'tests/FeatureTest.php');
// Create a commit
$commitId = $repo->commit('Add new feature with tests');
echo "Created commit: {$commitId->hex}\n";
Имя и адрес электронной почты автора определяются в таком порядке: переменные среды PITMASTER_AUTHOR_NAME / PITMASTER_AUTHOR_EMAIL, переменные среды GIT_AUTHOR_NAME / GIT_AUTHOR_EMAIL, константы PITMASTER_AUTHOR_NAME / PITMASTER_AUTHOR_EMAIL, собственная .git/config репозитория (user.name и user.email) и, наконец, Pitmaster <pitmaster@localhost>. Читается только файл конфигурации репозитория (и подключённые к нему файлы), но не ~/.gitconfig. Данные коммиттера определяются аналогично по именам *_COMMITTER_* и при отсутствии значения берутся из констант автора.
Вычисление различий
// Unstaged changes (worktree vs index)
$diffs = $repo->diff();
foreach ($diffs as $diff) {
echo $diff->format(); // Unified diff output
}
// Staged changes (index vs HEAD)
$staged = $repo->diffStaged();
Клонирование удалённого репозитория
$repo = Pitmaster::clone('https://github.com/user/repo.git', '/path/to/destination');
Обнаруживает ссылки, загружает pack-файл, настраивает ветки отслеживания удалённого репозитория и переключается на ветку по умолчанию. URL HTTP(S) используют умный протокол HTTP с переходом на простой HTTP при сбое; URL SSH используют транспорт SSH. Для поверхностного клонирования передайте глубину третьим аргументом: Pitmaster::clone($url, $path, 1).
Чтение любого объекта по хешу
$object = $repo->readObject($fullHash); // full 40-character (or 64 for SHA-256) hex hash
if ($object instanceof \Pitmaster\Object\Blob) {
echo $object->content;
} elseif ($object instanceof \Pitmaster\Object\Commit) {
echo $object->message;
}
Настройка
Pitmaster учитывает .git/config репозитория при получении сведений об авторе и URL удалённых репозиториев. Также можно задать глобальные значения по умолчанию с помощью констант PHP, объявленных до запуска Pitmaster:
define('PITMASTER_AUTHOR_NAME', 'Your Name');
define('PITMASTER_AUTHOR_EMAIL', 'you@example.com');
define('PITMASTER_HTTP_TIMEOUT', 60); // Seconds
define('PITMASTER_MAX_DELTA_CHAIN', 50); // Max delta chain depth
define('PITMASTER_OBJECT_CACHE_BYTES', '64M');
| Константа | По умолчанию | Действие |
|---|---|---|
PITMASTER_AUTHOR_NAME, PITMASTER_AUTHOR_EMAIL |
нет | Данные автора (см. порядок выше) |
PITMASTER_COMMITTER_NAME, PITMASTER_COMMITTER_EMAIL |
значения автора | Данные коммиттера |
PITMASTER_HTTP_TIMEOUT |
30 |
Тайм-аут умного протокола HTTP в секундах (целое число) |
PITMASTER_MAX_DELTA_CHAIN |
50 |
Максимальная глубина цепочки delta при чтении pack-файлов (целое число) |
PITMASTER_OBJECT_CACHE_ENTRIES |
1024 |
Объекты, хранящиеся в кэше объектов в памяти |
PITMASTER_OBJECT_CACHE_BYTES |
16M |
Лимит размера кэша объектов в байтах |
PITMASTER_PACK_RESOLVED_CACHE_ENTRIES |
4096 |
Разрешённые объекты delta, кэшируемые для каждого pack-файла |
PITMASTER_PACK_RESOLVED_CACHE_BYTES |
32M |
Лимит размера кэша этого pack-файла в байтах |
PITMASTER_MAX_PACK_MEMORY |
нет | Прежнее имя лимита размера кэша pack-файлов, используемое, только если PITMASTER_PACK_RESOLVED_CACHE_BYTES не определена |
Для значений в байтах можно указать целое число или строку с суффиксом k, m или g ('256M'). Недопустимые значения заменяются значением по умолчанию.
Переменные среды имеют приоритет над константами идентификации: PITMASTER_AUTHOR_NAME, PITMASTER_AUTHOR_EMAIL, PITMASTER_AUTHOR_DATE, соответствующие переменные PITMASTER_COMMITTER_*, а также собственные переменные GIT_AUTHOR_* и GIT_COMMITTER_* для git. Транспорт SSH считывает переменные PITMASTER_SSH_*, описанные в разделе Протоколы.
Для алгоритма хеширования нет константы. Формат объектов выбирается при создании репозитория (Pitmaster::init($path, 'sha256') или init --object-format=sha256 в CLI), а затем считывается из конфигурации репозитория.