پرش به محتوای اصلی
پرش به محتوای مقاله

۶ تلهٔ Git Worktree که باعث شکست عامل‌های کدنویس می‌شود

·۳۱ شهریور ۱۴۰۵۷ دقیقه مطالعه۳ بازدید
راهنما
درختان کاری Git برای جداسازی عامل: چه چیزی خراب شد، همراه کد
درختان کاری Git برای جداسازی عامل: چه چیزی خراب شد، همراه کد
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

شناسایی ۶ نقطه شکست خاص در ترکیب Git Worktrees و AI Agents که پیش از این در مستندات استاندارد گیت یا راهنمای عامل‌ها ذکر نشده بود؛ به‌ویژه تداخل بین مالکیت فایل‌های root و دستورات حذف گیت.

تصور کنید یک عامل هوش مصنوعی در حال مدیریت ده‌ها شاخه کد در محیط‌های مجزا است، اما ناگهان دیسک سرور شما بدون دلیل پر می‌شود. اگر از Git worktrees برای ایزوله‌سازی تسک‌های عامل‌های خود استفاده می‌کنید، احتمالاً با «فایل‌های شبح» روبرو هستید که ابزارهای استاندارد گیت قادر به شناسایی آن‌ها نیستند. این چالش اصلی سازنده VADD است؛ یک داشبورد محلی که محیط‌های Claude Code و Codex را مدیریت می‌کند. او شش نقطه شکست بحرانی را شناسایی کرده است که زمانی رخ می‌دهند که عامل‌های هوش مصنوعی خودشان مدیریت چک‌اوت‌ها (checkouts) را بر عهده می‌گیرند.

در ساختار VADD، هر هدف (Objective) در یک worktree مجزا در مسیر ~/.vadd/worktrees/<projectId>/<objectiveId> اجرا می‌شود. اکثر توسعه‌دهندگان از worktreeها استفاده می‌کنند تا به هر تسک AI یک شاخه اختصاصی بدهند بدون اینکه چک‌اوت اصلی را به هم بریزند. این یک راهکار بومی و ارزان است که در ظاهر بی‌نقص به نظر می‌رسد، اما وقتی اتوماتیک می‌شود، مشکلاتی ظاهر می‌گردد. این رویکرد در واقع پاسخی به چالش‌های تداخل در کدنویسی AI است که در روش‌های سنتی مدیریت شاخه‌ها دیده می‌شد. مسئله این است که «موفقیت در سطح گیت» و «موفقیت در سطح سیستم فایل» دو حقیقت متفاوت هستند.

برای درک بهتر، پروژه‌ای با فریم‌ورک Laravel را تصور کنید. عامل یک نصب کانتینری را اجرا می‌کند که فایل‌ها را با دسترسی root می‌نویسد. وقتی عامل سعی می‌کند worktree را حذف کند، گیت لینک مدیریتی را حذف می‌کند اما در حذف فایل‌های متعلق به root شکست می‌خورد. سیستم گزارش موفقیت می‌دهد، اما دیسک همچنان با دایرکتوری‌های «شبح» پر می‌شود.

نشت دایرکتوری‌های شبح

طبق مستندات VADD، دستور worktree remove --force ابتدا لینک .git را حذف می‌کند. اگر حذف بازگشتی (recursive delete) متعاقب آن شکست بخورد — که اغلب به دلیل وجود پوشه‌های vendor/ یا node_modules/ با مالکیت root است — گیت پیش از آنکه متوجه شکست شود، وجود آن worktree را فراموش کرده است. این رفتار مشابه برخی موانع حذف خودکار کدها در Claude Code است که به دلیل قفل‌های سیستمی رخ می‌دهد.

در یک مورد واقعی، یک اجرای پاک‌سازی گزارش موفقیت ۲۶ مورد از ۲۶ مورد را نشان می‌داد، اما ۱.۷ گیگابایت داده در پنج دایرکتوری باقی مانده بود. دلیل این اتفاق این بود که کاربر نمی‌توانست فایل‌هایی را در دایرکتوری حذف کند که مالک آن‌ها نبود (به طور مشخص backend/vendor که با مالکیت root:root نوشته شده بود).

  • دستور git worktree prune این نشت‌ها را پیدا نمی‌کند چون حذف شدن فایل لینک .git دقیقاً همان چیزی است که باعث می‌شود گیت یک worktree را از ثبت خود خارج کند.
  • دستور git worktree list نمی‌تواند این دایرکتوری‌ها را نشان دهد چون گیت دیگر نمی‌داند آن‌ها وجود دارند.
  • تنها راه حل این است که به صورت دستی دایرکتوری ریشه worktreeها را readdir کنید و هر پوشه‌ای را که توسط یک ردیف دیتابیس یا ورودی گیت ادعا نشده است، گزارش کنید.

برای جلوگیری از این وضعیت، اتوماسیون باید هم رجیستری گیت و هم سیستم فایل را بررسی کند:
۱. مسیر worktree را استخراج کند.
۲. بررسی کند که آیا listWorktrees هنوز هدف مورد نظر را شامل می‌شود یا خیر.
۳. از existsSync استفاده کند تا تایید کند دایرکتوری واقعاً از روی دیسک حذف شده است.

جدا کردن محیط عامل‌ها با Git worktrees: مشکلات پیش‌آمده و کد رفع آن‌ها

شکاف‌های محیطی و وابستگی‌ها

یک worktree تازه، کاملاً خالی از فایل‌های ردیابی‌نشده (untracked) است. عاملی که سعی می‌کند یک گردش کار «ابتدا-تست» (test-first) را اجرا کند، بلافاصله شکست می‌خورد؛ زیرا فایل‌های .env، پوشه node_modules و دایرکتوری vendor را ندارد و فقط به فایل‌های ردیابی‌شده دسترسی دارد.

استفاده از Symlink برای node_modules ریشه در ساختارهای پیچیده مثل pnpm workspaces ناکافی است. از آنجایی که pnpm مسیرها را از طریق node_modules هر پکیج حل می‌کند، یک symlink ساده همچنان می‌تواند منجر به خطاهایی مانند Cannot find package 'zod' شود.

مکانیزم‌های راه‌اندازی

راه حل، تعریف یک مرحله Setup برای هر مخزن در فایل .vadd/config.json است که دقیقاً یک بار هنگام ایجاد worktree اجرا شود. این مرحله باید پیش از اولین تسک تاییدیه اجرا شود، زیرا عامل‌ها نیاز دارند بلافاصله تست‌ها را اجرا کنند.

مثال از پیکربندی:

{
  "verify": {
    "setup": [{ "id": "deps", "run": "pnpm install --frozen-lockfile" }],
    "commands": [{ "id": "test", "run": "pnpm test", "required": true }]
  }
}

اگر این Setup شکست بخورد، هدف (Objective) باید در وضعیت setup_failed متوقف شود و لاگ‌ها به عنوان مدرک نگه داشته شوند، به جای اینکه اجازه دهیم عامل در worktree‌ای که قابلیت بیلد شدن ندارد، دست و پا بزند.

توهم لینک‌های سخت (Hard-Link)

برخی توسعه‌دهندگان برای صرفه‌جویی در زمان و فضای دیسک در دایرکتوری‌های حجیم vendor/ در PHP، از cp -al (کپی لینک سخت) استفاده می‌کنند. با این حال، در اکثر توزیع‌های لینوکس، تنظیم fs.protected_hardlinks=1 به صورت پیش‌فرض فعال است. این تنظیم کرنل از ایجاد لینک سخت برای فایلی که کاربر مالک آن نیست، جلوگیری می‌کند.

نکته حیاتی این است که cp -al وقتی این اتفاق می‌افتد، خطای شدیدی نمی‌دهد. در یک مورد، ۱۸۰۰ فایل متعلق به root بی‌صدا نادیده گرفته شدند. worktree کامل به نظر می‌رسید، اما اپلیکیشن خراب بود.

برای رفع این مشکل، یک رویکرد دو مرحله‌ای لازم است:

  • اول، اجرای cp -al "$MAIN/backend/vendor" "$WT/backend/vendor".
  • دوم، اجرای cp -a --no-clobber "$MAIN/backend/vendor/." "$WT/backend/vendor/" برای پر کردن شکاف‌های باقی‌مانده.

آلودگی محیطی داکر

بسیاری از پروژه‌ها چک‌اوت اصلی را به صورت bind-mount به کانتینرهای داکر متصل می‌کنند. وقتی یک عامل دستور docker compose exec app php artisan test را از داخل یک worktree اجرا می‌کند، در واقع در حال تست کردن کدهای چک‌اوت اصلی است، نه تغییراتی که همین حالا نوشته است.

هیچ راه حل بومی در گیت برای این مشکل وجود ندارد. راه حل این است که از یک مرحله Setup استفاده شود که یک فایل .env کپی شده ایجاد کند. این فایل باید تست‌رنر را به پورت‌های Host-exposed کانتینرها (برای دیتابیس و کش) متصل کند. بدین ترتیب تست‌ها روی Host و داخل worktree اجرا می‌شوند و داکر فقط سرویس‌های پشتیبان را فراهم می‌کند.

نشت کامیت‌های Squash

اسکریپت‌های Setup که فایل‌های ردیابی‌شده (مانند backend/.env.testing) را برای تغییر پورت‌ها بازنویسی می‌کنند، ریسک جدیدی ایجاد می‌کنند. از آنجایی که عامل‌ها اغلب برای ایجاد نقاط بازگشت (checkpoints) از git add -A استفاده می‌کنند، این تغییرات محیطی محلی به هر کامیت نشت می‌کنند.

اگر این مورد مدیریت نشود، کامیت نهایی (Squash commit) این تغییرات را به شاخه می‌برد و تنظیمات داکر را برای تمام توسعه‌دهندگان دیگر تیم خراب می‌کند.

سیاست‌های سخت‌گیرانه (Enforcement Policy)

برای جلوگیری از این اتفاق، سخت‌گیری باید در زمان Squash رخ دهد، نه در زمان Setup. این فرآیند مراحل زیر را دنبال می‌کند:
۱. اجرای git add -A
۲. اجرای git reset --soft "$BASE_SHA"
۳. شناسایی مسیرهای Stage شده که با یک glob محافظت‌شده مطابقت دارند از طریق git diff --cached --name-only -z.
۴. اجرای git reset -q "$BASE_SHA" -- "${excluded[@]}" برای بازگرداندن فایل‌های محافظت‌شده به حالت پایه.

هر فایل محافظت‌شده‌ای که توسط عامل ایجاد شده و در حالت پایه وجود نداشته است، کاملاً از index حذف می‌شود. سپس VADD رویدادی را صادر می‌کند که نام تمام مسیرهای حذف شده را ذکر می‌کند تا در مورد آنچه کامیت شده است، به کاربر «دروغ» نگوید.

تداخل‌های موازی

ایزولاسیون زمانی شکست می‌خورد که اسکیمای دیتابیس‌ها منحصربه‌فرد نباشند. در VADD، یک جدول plan-task در ابتدا از شماره ترتیبی تسک ('0', '1', '2') به عنوان کلید اصلی جهانی استفاده می‌کرد. در حالی که این شماره در یک هدف (Objective) منحصربه‌فرد است، اما در چندین هدف موازی نیست.

وقتی هدف دوم به مرحله برنامه‌ریزی رسید، با خطای UNIQUE مواجه شد. چون این خطا بلعیده شده بود، کاربر یک پلان بدون ردیف می‌دید. این باگ پنهان ماند زیرا تست‌ها هر بار فقط یک هدف را اجرا می‌کردند. درس این است: اگر می‌خواهید کارهای موازی را ایزوله کنید، تست‌های شما هم باید واقعاً به صورت موازی اجرا شوند. برای بهینه‌سازی این لایه‌ها، برخی ابزارها از زبان‌های سیستمی استفاده می‌کنند؛ برای مثال استفاده از Rust در ابزارهای گیت می‌تواند مدیریت موازی عامل‌ها را به شکل بسیار ساده‌تری پیاده‌سازی کند.

این تغییر در رویکرد به این معناست که توسعه‌دهندگان دیگر نمی‌توانند به وضعیت داخلی گیت به عنوان منبع حقیقت برای سلامت سیستم فایل اعتماد کنند. بار تایید صحت از ابزار به لایه اتوماسیون (wrapper) منتقل می‌شود.

برای کسانی که گردش کارهای عامل‌محور (agentic workflows) می‌سازند، درس روشن است: فرض کنید سیستم فایل به شما دروغ می‌گوید. هر حذف باید روی دیسک تایید شود و هر Setup باید در صورت شکست، به عنوان یک توقف سخت (hard stop) در نظر گرفته شود.

برای اجتناب از این تله‌ها، با بازبینی bind-mountها و ساختارهای دسترسی (permissions) پروژه خود شروع کنید. پیاده‌سازی کامل این اصلاحات در سورس کد سرور VADD در مسیر packages/server/src/git/ و لیست کامل تله‌ها در فایل CLAUDE.md موجود است.

گام بعدی شما

  • ساختار bind-mountها و دسترسی‌های فایل (Permissions) پروژه خود را بازبینی کنید.
  • برای هر محیط ایزوله، یک مرحله Setup اجباری تعریف کنید که پیش از اجرای هر تسک، صحت وابستگی‌ها را تایید کند.
  • در اتوماسیون‌های گیت، هرگز به خروجی دستورات اکتفا نکنید و وضعیت فیزیکی دیسک را با existsSync چک کنید.

اما داستان سخت‌افزاری این تحول حتی شگفت‌انگیزتر است — به تحلیل ما درباره‌ی تراشه‌های Blackwell مراجعه کنید.

چرا این موضوع مهم است؟

این یافته‌ها بر اساس تجربه عملی در مقیاس بالا است و نشان می‌دهد که خطاهای زیرساختی کوچک می‌توانند منجر به تخریب مخازن کد در محیط‌های عامل‌محور شوند. اعتماد به وضعیت داخلی گیت بدون تایید سیستم‌فایل، ریسک نشت داده و خرابی محیط توسعه را افزایش می‌دهد.

تأثیر برای ایران

برای برنامه‌نویسان ایرانی که در حال ساخت ابزارهای اتوماسیون کدنویسی با APIهای خارجی هستند، این نکات در طراحی زیرساخت سرور برای جلوگیری از پر شدن دیسک و تداخل محیط‌ها حیاتی است.

·نگاه ما
تحریریه دات‌هوش

این گزارش نشان می‌دهد که در عصر عامل‌های هوش مصنوعی، لایه انتزاعی ابزارهایی مثل گیت دیگر برای تضمین صحت محیط کافی نیست. ما با جابجایی مسئولیت تایید از «ابزار» به «پوشش اتوماسیون» (Automation Wrapper) روبرو هستیم. در واقع، توسعه‌دهندگان باید فرض کنند سیستم فایل در برابر عامل‌ها «دروغ می‌گوید» و هر عملیات حذفی یا کپی را به صورت فیزیکی بازبینی کنند.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.