PHP API
Pitmaster\Pitmaster
فئة Pitmaster\Pitmaster هي نقطة الدخول الثابتة. وتوفر طرقًا لإنشاء كائنات لفتح المستودعات وإنشائها واستنساخها، إلى جانب أدوات مساعدة لاكتشافها.
use Pitmaster\Pitmaster;
open
public static function open(string $path, array $options = []): Repository
افتح مستودعًا موجودًا في $path. ينبغي أن يكون المسار جذر شجرة العمل (الذي يحتوي على .git/). كما يدعم أشجار العمل المرتبطة (حيث يكون .git ملفًا يحتوي على gitdir: <path>) والمستودعات المجردة (حيث يكون $path هو دليل .git نفسه).
يقبل $options قيمتين منطقيتين، وتكون كلتاهما true افتراضيًا:
hooks: تشغيل نصوص.git/hooks. مرّرfalseلتخطيها لهذا المقبض.processes: السماح بكل ما يبدأ عملية أو يفتح نقلًا عبر الشبكة. مرّرfalseلتعطيل الخطافات وخطاف fsmonitor والاستنساخ والجلب والدفع ونقل عمليات SSH. وتظل عمليات القراءة والكتابة المحلية تعمل.
يطرح InvalidArgumentException إذا لم يكن المسار مستودع git.
$repo = Pitmaster::open('/home/user/project');
$repo = Pitmaster::open('/home/user/project', ['hooks' => false]);
$repo = Pitmaster::open('/home/user/project', Pitmaster::processFreeOptions());
init
public static function init(string $path, string $objectFormat = 'sha1', array $options = []): Repository
تهيئة مستودع جديد في $path. ينشئ بنية المجلدات .git مع objects/ وrefs/heads/ وrefs/tags/ وhooks/ وinfo/ وHEAD (يشير إلى refs/heads/main) وconfig افتراضي.
$objectFormat هو 'sha1' أو 'sha256'. يحصل المستودع SHA-256 على repositoryformatversion = 1 وextensions.objectformat = sha256 في إعداداته. وتؤدي أي قيمة أخرى إلى طرح InvalidArgumentException. يقبل $options المفاتيح نفسها التي يقبلها open().
يطرح RuntimeException إذا كان هناك مستودع بالفعل في المسار.
$repo = Pitmaster::init('/home/user/new-project');
$repo = Pitmaster::init('/home/user/sha256-project', 'sha256');
clone
public static function clone(string $url, string $path, ?int $depth = null, array $options = []): Repository
استنساخ مستودع بعيد. يهيئ مستودعًا جديدًا، ويكتشف المراجع البعيدة، ويجلب ملف الحزمة، ويعد فروع تتبع البعيد، وينشئ شجرة العمل. تستخدم عناوين SSH (ssh://... أو user@host:path) نقل SSH؛ أما العناوين الأخرى فتستخدم HTTP الذكي، وتعود إلى HTTP غير الذكي عند فشل التبادل الذكي. مرّر $depth لإجراء استنساخ سطحي.
يطرح RuntimeException عندما يكون $options['processes'] هو false. إذا فشل الاستنساخ ولم يكن $path موجودًا من قبل، يُحذف المجلد الذي أُنشئ جزئيًا.
$repo = Pitmaster::clone('https://github.com/user/repo.git', '/tmp/repo');
$repo = Pitmaster::clone('https://github.com/user/repo.git', '/tmp/shallow', 1);
$repo = Pitmaster::clone('https://github.com/user/repo.git', '/tmp/repo', null, ['hooks' => false]);
processFreeOptions
public static function processFreeOptions(): array
يعيد ['processes' => false, 'hooks' => false] لبيئات التشغيل التي يجب ألا تبدأ عمليات على المضيف. مرّره إلى open() أو init().
isRepository
public static function isRepository(string $path): bool
تحقّق مما إذا كان المسار مستودع git. يعيد true للمستودعات العادية (مجلد .git/)، وأشجار العمل المرتبطة (ملف .git)، والمستودعات العارية (عند وجود ملف HEAD).
if (Pitmaster::isRepository('/path/to/check')) {
// It's a git repo
}
isWorktree
public static function isWorktree(string $path): bool
تحقّق مما إذا كان المسار شجرة عمل مرتبطة (وليست المستودع الرئيسي). يعيد true فقط إذا كان .git ملفًا يحتوي على مرجع gitdir:.
if (Pitmaster::isWorktree('/path/to/worktree')) {
// It's a linked worktree
}
commonGitDir
public static function commonGitDir(string $path): ?string
حلّ مجلد git المشترك انطلاقًا من أي مسار تسجيل خروج. في المستودعات العادية، يكون هذا هو مجلد .git. وفي أشجار العمل المرتبطة، يكون مجلد git المشترك الذي يحتوي على الكائنات والإعدادات وpacked-refs. يعيد null إذا لم يكن المسار مستودعًا.
$common = Pitmaster::commonGitDir('/path/to/worktree');
// '/path/to/main-repo/.git'
Pitmaster\Repository
الفئة Pitmaster\Repository هي المقبض الرئيسي لجميع عمليات git. احصل على نسخة منها عبر Pitmaster::open() أو Pitmaster::init() أو Pitmaster::clone().
use Pitmaster\Repository;
موفّرات المسارات
gitDir
public function gitDir(): string
يعيد مجلد git الخاص بشجرة العمل. في المستودعات العادية يكون .git/. أما في أشجار العمل المرتبطة فهو .git/worktrees/<name>/.
commonGitDir
public function commonGitDir(): string
يعيد مجلد git المشترك. وهو نفسه gitDir() في المستودعات العادية. أما في أشجار العمل المرتبطة فهو مجلد .git/ للمستودع الرئيسي (حيث توجد الكائنات والإعدادات وpacked-refs).
workDir
public function workDir(): string
يعيد مسار جذر شجرة العمل.
isLinkedWorktree
public function isLinkedWorktree(): bool
يعيد true إذا كان مقبض هذا المستودع لشجرة عمل مرتبطة.
isBare, hooksEnabled, processesEnabled
public function isBare(): bool
public function hooksEnabled(): bool
public function processesEnabled(): bool
يوضح ما إذا كان المستودع بلا شجرة عمل، وأيٌّ من الخيارين hooks / processes ساري على هذا المقبض. تكون hooksEnabled() هي false دائمًا عند تعطيل العمليات.
الكائنات
readObject
public function readObject(string $hash): GitObject
اقرأ أي كائن باستخدام تجزئته السداسية الكاملة (40 حرفًا، أو 64 في مستودع SHA-256). لا تُقبل التجزئات المختصرة. يعيد نسخة من Blob أو Tree أو Commit أو Tag. يبحث أولًا في الكائنات المنفصلة، ثم في ملفات الحزم.
يطرح ObjectNotFoundException إذا لم يُعثر على التجزئة.
$object = $repo->readObject('a1b2c3d4e5f6...');
writeObject
public function writeObject(GitObject $object): ObjectId
اكتب كائنًا في مخزن الكائنات المنفصلة. يعيد ObjectId المحسوب.
use Pitmaster\Object\Blob;
$blob = Blob::fromContent('Hello, world!');
$id = $repo->writeObject($blob);
catFile
public function catFile(string $hash): string
أعد المحتوى الخام لكائن، بما يعادل git cat-file -p.
echo $repo->catFile('a1b2c3d4...');
objectExists
public function objectExists(string $hash): bool
تحقّق مما إذا كان الكائن موجودًا في المستودع (منفصلًا أو ضمن حزمة).
listObjects
public function listObjects(): array
أدرج كل تجزئات الكائنات في المستودع. يعيد مصفوفة من السلاسل السداسية.
المراجع
head
public function head(): Commit
يعيد إيداع HEAD الحالي. ويتبع المراجع الرمزية (HEAD -> refs/heads/main -> تجزئة الإيداع).
يطرح RuntimeException إذا لم يكن HEAD يشير إلى إيداع صالح (e.g، مستودع فارغ).
branch
public function branch(?string $name = null): ?string
من دون وسيطات، يعيد اسم الفرع الحالي (e.g، 'main')، أو null إذا كان HEAD منفصلًا.
عند تمرير اسم فرع، يحلّه إلى تجزئة إيداعه (سلسلة سداسية) أو يعيد null إذا لم يكن الفرع موجودًا.
$current = $repo->branch(); // 'main'
$hash = $repo->branch('feature'); // 'abc123...' or null
branches
public function branches(): array
يعيد مصفوفة مرتبة بأسماء جميع الفروع (من دون السابقة refs/heads/).
$branches = $repo->branches();
// ['bugfix/typo', 'feature/login', 'main']
tags
public function tags(): array
يعيد مصفوفة مرتبة بأسماء جميع الوسوم (من دون السابقة refs/tags/).
resolve
public function resolve(string $revision): ObjectId
حلّ تعبير مراجعة إلى ObjectId. يدعم ما يلي:
- التجزئات السداسية الكاملة (40 حرفًا، أو 64 في SHA-256). لا تُحل التجزئات المختصرة مثل
abc1234. HEAD- أسماء الفروع (
main،feature/login) - أسماء الوسوم (
v1.0.0) - مسارات المراجع الكاملة (
refs/heads/main) - تعبيرات المراجعة (
HEAD~3،main^2)
يطرح RuntimeException إذا تعذّر حلّ المراجعة.
$id = $repo->resolve('HEAD~3');
$id = $repo->resolve('v1.0.0');
$id = $repo->resolve('feature/login');
allRefs
public function allRefs(): array
يعيد جميع المراجع في مصفوفة ترابطية تربط اسم المرجع بتجزئته السداسية.
$refs = $repo->allRefs();
// ['refs/heads/main' => 'abc123...', 'refs/tags/v1.0.0' => 'def456...']
updateRef
public function updateRef(string $name, ObjectId $target): void
حدّث مرجعًا ليشير إلى هدف جديد.
$repo->updateRef('refs/heads/main', $commitId);
createBranch
public function createBranch(string $name, ?ObjectId $from = null): void
أنشئ فرعًا جديدًا. إذا كانت $from خالية، يُنشأ الفرع انطلاقًا من HEAD الحالي.
$repo->createBranch('feature/new-thing');
$repo->createBranch('hotfix', $repo->resolve('v1.0.0'));
deleteBranch
public function deleteBranch(string $name): void
احذف فرعًا بالاسم. يطرح RuntimeException إذا كان الفرع قيد تسجيل الخروج أو غير موجود. بخلاف git branch -d، لا يتحقق مما إذا كان الفرع قد دُمج.
$repo->deleteBranch('feature/old');
createLightweightTag
public function createLightweightTag(string $name, ?ObjectId $target = null): void
أنشئ وسمًا خفيفًا. إذا كانت $target خالية، يضع الوسم مباشرة على HEAD الحالي.
$repo->createLightweightTag('v2.0.0');
$repo->createLightweightTag('hotfix-start', $repo->resolve('main~2'));
createTag
public function createTag(string $name, string $message, ?ObjectId $target = null, ?string $tagger = null): ObjectId
أنشئ وسمًا مشروحًا. إذا كانت $target خالية، يضع الوسم على HEAD الحالي. يعيد ObjectId لكائن الوسم.
$tagId = $repo->createTag('v2.0.0', 'Release version 2.0.0');
deleteTag
public function deleteTag(string $name): void
احذف وسمًا بالاسم.
$repo->deleteTag('v1.0.0');
packRefs
public function packRefs(): void
أعد كتابة ملف packed-refs المشترك انطلاقًا من مجموعة المراجع المنفصلة الحالية، واحذف المراجع المنفصلة المشتركة المقابلة. في أشجار العمل المرتبطة، يكتب ذلك في مجلد git المشترك.
$repo->packRefs();
defaultBranch
public function defaultBranch(): string
حلّ الفرع الافتراضي للمستودع. يتحقق أولًا من مرجع HEAD الرمزي البعيد، ثم HEAD المحلي، ثم يعود إلى main أو master.
isBranchMerged
public function isBranchMerged(string $branch, ?string $target = null): bool
تحقّق مما إذا كان فرع قد دُمج بالكامل في فرع آخر (الفرع الافتراضي هو الخيار الافتراضي).
if ($repo->isBranchMerged('feature/done')) {
$repo->deleteBranch('feature/done');
}
checkout
public function checkout(string $target): void
بدّل الفروع أو افصل HEAD. يحدّث HEAD والفهرس وشجرة العمل. تكون $target اسم فرع أو وسمًا أو تجزئة كاملة أو تعبير مراجعة؛ وأي قيمة ليست فرعًا تفصل HEAD.
يطرح RuntimeException إذا وُجد تغيير محلي (مُدرج في الفهرس أو غير مُدرج) أو ملف غير متتبع في مسار يختلف بين الشجرة الحالية والشجرة المستهدفة.
لا تُنقل التغييرات غير المودعة في الملفات الأخرى المتتبعة: يُعاد إنشاء الفهرس وشجرة العمل من الشجرة المستهدفة، لذا تُفقد التعديلات على الملفات المتطابقة في الجانبين، بينما يحتفظ بها git (#2). أودعها أو خزّنها مؤقتًا أولًا. تعيد merge() وcherryPick() وrevert() وrebase() وطرق bisect إنشاء شجرة العمل بالطريقة نفسها.
$repo->checkout('feature/login');
$repo->checkout($repo->resolve('v1.0.0')->hex); // Detached HEAD
الفهرس
index
public function index(): Index
اقرأ الفهرس الحالي (منطقة التجهيز) من .git/index وأعده.
add
public function add(string ...$paths): void
أدرج الملفات في الفهرس. يقرأ كل ملف من شجرة العمل، وينشئ كائن blob، ويحدّث الفهرس. يجب أن تكون كل وسيطة مسار ملف (أو رابط رمزي) نسبةً إلى جذر شجرة العمل؛ لا تُوسّع المجلدات وأنماط glob، ويطرح الملف المفقود RuntimeException.
$repo->add('src/Feature.php', 'tests/FeatureTest.php');
remove
public function remove(string ...$paths): void
public function removeCached(string ...$paths): void
أزل المسارات المتتبعة من الفهرس وشجرة العمل معًا. يدعم --cached و-r / --recursive في قائمة الوسيطات لمحاكاة سلوك Git.
$repo->remove('old-file.txt');
$repo->remove('-r', 'src');
$repo->remove('--cached', 'old-file.txt');
$repo->removeCached('old-file.txt');
mv
public function mv(string $source, string $destination): void
انقل ملفًا أو أعد تسميته في شجرة العمل والفهرس معًا.
$repo->mv('old-name.php', 'new-name.php');
الإيداعات
commit
public function commit(?string $message = null, ?string $author = null): ObjectId
أنشئ إيداعًا من الفهرس الحالي. ينشئ تسلسلًا هرميًا للشجرة من مدخلات الفهرس، وينشئ كائن الإيداع مع HEAD كأصل (إن وُجد)، ويحدّث HEAD. يعيد ObjectId للإيداع الجديد.
لا يجوز أن تكون $message هي null إلا عند توقف دمج أو انتقاء إيداع أو تراجع أو إعادة تأسيس بسبب تعارض؛ عندها تُستخدم الرسالة المُعدّة. وإلا فإن رسالة null تؤدي إلى طرح RuntimeException('Commit message required'). ويُطرح أيضًا إذا احتوى الفهرس على مسارات لم تُحل تعارضاتها، أو كان فارغًا في مستودع بلا إيداعات، أو لم تتغير الشجرة عن HEAD.
المعامل $author عبارة كاملة عن مؤلف git (Name <email> timestamp timezone). إذا كان خاليًا، يُحدّد من متغيرات البيئة والثوابت و.git/config، وفق الترتيب الموضح في البدء.
$id = $repo->commit('Fix null pointer bug');
show
public function show(string $revision): array
اعرض إيداعًا أو ما يشبهه والفروق بينه وبين الأصل الأول. عندما تُحل المراجعة إلى وسم مشروح، تتضمن القيمة المعادة أيضًا ['tag' => Tag]، ويكون commit هو الإيداع المستهدف بعد فك الوسم.
$result = $repo->show('HEAD');
echo $result['commit']->message;
foreach ($result['diff'] as $diff) {
echo $diff->format();
}
reset
public function reset(string $revision, string $mode = 'mixed'): void
أعد HEAD إلى إيداع. الأوضاع:
'soft': نقل HEAD فقط'mixed': نقل HEAD وإعادة تعيين الفهرس (افتراضيًا)'hard': نقل HEAD وإعادة تعيين الفهرس وشجرة العمل
$repo->reset('HEAD~1', 'soft');
$repo->reset('main', 'hard');
restore
public function restore(string $path, ?string $source = null, bool $staged = false, bool $worktree = false): void
استعد مسارًا من الفهرس أو من مراجعة مصدر محددة. إذا لم يُضبط أي من العلمين، يستعيد Pitmaster شجرة العمل من الفهرس (أو من $source عند تمريره). أما staged: true فيستعيد الفهرس من HEAD (أو $source) ويترك شجرة العمل كما هي؛ مرّر staged: true, worktree: true لاستعادة كليهما.
$repo->restore('src/File.php'); // Worktree from index
$repo->restore('src/File.php', staged: true); // Index from HEAD
$repo->restore('src/File.php', 'HEAD~1'); // Worktree from another commit
$repo->restore('src/File.php', 'HEAD~1', staged: true, worktree: true); // Index + worktree from another commit
cherryPick
public function cherryPick(string $revision): ObjectId
public function cherryPickContinue(): ObjectId
public function cherryPickAbort(): void
طبّق إيداعًا كإيداع جديد على الفرع الحالي مع الحفاظ على المؤلف الأصلي. إذا أوقف التعارض العملية، فحلّه وأدرج المسارات في الفهرس، ثم استدعِ cherryPickContinue() أو cherryPickAbort().
$newId = $repo->cherryPick('feature~2');
// After resolving conflicts:
$repo->add('src/File.php');
$repo->cherryPickContinue();
revert
public function revert(string $revision): ObjectId
public function revertContinue(): ObjectId
public function revertAbort(): void
أنشئ إيداعًا يلغي إيداعًا آخر. إذا أوقف التعارض التراجع، فحلّه وأدرج المسارات في الفهرس، ثم استدعِ revertContinue() أو revertAbort().
$revertId = $repo->revert('HEAD~1');
// After resolving conflicts:
$repo->add('src/File.php');
$repo->revertContinue();
rebase
public function rebase(string $onto): array
public function rebaseContinue(): array
public function rebaseAbort(): void
public function rebaseSkip(): array
أعد تأسيس الفرع الحالي على مراجعة أخرى. تغطي Pitmaster حاليًا عمليات إعادة التأسيس الخطية مع حالة توقف متوافقة مع Git عند حدوث تعارض، إضافةً إلى المتابعة والإلغاء والتخطي. يجب أن يشير HEAD إلى فرع.
تعيد rebase() وrebaseContinue() وrebaseSkip() القيمة ['success' => bool, 'commits' => int, 'conflicts' => list<string>]: ما إذا كانت إعادة التأسيس قد اكتملت، وعدد الإيداعات المطبّقة، والمسارات المتعارضة عند التوقف.
$result = $repo->rebase('main');
if (!$result['success']) {
// Resolve conflicts, then continue or skip/abort.
$repo->add('src/File.php');
$repo->rebaseContinue();
}
الحالة
status
public function status(): array
احسب حالة شجرة العمل. يعيد مصفوفة من كائنات StatusEntry، يحتوي كل منها على:
path: مسار الملفindex: تعدادFileStatusللتغييرات بين HEAD والفهرسworktree: تعدادFileStatusللتغييرات بين الفهرس وشجرة العملorigPathوrenameScore: يُضبطان للمدخلات التي أُعيدت تسميتها، وإلا فهماnull
تكون قيمة الملفات غير المتتبعة FileStatus::Untracked في العمودين. لا تُعرض الملفات المتجاهلة.
foreach ($repo->status() as $entry) {
echo $entry->shortFormat() . "\n"; // "M src/File.php", "?? notes.txt"
}
statusPorcelainV2
public function statusPorcelainV2(): string
مخرجات حالة قابلة للقراءة آليًا بتنسيق porcelain v2 الخاص بـ git.
echo $repo->statusPorcelainV2();
// 1 M. N... 000000 000000 000000 0000...0000 0000...0000 modified-file.txt
// ? untracked-file.txt
الفرق
diff
public function diff(?string $pathspec = null, string $algorithm = 'myers'): array
اعرض الفرق بين شجرة العمل والفهرس (التغييرات غير المدرجة). يعيد مصفوفة من كائنات DiffResult. يرشّح $pathspec النتائج بمسار ملف واحد مطابق تمامًا. تكون $algorithm هي 'myers' (افتراضيًا) أو 'patience' أو 'histogram' أو 'minimal'؛ وأي قيمة أخرى تطرح InvalidArgumentException.
$diffs = $repo->diff();
foreach ($diffs as $diff) {
echo $diff->format(); // Unified diff output
}
diffStaged
public function diffStaged(?string $pathspec = null, string $algorithm = 'myers'): array
اعرض الفرق بين الفهرس وHEAD (التغييرات المدرجة). يعيد DiffResult[] مع اكتشاف إعادة التسمية بين الملفات المحذوفة والمضافة.
يُتجاهل حاليًا المعامل $pathspec، لذا تُعاد جميع الملفات المدرجة، وتعيد الطريقة مصفوفة فارغة قبل الإيداع الأول (#5).
$staged = $repo->diffStaged();
diffTree
public function diffTree(ObjectId $a, ObjectId $b, string $algorithm = 'myers'): array
قارن شجرتين باستخدام ObjectId الخاص بهما. يعيد DiffResult[]. مرّر معرّفات الشجرة، لا معرّفات الإيداع: لا يُقرأ معرّف الإيداع على أنه شجرة وينتج عنه نتيجة فارغة.
$old = $repo->readObject($repo->resolve('HEAD~1')->hex);
$new = $repo->head();
$diffs = $repo->diffTree($old->tree, $new->tree);
السجل
log
public function log(int $limit = 50, ?ObjectId $from = null): array
استعرض سجل الإيداعات، من الأحدث أولًا حسب الطابع الزمني للمودِع. يعيد Commit[]. إذا كانت $from خالية، يبدأ من HEAD. يعيد مصفوفة فارغة إذا لم يكن لـ HEAD إيداع بعد.
$commits = $repo->log(10);
logAll
public function logAll(int $limit = 50): array
استعرض الإيداعات التي يمكن الوصول إليها من كل مرجع ومن HEAD، من الأحدث أولًا. يعيد Commit[].
logOneline
public function logOneline(int $limit = 50, bool $all = false, ?string $path = null): array
أعد أسطر السجل بصيغة git log --oneline (abc1234 Subject)، انطلاقًا من HEAD أو من جميع المراجع ($all)، أو مع ترشيحها حسب المسار.
logPath
public function logPath(string $path, int $limit = 50): array
سجل مرشّح حسب مسار ملف. يعيد الإيداعات التي يضيف فرقها عن الأصل الأول ذلك الملف المحدد أو يعدّله أو يحذفه أو يعيد تسميته فقط. لا تطابق مسارات المجلدات.
يُفحص أحدث 5 * $limit إيداع فقط، لذا قد لا تظهر في النتيجة الإيداعات الأقدم التي تمس الملف (#7).
$commits = $repo->logPath('src/Repository.php', 20);
الدمج
merge
public function merge(string $branch, string $strategy = 'recursive'): MergeResult
public function mergeOctopus(array $branches): MergeResult
public function mergeContinue(): ObjectId
public function mergeAbort(): void
ادمج فرعًا (أو أي مراجعة) في HEAD. يكتشف عمليات الدمج بالتقديم السريع تلقائيًا. أما عمليات الدمج التي لا تتم بالتقديم السريع، فتتحقق من التعارضات على مستوى الشجرة وتنشئ إيداع دمج عند خلوّها من التعارض. عند حدوث تعارض، تحفظ حالة دمج متوافقة مع Git في الفهرس وشجرة العمل؛ حلّ المسارات وأدرجها في الفهرس، ثم استدعِ mergeContinue() أو mergeAbort().
يسجل $strategy 'ours' إيداع دمج يحتفظ بشجرة HEAD؛ وأي قيمة أخرى تستخدم الدمج التكراري الافتراضي. يدمج mergeOctopus() فرعين أو أكثر في إيداع واحد. إذا تعارض أي فرع، يعيد نتيجة غير نظيفة من دون كتابة حالة الدمج أو إنشاء إيداع.
يؤدي دمج فرع موجود بالفعل ضمن HEAD إلى إنشاء إيداع دمج آخر بدلًا من الإبلاغ عن «محدّث بالفعل» (#6). وتُستبدل التغييرات غير المودعة في الملفات المتتبعة كما هو موضح ضمن checkout().
يعيد MergeResult مع:
clean: ما إذا نجح الدمج من دون تعارضاتcommitId: معرّف إيداع الدمج (إذا كان الدمج نظيفًا)conflictPaths: مصفوفة بمسارات الملفات المتعارضة (إذا لم يكن نظيفًا)mergedContents: المسار المتعارض ومحتوى الملف مع علامات التعارض (إذا لم يكن نظيفًا)
$result = $repo->merge('feature/login');
if ($result->clean) {
echo "Merged: {$result->commitId->hex}\n";
} else {
echo "Conflicts in: " . implode(', ', $result->conflictPaths) . "\n";
$repo->add('src/File.php');
$repo->mergeContinue();
}
mergeBase
public function mergeBase(ObjectId $a, ObjectId $b): ?ObjectId
اعثر على أساس الدمج (أدنى سلف مشترك) لإيداعين. يعيد null إذا لم يوجد سلف مشترك.
$base = $repo->mergeBase(
$repo->resolve('main'),
$repo->resolve('feature/login'),
);
التقسيم الثنائي
public function bisectStart(string $bad, string $good): ObjectId
public function bisectGood(?string $revision = null): ?ObjectId
public function bisectBad(?string $revision = null): ?ObjectId
public function bisectReset(): void
ابحث ثنائيًا عن الإيداع الذي أدخل تغييرًا. يسجل bisectStart() المراجعتين السيئة والجيدة، ويسجل خروج المرشح الأول ويعيده. يحدد bisectGood() وbisectBad() HEAD الحالي (أو $revision)، ويسجلان خروج المرشح التالي ويعيدانه. عند بقاء مشتبه به واحد، يُعاد ذلك الإيداع ويبقى مرشحًا؛ فهو أول إيداع سيئ. ينهي bisectReset() الجلسة ويعيدك إلى الفرع أو الإيداع الذي بدأت منه.
$candidate = $repo->bisectStart('HEAD', 'v1.0.0');
// test $candidate ...
$candidate = $repo->bisectBad();
$candidate = $repo->bisectGood();
$repo->bisectReset();
الشبكة
fetch
public function fetch(string $remote = 'origin', ?int $depth = null): void
اجلب التغييرات من مستودع بعيد. ينزّل الكائنات الجديدة ويحدّث مراجع تتبع البعيد. مرّر $depth لزيادة عمق السجل السطحي أو تحديده.
يطرح RuntimeException كل من fetch() وطرق push*() عند استخدام مقبض مفتوح مع ['processes' => false].
$repo->fetch();
$repo->fetch('upstream');
push
public function push(string $remote = 'origin', ?string $branch = null): void
public function pushForceWithLease(string $remote = 'origin', ?string $branch = null, ?ObjectId $expected = null): void
public function pushAtomic(string $remote = 'origin', array $branches = []): void
public function pushMirror(string $remote = 'origin'): void
ادفع الفرع الحالي (أو فرعًا محددًا) إلى مستودع بعيد. تتوفر خيارات القوة مع lease والذرية والنسخ المتطابق لتحديث المراجع بنطاق أوسع أو بقيود أشد.
$repo->push();
$repo->push('origin', 'feature/login');
$repo->pushForceWithLease('origin', 'main', $repo->resolve('refs/remotes/origin/main'));
$repo->pushAtomic('origin', ['main', 'release']);
$repo->pushMirror();
أشجار العمل
addWorktree
public function addWorktree(string $path, string $branch, ?ObjectId $from = null, ?string $name = null): Worktree
أضف شجرة عمل مرتبطة. ينشئ الفرع إن لم يكن موجودًا، ويعدّ بيانات الشجرة الوصفية، وينشئ ملفات شجرة العمل. مرّر $name عند الحاجة إلى معرّف بيانات وصفية ثابت يختلف عن اسم المجلد الأساسي لتسجيل الخروج.
$wt = $repo->addWorktree('/tmp/review', 'feature/review');
$wt = $repo->addWorktree('/tmp/checkouts/review', 'feature/review', name: 'review-wt');
removeWorktree
public function removeWorktree(string $pathOrName, bool $force = false): void
أزل شجرة عمل مرتبطة. استخدم $force = true لإزالتها حتى إن كانت مقفلة.
worktrees
public function worktrees(): array
أدرج جميع أشجار العمل (الرئيسية والمرتبطة). يعيد Worktree[].
foreach ($repo->worktrees() as $wt) {
echo "{$wt->path} [{$wt->branch}]\n";
}
الإعدادات
config
public function config(): GitConfig
الوصول إلى إعدادات git للمستودع. اقرأ قيم الإعدادات واكتبها.
$config = $repo->config();
$name = $config->get('user.name');
$config->set('user.email', 'new@example.com');
الوصول الداخلي
تتيح هذه الطرق الوصول إلى المكونات الداخلية لحالات الاستخدام المتقدمة.
objectDatabase
public function objectDatabase(): ObjectDatabase
الوصول إلى قاعدة بيانات الكائنات الخام (المخازن المنفصلة ومخازن الحزم).
refDatabase
public function refDatabase(): RefDatabase
الوصول إلى قاعدة بيانات المراجع الخام (المراجع المنفصلة والمجمّعة).
الفئات منخفضة المستوى
هذه الفئات غير مغلّفة بواسطة Repository، ويُنشأ مثيل منها باستخدام مكوناته الداخلية.
Pitmaster\Graph\Blame
public function blame(ObjectId $headId, string $path): array
يعيد مدخلًا لكل سطر من $path عند $headId: ['line' => int, 'hash' => string, 'author' => string, 'content' => string]. أما author فهو سلسلة الهوية الكاملة (Name <email> timestamp timezone).
use Pitmaster\Graph\Blame;
$blame = new Blame($repo->objectDatabase());
foreach ($blame->blame($repo->resolve('HEAD'), 'src/File.php') as $line) {
echo substr($line['hash'], 0, 8) . " {$line['content']}\n";
}
Pitmaster\Graph\Grep
public function grep(ObjectId $treeId, string $pattern, string $prefix = '', array $options = []): array
يبحث في كتل شجرة. يعيد ['path' => string, 'line' => int, 'content' => string] لكل سطر مطابق. الخيارات: regex (التعامل مع النمط كنمط PCRE) وignore_case. يؤدي التعبير النمطي غير الصالح إلى طرح InvalidArgumentException.
use Pitmaster\Graph\Grep;
$grep = new Grep($repo->objectDatabase());
$matches = $grep->grep($repo->head()->tree, 'TODO', '', ['ignore_case' => true]);
Pitmaster\Ref\Notes
public function get(ObjectId $commitId, string $notesRef = 'refs/notes/commits'): ?string
public function set(ObjectId $commitId, string $noteContent, string $notesRef = 'refs/notes/commits'): void
public function remove(ObjectId $commitId, string $notesRef = 'refs/notes/commits'): void
public function listAll(string $notesRef = 'refs/notes/commits'): array
public function merge(string $sourceRef, string $targetRef = 'refs/notes/commits'): void
يقرأ ملاحظات git المخزنة ضمن مرجع ملاحظات ويكتبها. يعيد listAll() تجزئة الإيداع مقابل محتوى الملاحظة.
use Pitmaster\Ref\Notes;
$notes = new Notes($repo->objectDatabase(), $repo->refDatabase());
$notes->set($repo->resolve('HEAD'), "Reviewed\n");
echo $notes->get($repo->resolve('HEAD'));