Lecture des dépôts
Pitmaster lit les dépôts git en analysant directement les formats sur disque : objets libres (fichiers compressés avec zlib dans .git/objects/), fichiers pack (.git/objects/pack/), refs (fichiers dans .git/refs/ et packed-refs) et index (.git/index).
Ouvrir un dépôt
use Pitmaster\Pitmaster;
$repo = Pitmaster::open('/path/to/project');
Pitmaster prend en charge trois organisations de dépôt :
- Dépôts classiques :
.gitest un répertoire à la racine du projet. - Arbres de travail liés :
.gitest un fichier contenantgitdir: <path>pointant vers.git/worktrees/<name>/. - Dépôts nus : le chemin lui-même contient
HEAD,objects/, etc.
// Detection helpers
Pitmaster::isRepository('/path'); // true for any of the above
Pitmaster::isWorktree('/path'); // true only for linked worktrees
Lire les objets
Chaque donnée d’un dépôt git est stockée sous forme d’objet identifié par son hash : SHA-1 (40 caractères hexadécimaux) par défaut, ou SHA-256 (64 caractères hexadécimaux) dans les dépôts créés avec Pitmaster::init($path, 'sha256'). Il existe quatre types d’objets : blob, tree, commit et tag.
Les méthodes ci-dessous basées sur le hash attendent le hash hexadécimal complet ; les hash abrégés ne sont pas acceptés.
readObject
use Pitmaster\Object\Blob;
use Pitmaster\Object\Tree;
use Pitmaster\Object\Commit;
use Pitmaster\Object\Tag;
$object = $repo->readObject('a1b2c3d4e5f6...');
match (true) {
$object instanceof Blob => handleBlob($object),
$object instanceof Tree => handleTree($object),
$object instanceof Commit => handleCommit($object),
$object instanceof Tag => handleTag($object),
};
Les objets sont d’abord recherchés dans le stockage libre, puis dans les fichiers pack. Les recherches dans les fichiers pack utilisent la table de dispersion .idx pour une recherche binaire O(log n).
catFile
Pour récupérer simplement le contenu sans vérifier son type :
$content = $repo->catFile('a1b2c3d4e5f6...');
echo $content;
objectExists
if ($repo->objectExists('a1b2c3d4e5f6...')) {
// Object is in the repository
}
listObjects
$hashes = $repo->listObjects();
// ['a1b2c3d4...', 'f6e5d4c3...', ...]
Renvoie les hash hexadécimaux de tous les objets (libres et empaquetés).
Utiliser des blobs
Un blob contient le contenu brut d’un fichier.
$blob = $repo->readObject($hash);
echo $blob->content; // Raw file bytes
echo $blob->size(); // Content length
echo $blob->id->hex; // Object hash
Utiliser des arbres
Un arbre est une liste de répertoires. Chaque entrée comprend un mode, un nom et un hachage.
$tree = $repo->readObject($hash);
foreach ($tree->entries as $entry) {
echo "{$entry->mode} {$entry->name} {$entry->hash->hex}\n";
// 100644 README.md abc123...
// 40000 src def456...
// 100755 deploy.sh 789012...
if ($entry->isTree()) {
// Recurse into subdirectory (mode 40000)
} elseif ($entry->isExecutable()) {
// Executable file (mode 100755)
} elseif ($entry->isBlob()) {
// Regular file (any 10xxxx mode, so executables match too)
} elseif ($entry->isSymlink()) {
// Symbolic link (mode 120000)
} elseif ($entry->isGitlink()) {
// Submodule (mode 160000)
}
}
Travailler avec les commits
Un commit relie un instantané d’arbre à ses parents et à ses métadonnées.
$commit = $repo->head();
echo $commit->id->hex; // Full object hash
echo $commit->tree->hex; // Tree object hash
echo $commit->author; // "Name <email> timestamp tz"
echo $commit->committer; // "Name <email> timestamp tz"
echo $commit->message; // Full commit message
// Parent commits
foreach ($commit->parents as $parentId) {
$parent = $repo->readObject($parentId->hex);
}
// Merge detection
if ($commit->isMerge()) {
// Two or more parents
}
Travailler avec les tags
Les tags annotés sont des objets comprenant une cible, un type, un nom, un tagueur et un message.
$tag = $repo->readObject($hash);
echo $tag->object->hex; // Target object hash
echo $tag->objectType->value; // 'commit', 'tree', 'blob', or 'tag'
echo $tag->name; // Tag name
echo $tag->tagger; // "Name <email> timestamp tz"
echo $tag->message; // Tag message
Lire les références
HEAD actuel
$commit = $repo->head();
Résout HEAD (en suivant les références symboliques comme HEAD -> refs/heads/main -> commit hash) et renvoie l’objet commit.
Branche actuelle
$branch = $repo->branch(); // 'main' or null if detached
Lister les branches et les tags
$branches = $repo->branches(); // ['bugfix/typo', 'feature/login', 'main']
$tags = $repo->tags(); // ['v1.0.0', 'v1.1.0']
Toutes les références
$refs = $repo->allRefs();
// [
// 'refs/heads/main' => 'abc123...',
// 'refs/heads/feature' => 'def456...',
// 'refs/tags/v1.0.0' => '789012...',
// 'refs/remotes/origin/main' => 'abc123...',
// ]
Résoudre les révisions
$id = $repo->resolve('HEAD');
$id = $repo->resolve('main');
$id = $repo->resolve('v1.0.0');
$id = $repo->resolve('HEAD~3');
$id = $repo->resolve('main^2');
$id = $repo->resolve('3f2c1e0b9d6a4f8e7c5b2a1d0e9f8c7b6a5d4e3f');
L’analyseur de révisions prend en charge les opérateurs ~N (ancêtre) et ^N (parent), qui peuvent être chaînés sans limite. Les hachages doivent être fournis en entier.
Parcourir l’historique des commits
log
Les commits sont renvoyés du plus récent au plus ancien, selon l’horodatage du committer.
// Last 20 commits from HEAD
$commits = $repo->log(20);
foreach ($commits as $commit) {
$short = substr($commit->id->hex, 0, 7);
echo "{$short} {$commit->message}\n";
}
log à partir d’un commit spécifique
$from = $repo->resolve('feature/login');
$commits = $repo->log(10, $from);
log filtré par chemin de fichier
$commits = $repo->logPath('src/Repository.php', 20);
Renvoie uniquement les commits où le fichier indiqué a été modifié (ajouté, modifié, supprimé ou renommé) par rapport au premier parent. Le chemin doit correspondre exactement à un fichier ; les répertoires ne correspondent pas. Seuls les 5 * $limit commits les plus récents sont examinés : des correspondances plus anciennes peuvent manquer (#7).
show
$result = $repo->show('HEAD');
$commit = $result['commit'];
$diffs = $result['diff'];
echo "Author: {$commit->author}\n";
echo "Message: {$commit->message}\n\n";
foreach ($diffs as $diff) {
echo $diff->format();
}
Détection de la branche par défaut
$default = $repo->defaultBranch();
// Checks: remote HEAD symref -> local HEAD -> main/master fallback
Lorsque remote.origin.url est défini et que les processus sont activés, la première vérification envoie une requête HTTP intelligente au dépôt distant. Les erreurs réseau sont ignorées et les vérifications locales suivent.
Ancêtres de fusion
// Is feature fully merged into main?
$merged = $repo->isBranchMerged('feature/done', 'main');
// Find the merge base of two commits
$base = $repo->mergeBase(
$repo->resolve('main'),
$repo->resolve('feature/login'),
);