إن إنشاء الـ worktrees أمر سهل، ونسيانها أسهل. تُنشئ واحدًا ليعمل فيه وكيل على فرع بمعزل عن غيره، فيُنهي الوكيل عمله، وتراجع أنت الفرق (diff)، ثم يظل المجلد جالسًا في مكانه. وبعد أسبوع، يتمدد ناتج git worktree list خارج حدود الشاشة، ويقرأ du -sh على المستودع اثني عشر جيجابايت، وثلاثة من تلك المجلدات تشير إلى فروع دُمجت وحُذفت منذ أيام. لم يختر أحد الإبقاء عليها؛ بل تراكمت لأن الإنشاء كان أمرًا واحدًا والتنظيف كان عبئًا.
هذا هو الجزء الذي لا يحذّرك منه أحد في العمل المتوازي بالوكلاء. فبدائية العزل موثّقة جيدًا؛ ودليلنا إلى worktrees في git لوكلاء البرمجة بالذكاء الاصطناعي يغطي آليات الإنشاء والتفريع بالتفصيل. أما دورة الحياة بعد لحظة «الانتهاء» فهي حيث يكمن الألم، وهي تزداد سوءًا بسرعة عندما يكون المُنشئ للـ worktrees وكيلًا قادرًا على فتح خمسة منها في دقيقة ولا يملك أي غريزة للترتيب. هذه المقالة عن النصف الثاني: انضباط التنظيف، والأوامر الدقيقة، ونمط الفشل الذي ينتظرك في كل خطوة، والنقطة التي يتوقف عندها سكربت مكتوب يدويًا عن أن يكون كافيًا.
Sharkly هو أحد الحلول لمشكلة «من ينظّف؟»: فهو يشغّل كل مهمة داخل worktree خاص بها، ويتعامل مع ذلك الـ worktree كجزء من دورة حياة المهمة لا كمجلد عليك أن تتذكره. سنصل إلى ذلك. لكن أولًا، الآليات، لأن عليك أن تفهم النسخة اليدوية قبل أن تقرر التوقف عن أدائها بيدك.

باختصار
الـ worktree في git هو دليل عمل ثانٍ مرتبط بمستودع واحد، وله فرعه وفهرسه وHEAD الخاص به. والوكلاء يجعلونها تتراكم لأن كل تشغيل يريد العزل، ولا أحد منهم ينظّف بعد نفسه. ومسار التنظيف أربعة أوامر: git worktree list لرؤية الموجود، وgit worktree remove لحذف worktree منتهٍ، وgit worktree prune لمسح البيانات الوصفية القديمة، وgit worktree lock لحماية واحد تريد الإبقاء عليه. ولكل منها نمط فشل يترك وراءه مجلدات يتيمة، أو عملًا ضائعًا، أو فروعًا مقفلة، إن أهملت خطوة منه. النسخة اليدوية تكفي مع عدد قليل من الـ worktrees، أما بعد ذلك فاربط كل worktree بسجل مهمة حتى يصبح للتنظيف مسؤول، وهو ما يفعله Sharkly تلقائيًا.
لماذا تتراكم الـ worktrees أسرع مع الوكلاء
للـ worktree دورة حياة يديرها الإنسان بطبيعته: تُنشئه، تعمل فيه، تدمجه، ثم تحذفه. وخطوة الحذف تعتمد على تذكّر الإنسان. والوكلاء يكسرون هذا الافتراض في اتجاهين في آنٍ واحد.
أولًا، الحجم. مطوّر واحد يشغّل أربعة وكلاء بالتوازي يُنشئ أربعة worktrees في الساعة، لا واحدًا في اليوم. ومقالنا عن تشغيل عدة وكلاء Claude Code بالتوازي يشرح لماذا يتصاعد هذا العدد بهذه السرعة. وثانيًا، غياب غريزة التنظيف. فالوكيل يقرأ المهمة، ويؤدي العمل، ويكتب النتيجة، ثم يتوقف. وهو لا يفكر: «لقد دُمج الفرع، إذن هذا المجلد صار عبئًا بلا فائدة الآن». لذا تبقى المجلدات حيّة بعد أن تنتهي فائدتها، وهذه البقايا هي المشكلة: نسخ عمل قديمة على فروع محذوفة، وتجارب نصف منتهية تخلى عنها الوكيل، وأشجار node_modules مكررة تلتهم مساحة القرص في كل واحد منها.
والتكلفة ليست مجردة. فكل worktree هو نسخة عمل كاملة إضافة إلى ما ثبّته الوكيل داخلها. عشرة worktrees في مستودع JavaScript متوسط الحجم تعني عشرة مجلدات node_modules. يمتلئ القرص، ويتباطأ git status عبر المجموعة كلها، ولا يعود الشخص التالي الذي يشغّل git worktree list قادرًا على التمييز بين المجلدات التي فيها عمل حقيقي وتلك التي هي مجرد مخلفات.
مسار التنظيف، خطوة بخطوة
إليك دورة الحياة كاملة في أربعة أوامر. نفّذها بهذا الترتيب وتبقى أنماط الفشل مغلقة.
رؤية ما هو موجود. ابدأ كل جولة تنظيف من هنا:
git worktree list
# /repo a1b2c3d [main]
# /repo-auth-refactor 4d5e6f7 [auth-refactor]
# /repo-fix-logging 8g9h0i1 [fix-logging]
نمط الفشل إن أهملت هذه الخطوة: أن تحذف المجلد الخطأ. فوكيلان على فرعين متشابهي الاسم ينتجان مساري worktree متشابهين، وحذف الحي منهما يكلفك عملًا غير مُودَع. اقرأ القائمة قبل أن تلمس أي شيء.
حذف واحد منتهٍ. بعد دمج فرع الـ worktree وتأكدك من عدم وجود أي تغييرات غير محفوظة فيه:
git worktree remove /repo-fix-logging
نمط الفشل: يرفض remove الحذف إذا كان في الـ worktree تغييرات غير مُودَعة أو ملفات غير متتبعة، وهذا هو السلوك الآمن الافتراضي. أما الخطوة غير الآمنة فهي التمدد إلى --force لإسكات الخطأ. فاستخدام القوة على worktree متسخ يحذف عملًا حقيقيًا أنتجه الوكيل ولم يودعه قط. وإذا اشتكى remove، فاذهب وانظر في المجلد أولًا؛ فالشكوى تكون صحيحة في الغالب.
تقليم البيانات الوصفية القديمة. إذا حُذف مجلد worktree بالأمر rm -rf بدل git worktree remove، فإن git يظل محتفظًا بسجل إداري له. وهذا هو اليتيم الكلاسيكي:
git worktree prune
git worktree prune --dry-run # preview first
نمط الفشل: إهمال prune يترك مدخلات شبحيّة في git worktree list، والأسوأ من ذلك أن git قد يرفض إعادة استخدام فرع يظن أنه ما زال مسحوبًا في مكان ما. وprune يمسح هذه القيود الدفترية. شغّل --dry-run أولًا لترى ما سيسقطه قبل أن يُسقطه. كما يوضّح توثيق git worktree بدقة ما يعتبره prune قديمًا.
قفل ما تريد الإبقاء عليه. الـ worktree الموجود على قرص خارجي بطيء، أو الذي يحمل تجربة طويلة الأمد، لا ينبغي أن يقتلعه سكربت تنظيف شرس:
git worktree lock /repo-experiment --reason "release repro, keep until 2.0 ships"
نمط الفشل: بدون قفل، قد تحذف مهمة تنظيف ليلية تقلّم كل ما هو «قديم» worktree أوقفته أنت عن قصد. والقفل مع سلسلة سبب هو الفرق بين سكربت تنظيف تثق به وآخر تعطّله بعد أن يلتهم شيئًا مهمًا.
أين يتوقف سكربت التنظيف عن التوسع
يمكنك أتمتة الخطوات الأربع كلها. فمهمة cron تسرد الـ worktrees، وتتحقق من كل فرع مقابل السجل المدمج، وتحذف المدمَج منها، هي ثلاثون سطرًا من الصدفة (shell). وهي تعمل، وتكفي لمطوّر يعمل منفردًا ويشغّل بضعة وكلاء. استخدم السكربت عندما يكون عدد الـ worktrees صغيرًا وشخص واحد يملك المستودع.
لكنه يتوقف عن التوسع عند الحكم، لا عند معدل التنفيذ. فالسكربت يستطيع أن يعرف أن فرعًا قد دُمج، لكنه لا يستطيع أن يعرف أن worktree ما يحمل عملًا أنتجه وكيل ولم تروّجه أنت بعد، أو أن فرعًا «قديمًا» هو في الحقيقة مهمة موقوفة مؤقتًا ينوي أحدهم استئنافها. وفي اللحظة التي يحتاج فيها التنظيف إلى معرفة مقصد الـ worktree، فإن قاعدة لا ترى سوى حالة git ستحذف يومًا شيئًا كان مهمًا. والحد الآخر هو التنسيق: على جهاز مشترك، لا يعرف سكربت تنظيف أحدهم ما تفعله وكلاء شخص آخر، ولم يعد السؤال «هل الحذف آمن؟» قابلًا للإجابة من git worktree list وحده. ولمزيد حول مشكلة الجهاز المشترك، راجع تجميعتنا لـأدوات إدارة وكلاء البرمجة بالذكاء الاصطناعي المتوازيين.
ما الذي يضيفه لوح المهام
الحل هو أن تمنح كل worktree مالكًا يعيش أطول من جلسة الطرفية. اربط كل worktree بسجل مهمة، فيصبح التنظيف ليس سؤال «أي المجلدات تبدو قديمة» بل «أي المهام انتهت ورُوجعت».
هذه هي الطبقة التي يعمل عندها Sharkly. لديك وكلاء برمجة بالفعل؛ وSharkly يحوّلهم إلى فريق بأن يجعل كل تشغيل «مهمة». وعندما تبدأ المهمة، تجهّز الخدمة المحلية على الحاسوب المتصل worktree معزولًا لها. وعندما يعود ناتج المهمة للمراجعة ويقبله شخص، تنتهي دورة حياة الـ worktree مع المهمة بدل أن تظل مجلدًا لا يتذكره أحد. وهكذا يصبح لسؤال التنظيف جواب، لأن الـ worktree لم يكن يومًا مجهول الهوية.
ويبقى تقسيم العمل نزيهًا. الوكلاء يطالبون بالمهام، ويعملون في worktrees معزولة، ويشغّلون الاختبارات، ويعيدون الفرق (diff). والناس يحددون الاتجاه ويقررون خطوة الدمج والإصدار. وSharkly ليس بديلًا عن Claude Code أو Codex أو أوامر git أعلاه؛ بل يضيف السجل المشترك كي يظل العزل والتقدم والنتائج والتنظيف ظاهرين من الطلب حتى الإصدار بدل أن يتشتتوا بين نوافذ الطرفية. إن كنت تشغّل وكيلًا واحدًا ويستغرق التنظيف اليدوي عشر ثوانٍ، فلا تحتاج إلى هذا بعد. أما عندما يتمدد ناتج `git worktree list` خارج الشاشة، فمشكلة الإدارة هي المشكلة الحقيقية، وملاحظتنا عن إبقاء البشر في حلقة القرار عبر تشغيلات الوكلاء تغطي الجانب المتعلق بالمراجعة.
قائمة التحقق التي يمكنك تنفيذها اليوم
نفّذ هذه الجولة على أي مستودع عمل فيه الوكلاء:
- شغّل
git worktree listواقرأه كاملًا قبل حذف أي شيء. - لكل worktree منتهٍ: تأكد من دمج الفرع، وتحقق من نظافة المجلد، ثم استخدم
git worktree remove(ولا تستخدم--forceأبدًا على شجرة متسخة). - شغّل
git worktree prune --dry-run، وراجع النتيجة، ثمgit worktree pruneلمسح البيانات الوصفية اليتيمة. - استخدم
git worktree lockلأي worktree تُبقيه عن قصد، مع سلسلة سبب. - تحقق من القرص: شغّل
du -shعلى مجموعة الـ worktrees، واحذف عمليات تثبيت الاعتماديات المكررة من الأشجار الميتة. - إن كنت تفعل هذا أكثر من مرة في اليوم، فتوقف عن كتابة سكربتات التنظيف وامنح كل worktree مالكًا من المهام بدلًا من ذلك.
يمكنك الاحتفاظ بالأوامر الأربعة وتنفيذها يدويًا، أو تشغيل وكلاء البرمجة الحاليين لديك عبر Sharkly بحيث يُنشأ الـ worktree ويُتتبَّع ويُتقاعد مع المهمة التي ينتمي إليها.



