نشست‌ها و درخواست‌های ادغام پشته‌ای در اپلیکیشن گیت‌هاب کوپایلت

نشست‌ها و درخواست‌های ادغام پشته‌ای در اپلیکیشن گیت‌هاب کوپایلت

می‌خواهم چند لحظه به این اسکرین‌شات از اپلیکیشن گیت‌هاب کوپایلت (GitHub Copilot app) نگاه کنید. تصویر کوچکی است، آیکون‌های زیادی دارد و شگفت‌انگیزترین داستانی را روایت می‌کند که واقعاً من را هیجان‌زده کرده است.

این تصویر مجموعه‌ای از «نشست‌های پشته‌ای» (Stacked sessions) است؛ دسته‌ای از وظایف در یک مخزن (Repository) مشترک که هر نشست بر پایه‌ی نشست قبلی شکل می‌گیرد!

چرا این اسکرین‌شات جادویی است؟

در ادامه بیشتر به این موضوع می‌پردازیم، اما ابتدا چرا این اسکرین‌شات این‌قدر جادویی است؟ برای شروع باید بیش از یک دهه به عقب برگردیم. من مخزن قدیمی برای یک برنامه شخصی دارم. اولین بار آن را سال‌ها پیش (حدود اواخر سال ۲۰۱۴) ساختم و در تمام این سال‌ها همان کاری را انجام داده که می‌خواستم (یک داشبورد شخصی زندگی شامل تقویم‌ها، دستگاه‌های هوشمند خانه و مدیریت وظایف). من هر از گاهی به‌روزرسانی‌هایی انجام می‌دهم، اما مدیریت آن‌ها روزبه‌روز سخت‌تر شده است.

وابستگی‌های (Dependencies) پروژه من بسیار قدیمی شده بودند؛ به‌طوری که خجالت‌آور بود! من از ری‌اکت ۱۵ (React 15 – که سال ۲۰۱۶ منتشر شد)، Less برای پیش‌پردازش CSS و نسخه‌ای از react-bootstrap متعلق به همان زمان استفاده می‌کردم. بله، درست خواندید، بوت‌استرپ! واقعاً قدیمی بود.

مرتب کردن این آشفتگی مطلق قبل از ظهور هوش مصنوعی هفته‌ها از من زمان می‌برد. قبلاً تلاش کرده و تسلیم شده بودم. این بزرگ‌ترین برنامه جهان نیست، اما دقیقاً به اندازه‌ای بزرگ است که بازنویسی آن دردناک باشد و ارزش این همه زحمت را نداشته باشد.

اما اکنون هوش مصنوعی در اختیار ماست؛ بنابراین اپلیکیشن گیت‌هاب کوپایلت را اجرا کردم، مخزن را افزودم و کار را شروع کردم.

گام اول: آیا امکان بازنویسی یک‌باره وجود داشت؟

خیر! اما تلاشم را کردم. این دستورالعملی (Prompt) است که در حالت برنامه‌ریزی (Plan mode) استفاده کردم:

blockquote>من می‌خواهم بخش فرانت‌اند (Frontend) این پروژه را مدرن‌سازی کنم. اکثر این کدها را بیش از ۱۰ سال پیش نوشتم و باید تا حد زیادی پاک‌سازی شوند. فکر می‌کنم کار را یا با Tailwind یا با CSS خالص شروع کنیم (لطفاً همه چیز را بررسی کن تا تصمیم بگیرم)، تمام Less و موارد مشابه را حذف کنیم و همه چیز را از نظر دسترسی‌پذیری (Accessibility) و واکنش‌گرایی (Responsiveness) بهینه‌سازی کنیم. در حال حاضر واقعاً می‌خواهم روی استایل‌ها تمرکز کنم و سپس به‌آرامی اما با اطمینان، قابلیت‌های React را سازمان‌دهی و یکپارچه کنم. شاید ارزش داشته باشد وابستگی‌ها را هم به‌روز کنیم. بیا قبل از شروع کار، یک برنامه برای این کار طراحی کنیم.

۱. هیچ‌چیز مقدس نیست، اگر مجبور شویم برخی بخش‌ها را از نو شروع کنیم مشکلی ندارد.
۲. لینک‌ها باید هنگام قرار گرفتن نشانگر (Hover) یا فوکوس (Focus)، تغییر رنگ دهند و خط زیرین داشته باشند.
۳. فیلدهای ورودی (Input boxes) به طور کلی باید شعاع حاشیه (Border radius) کوچک‌تری داشته باشند و لیبل‌های آن‌ها تمیزتر باشد.
۴. باید پیچش مناسب متن (Wrapping) و حداکثر عرض (Max-width) برای کانتینرها وجود داشته باشد تا فیلد ورودی تمام عرض یک مانیتور عریض را نگیرد.

من این دستور را به Claude Opus 4.8 دادم، یک بررسی Rubber Duck از GPT-5.5 گرفتم و مجبور شدم برای تصمیم‌گیری رفت‌وبرگشت‌های زیادی انجام دهم. وقتی به نتیجه رضایت‌بخشی رسیدم، دکمه شروع را زدم تا اپلیکیشن کار روی پروژه را آغاز کند و ببینم آیا جواب می‌دهد یا خیر! … اما جواب نداد و تقصیر خود من بود.

گام دوم: متوجه شدم قبلاً این کار را امتحان کرده بودم

یادتان هست گفتم «قبلاً تلاش کرده و تسلیم شده بودم»؟ معلوم شد که من در واقع یک شاخه توسعه (devbranch) قدیمی داشتم که در آن برخی بخش‌ها را به‌روز کرده بودم و متوجه مشکلات ناسازگاری نشده بودم.

اما این اتفاق خوبی بود! وقتی نسخه جدید این نشست را اجرا کردم، متوجه شدم که از شاخه اصلی (main) انشعاب گرفته‌ام، اما نسخه در حال اجرای فعلی من از همان نسخه نیمه‌کاره در شاخه dev استفاده می‌کرد. بنابراین برخی ویژگی‌های مورد نیازم باید در این تغییرات گنجانده می‌شدند. اما تغییرات به قدری بزرگ بودند که برای حفظ آرامش ذهنی مجبور شدم آن‌ها را روی devbranch اعمال کنم نه اینکه تغییرات dev را وارد main کنم.

پیش از هوش مصنوعی… خدای من، این اتفاق کلافه‌کننده بود! اینجا هم کلافه شده بودم، چون زمان و توکن‌های زیادی صرف کرده بودم. اما توانستم تنها با یک درخواست ساده، مسیر (و نشست‌ها) را تغییر دهم که بسیار جالب‌تر از حد انتظارم بود.

همه چیز هدر نرفت! کوپایلت یک نشست جدید برای من ایجاد کرد، درخواست ادغامی (Pull request) که امتحان کرده بودم را بست و تصمیمات استایل من را به تغییراتی که روی شاخه dev اعمال می‌کرد، منتقل کرد.

گام سوم: یافته‌ها پس از تست

هوف! خب، حالا یک شاخه خوب و یک Pull request داشتم که نسبتاً از آن راضی بودم. اما هنگام تست، متوجه هشدارهای قدیمی در کنسول شدم.

با دیدن ارجاعات قدیمی به findDOMNode و componentWillReceiveProps ترس تمام وجودم را گرفت؛ توابعی که سال‌ها بود دست نزده بودم. این ارجاعات در کدبیس من نبودند، بلکه در react-bootstrap بودند. دوباره حالت Plan mode را باز کردم تا ببینم آیا ارتقا جواب می‌دهد یا باید کلاً کتابخانه را حذف کنم:

blockquote>آیا فکر می‌کنی باید react-bootstrap را به طور کامل حذف کنیم (و با یک جایگزین مدرن جایگزین کنیم) یا فقط مؤلفه‌های (Components) موجود را ارتقا/مهاجرت دهیم؟

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

گام چهارم: قرار دادن یک نشست روی نشست دیگر (Stacking)

باید مطمئن می‌شدم تغییراتم نسبت به کارهای قبلی امن هستند، اما جایگزینی react-bootstrap فراتر از محدوده (Scope creep) کار فعلی‌ام به نظر می‌رسید.

در کارهای مهندسی مبتنی بر ایجنت (Agentic engineering) فهمیده‌ام که جلوگیری از گسترش محدوده کار سخت است. چون مجبور نیستم خودم کد بنویسم، وسوسه‌انگیز است که یک Pull request ۱۰,۰۰۰ خطی بسازم! که در واقع شکل جدیدی از اتلاف وقت است.

بنابراین به جای ساخت یک PR غول‌پیکر، آن را به یک نشست جدید تقسیم کردم و پرامپت دادم:

blockquote>بیا برای کار موجود یک Pull request بسازیم و سپس یک نشست جدید برای جایگزینی react-bootstrap شروع کنیم که از این کار موجود انشعاب بگیرد و یک Pull request مجزا باشد تا بعد از این یکی در dev ادغام (Merge) شود.

این همان بخشی بود که آن‌قدر جادویی به نظر می‌رسید که من را واداشت این پست را بنویسم. اپلیکیشن گیت‌هاب کوپایلت:

  • برای تمام تغییرات فعلی من از شاخه dev یک Pull request ساخت.
  • یک «نشست پشته‌ای» (Stacked session) برای حذف react-bootstrap ساخت (با دریافت کانتکست قبلی، نشستی برای اجرا بعد از نشست موجود ایجاد کرد، برنامه‌ای ساخت، تأیید مرا گرفت و اجرا شد).
  • یک Pull request پشته‌ای به دنبال کار قبلی من ایجاد کرد.

این فوق‌العاده بود! نشست‌های پشته‌ای و Pull requestهای پشته‌ای؟ آیا این آینده است؟ بله!

اگر مفهوم نام آن را متوجه نمی‌شوید: پشته (Stack) مجموعه‌ای از Pull requestها در یک مخزن است که هر PR شاخه مربوط به PR زیرین خود را هدف قرار می‌دهد و یک زنجیره مرتب می‌سازد که در نهایت به شاخه اصلی (main) می‌رسد.

در مورد من، نه تنها نشست‌ها پشت سر هم بودند، بلکه تغییرات آن‌ها نیز همین‌طور بود!

گام پنجم: موفقیت نهایی با Pull requestهای پشته‌ای

می‌دانم هیجانم کمی شوخ‌طبعانه است، اما خوشحالی‌ام واقعی است. سهولت در ارائه این تغییرات پس از مدت‌ها بی‌توجهی به کدبیس قدیمی‌ام، تجربه‌ای دلپذیر بود.

بیایید دوباره به اسکرین‌شات اول نگاه کنیم؛ شما را راهنمایی می‌کنم:

  • در بالا، مخزنی را می‌بینید که وارد کرده‌ام.
  • عبارت «Frontend modernization» نام نشست اولیه است.
  • لایه بعدی درون آن، اولین تلاش برای Pull request است که نهایتاً ارسال نکردیم (به همین دلیل آیکون قرمز دارد).
  • لایه بعدی در همان سطح، جایی است که یک Pull request کارآمد برای devbranch گرفتیم.
  • نشست توکار (Nested) زیر آن، پیش‌نویس (Draft) PR در حال پیشرفت با تغییرات react-bootstrap است.

توسعه نرم‌افزار هرگز هموار نبوده است. اما این پروژه با این ابزارهای مدرن بسیار آسان‌تر شد.

اگر به دنبال مدرن‌سازی کدبیس خود هستید، این قابلیت را امتحان کنید!

پشته‌های Pull request را در هر کجایی که کد ارسال می‌کنید در گیت‌هاب و نشست‌های پشته‌ای را در اپلیکیشن GitHub Copilot بررسی کنید.