Ανάγνωση αποθετηρίων
Το Pitmaster διαβάζει αποθετήρια git αναλύοντας απευθείας τις μορφές αρχείων στον δίσκο: χαλαρά αντικείμενα (αρχεία συμπιεσμένα με zlib στο .git/objects/), αρχεία pack (.git/objects/pack/), αναφορές (αρχεία στα .git/refs/ και packed-refs) και το ευρετήριο (.git/index).
Άνοιγμα αποθετηρίου
use Pitmaster\Pitmaster;
$repo = Pitmaster::open('/path/to/project');
Το Pitmaster υποστηρίζει τρεις διατάξεις αποθετηρίων:
- Κανονικά αποθετήρια: το
.gitείναι κατάλογος στη ρίζα του έργου. - Συνδεδεμένα worktrees: το
.gitείναι αρχείο που περιέχει τοgitdir: <path>και δείχνει στο.git/worktrees/<name>/. - Γυμνά αποθετήρια: η ίδια η διαδρομή περιέχει το
HEAD,objects/κ.λπ.
// Detection helpers
Pitmaster::isRepository('/path'); // true for any of the above
Pitmaster::isWorktree('/path'); // true only for linked worktrees
Ανάγνωση αντικειμένων
Κάθε δεδομένο σε ένα αποθετήριο git αποθηκεύεται ως αντικείμενο που προσδιορίζεται από το hash του: SHA-1 (40 δεκαεξαδικοί χαρακτήρες) από προεπιλογή ή SHA-256 (64 δεκαεξαδικοί χαρακτήρες) σε αποθετήρια που δημιουργούνται με Pitmaster::init($path, 'sha256'). Υπάρχουν τέσσερις τύποι αντικειμένων: blob, tree, commit και tag.
Οι παρακάτω μέθοδοι που βασίζονται σε hash δέχονται ολόκληρο το δεκαεξαδικό hash· δεν γίνονται δεκτά συντομευμένα hash.
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),
};
Τα αντικείμενα αναζητούνται πρώτα στην αποθήκευση loose και μετά στα αρχεία pack. Οι αναζητήσεις σε αρχεία pack χρησιμοποιούν τον πίνακα fanout .idx για δυαδική αναζήτηση O(log n).
catFile
Για απλή ανάκτηση περιεχομένου χωρίς έλεγχο τύπου:
$content = $repo->catFile('a1b2c3d4e5f6...');
echo $content;
objectExists
if ($repo->objectExists('a1b2c3d4e5f6...')) {
// Object is in the repository
}
listObjects
$hashes = $repo->listObjects();
// ['a1b2c3d4...', 'f6e5d4c3...', ...]
Επιστρέφει δεκαεξαδικά hash για όλα τα αντικείμενα (loose και packed).
Εργασία με blobs
Ένα blob περιέχει ακατέργαστο περιεχόμενο αρχείου.
$blob = $repo->readObject($hash);
echo $blob->content; // Raw file bytes
echo $blob->size(); // Content length
echo $blob->id->hex; // Object hash
Εργασία με δέντρα
Ένα δέντρο είναι μια καταχώριση καταλόγου. Κάθε εγγραφή έχει λειτουργία, όνομα και hash.
$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)
}
}
Εργασία με commits
Ένα commit συνδέει ένα στιγμιότυπο δέντρου με τους γονείς και τα μεταδεδομένα του.
$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
}
Εργασία με tags
Τα σχολιασμένα tags είναι αντικείμενα με στόχο, τύπο, όνομα, συντάκτη tag και μήνυμα.
$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
Ανάγνωση refs
Τρέχον HEAD
$commit = $repo->head();
Επιλύει το HEAD (ακολουθώντας συμβολικά refs όπως το HEAD -> refs/heads/main -> commit hash) και επιστρέφει το αντικείμενο commit.
Τρέχον branch
$branch = $repo->branch(); // 'main' or null if detached
Καταχώριση branches και tags
$branches = $repo->branches(); // ['bugfix/typo', 'feature/login', 'main']
$tags = $repo->tags(); // ['v1.0.0', 'v1.1.0']
Όλα τα refs
$refs = $repo->allRefs();
// [
// 'refs/heads/main' => 'abc123...',
// 'refs/heads/feature' => 'def456...',
// 'refs/tags/v1.0.0' => '789012...',
// 'refs/remotes/origin/main' => 'abc123...',
// ]
Επίλυση revisions
$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');
Ο αναλυτής revision υποστηρίζει τους τελεστές ~N (πρόγονος) και ^N (γονέας), με αλυσιδωτή εφαρμογή χωρίς περιορισμό. Τα hash πρέπει να δίνονται ολόκληρα.
Περιήγηση στο ιστορικό commit
καταγραφή
Τα commits επιστρέφονται με πρώτο το νεότερο, ταξινομημένα με βάση τη χρονική σήμανση του 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 από συγκεκριμένο commit
$from = $repo->resolve('feature/login');
$commits = $repo->log(10, $from);
log φιλτραρισμένο κατά διαδρομή αρχείου
$commits = $repo->logPath('src/Repository.php', 20);
Επιστρέφει μόνο commits όπου το καθορισμένο αρχείο άλλαξε (προστέθηκε, τροποποιήθηκε, διαγράφηκε ή μετονομάστηκε) σε σύγκριση με τον πρώτο γονέα. Η διαδρομή πρέπει να είναι ακριβής διαδρομή αρχείου· οι κατάλογοι δεν αντιστοιχίζονται. Εξετάζονται μόνο τα νεότερα 5 * $limit commits, επομένως παλαιότερες αντιστοιχίες μπορεί να λείπουν (#7).
εμφάνιση
$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();
}
Εντοπισμός προεπιλεγμένου branch
$default = $repo->defaultBranch();
// Checks: remote HEAD symref -> local HEAD -> main/master fallback
Όταν έχει οριστεί το remote.origin.url και είναι ενεργοποιημένες οι διεργασίες, ο πρώτος έλεγχος στέλνει ένα έξυπνο αίτημα HTTP στο remote. Τα σφάλματα δικτύου αγνοούνται και ακολουθούν οι τοπικοί έλεγχοι.
Καταγωγή merge
// 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'),
);