چه تفاوتی بین Clone کردن یک Repository با Fork کردن آن وجود دارد؟

چه تفاوتی بین Clone کردن یک Repository با Fork کردن آن وجود دارد؟

گیت چیست؟

همان طور که می دانید گیت، محبوب ترین سورس کنترلر یا Version Control System دنیای توسعه‌ی نرم‌­افزار است. گیت تغییراتی را که روی سورس کد یک پروژه ی نرم‌­افزاری اعمال می‌­شود، روی یک دیتابیس که Repository یا مخزن کد نام دارد، نگه داری می‌کند. با این کار می‌توانید تاریخچه‌ی تغییرات پروژه را داشته باشید و بدانید چه کسی، چه زمانی، بابت چه کاری، کجای سورس کد را تغییر داده است و به این ترتیب اگر مشکلی در نرم افزار ایجاد شد، می‌توانید تغییرات را حذف کرده و آن را به گذشته برگردانید.

سورس کنترلرها در دو دسته متمرکز یا Centralized و توزیع شده یا Distributed قرار می گیرند. گیت یک سورس کنترلر توزیع شده است. در سورس کنترلرهای توزیع شده هر یک از افراد گروه، روی سیستم خودشان، نسخه‌ای از پروژه را همراه با تاریخچه تغییرات آن نگه می‌دارند و همچنین می‌توانند این تغییرات را با یکدیگر به اشتراک بگذارند و با هم هماهنگ یا sync شوند. در واقع می توان از گیت به صورت تک نفره یا گروهی استفاده کرد. (برای آشنایی بیشتر با سیستم کنترل نسخه‌ی گیت، می‌توانید به دوره‌ی آموزش گیت سکان آکادمی مراجعه کنید.)

گیت چطور کار می کند؟

با یک سناریو ساده شروع می‌کنیم. فرض کنید یک نفر می‌خواهد روی کامپیوتر دسکتابش در منزل، یک محصول نرم‌افزاری را توسعه دهد. پس یک ریپازیتوری ایجاد می‌کند و تغییرات خودش را روی آن commit یا ثبت می‌کند. سپس تصمیم می‌گیرد کارش را در محل کار و روی لپ تابش ادامه دهد. گیت چون یک سیستمی براساس پوشه دارد، پس کل پوشه‌ای که روی کامپیوتر دسکتابش دارد را zip کرده و با یکی از روش های انتقال مانند انتقال از طریق اینترنت، فایل zip شده را به محل کارش برده و آن را unzip  کرده و در آن جا ادامه کار خود را پیش می‌برد.

مشکلی که این روش دارد این است که پروژه در دو جای مختلف توسعه داده شده و با هم هماهنگی ندارند. برای مثال ممکن است روی نسخه ای که در حال حاضر روی لپ تاپش دارد، تغییرات زیادی اعمال کرده باشد که این تغییرات بر روی کامپیوتر دسکتابش وجود نداشته باشد. پس هر بار مجبور است، کل پوشه (یا فقط تغییرات انجام شده) را به صورت دستی به جای دیگر منتقل کند تا با هم هماهنگ شوند. همان طور که قبلا گفته شد، گیت یک سورس کنترلر توزیع شده است پس می توان از این ویژگی گیت برای حل این مشکل استفاده کرد. 

راه حل گیت به این صورت است که در مکانی مشترک که همه ی اعضای گروه به آن دسترسی دارند، یک کپی از ریپازیتوری اصلی گرفته و روی آن قرار دهیم و هر یک از اعضای گروه تغییرات خودشان را به آن جا منتقل کنند تا در معرض دید همه قرار بگیرد. به این ریپازیتوری Remote Repository گفته می‌شود. برای مثال شکل زیر را در نظر بگیرید. فرض کنید برنامه ما روی کامپیوتر دسکتاب تا نسخه 2 پیش رفته ولی روی لپ تاپ در حال کار روی نسخه 4 آن هستیم. در این حالت تغییرات را تا نسخه 4، از روی لپ تاپ به این ریپازیتوری مشترک انتقال می‌دهیم تا کامپیوتر دسکتاپ این تغییرات را گرفته و در نتیجه از نظر تغییرات با هم هماهنگ می‌شوند. 

سوالی که ممکن است پیش بیاید این است که Remote Repository را کجاها می شود قرار داد تا در دسترس استفاده کنندگانش باشد؟ گیت در این موارد بسیار منعطف عمل می‌کند به این صورت که این امکان را در اختیار ما قرار می‌دهد تا آن را در جاهای مختلفی مانند یک درایو مشترک یا یک سرور مشترک قرار دهیم. فضاهای ابری هم جای مناسبی برای نگه داری آن هستند. یکی از مشهورترین شان GitHub است یا شرکت مایروسافت هم فضای ابری Azure DevOps را برای این مورد پیشنهاد می‌دهد. در این مثال می خواهیم آن را در گیت‌هاب قرار دهیم. 

گیت‌‎هاب چیست؟

گیت‌هاب محبوب‌ترین پلتفرم نگه داری ریپازیتوری‌های گیت است. در گیت‌هاب ریپازیتوری‌ها را می توان به دو صورت private (خصوصی) و public (عمومی) ساخت. بیایید به خصوصیات هر یک بپردازیم. ریپازیتوری‌های خصوصی فقط برای ایجاد‌کننده‌ی آن و افرادی که به آن ریپازیتوری به عنوان مشارکت کننده یا collaborator اضافه شده‌اند، قابل دسترسی هستند و برای سایرین، که به آن اضافه نشده اند، قابل رویت نیستند. هم چنین تنها افرادی که ریپازیتوری های خصوصی را می‌بینند می‌توانند کارهایی از قبیل Commit کردن تغییرات یا ساختن شاخه (branch) و ... را روی آن انجام دهند.

در مقابل، ریپازیتوری‌های عمومی را همه می‌توانند ببینند و به فایل های آن دسترسی داشته باشند و تاریخچه Commit های آن را مرور کنند اما همانند ریپازیتوری‌های خصوصی، تنها ایجاد کننده آن و کسانی که به عنوان مشارکت‌کننده به آن اضافه شده‌اند، می‌توانند ریپازیتوری را تغییر دهند. اما این محدودیت به این معنی نیست که نمی توان در توسعه و رفع مشکلات یک ریپازیتوری عمومی مشارکت داشت. راه‌هایی برای این کار وجود دارد که در ادامه به بررسی آن ها خواهیم پرداخت.

به طور کلی برای گرفتن کدهای یک ریپازیتوری دو راه وجود دارد:

  1. Clone گرفتن
  2. Fork گرفتن

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

فرآیند Centralized Workflow

فرض کنید رضا و احمد می‌خواهند نرم افزاری را با هم توسعه دهند. رضا ابتدا یک ریپازیتوری خصوصی بر روی گیت‌هاب می سازد و احمد را به عنوان مشارکت کننده به این ریپازیتوری اضافه می‌کند. سپس هر دو از این ریپازیتوری یک Clone روی سیستم خودشان می‌گیرند. پس در این مرحله هر دو یک ریپازیتوری محلی روی سیستمشان دارند. رضا شروع به کدنویسی می‌کند و روی ریپازیتوری محلی خودش، چندین Commit انجام می‌دهد. در این مرحله رضا باید کارهایی که تا اینجا کرده است را به دست احمد برساند. برای این کار رضا باید Commit های خودش را روی ریپازیتوری مشترکی که روی گیت‌هاب وجود دارد، push کند.

در این مرحله ریپازیتوری مشترک که ریپازیتوری مرکزی هم نامیده باشد با کارهایی که رضا تا این مرحله انجام داده است، هماهنگ و به روز شده است. احمد برای این که تغییرات رضا را داشته باشد، باید Commit هایی که تا این جا روی ریپازیتوری مرکزی قرار گرفته شده و او آن ها را ندارد، pull کند. این push و pull کردن ها ادامه خواهد داشت تا هر دو با هم هماهنگ و به روز شوند. این فرآیندی است که در تیم کوچک که در حال کار کردن با ریپازیتوری خصوصی هستند اتفاق می‌افتد که به این فرآیند Centralized Workflow گفته می شود. در شکل زیر این فرآیند را ملاحظه می‌فرمایید.

فرآیند Integration-Manager

در پروژه‌های open source داستان کمی متفاوت است و از یک workflow دیگری به نام Integration-Manager، استفاده می شود. در یک پروژه اپن سورس، یک یا چند عضو اصلی یا maintainer وجود دارند و کسانی هم هستند که تمایل دارند در این پروژه مشارکت داشته باشند اما فقط اعضای اصلی این پروژه دسترسی push روی این ریپازیتوری را دارند و مشارکت کننده ها دسترسی push را ندارند. پس این مشارکت به چه نحوی انجام می گیرد؟

مشارکت کننده ها باید ابتدا از ریپازیتوری عمومی یک Fork بگیرند، در نتیجه یک کپی از این ریپازیتوری عمومی گرفته شده و روی گیت‌هاب ساخته می‌شود و این ریپازیتوری هم عمومی خواهد بود و در دسترس عموم قرار خواهد گرفت. سپس باید یک Clone از این ریپازیتوری Fork شده گرفته شود تا یک کپی از آن روی کامپیوتر محلی مشارکت کننده ایجاد شود. سپس مشارکت کننده تغییرات خودش را روی ریپازیتوری محلی اعمال می‌کند و هر زمان نیاز شد، تغییرات را به ریپازیتوری Fork شده push می‌کند. به این نکته دقت داشته باشید که برای مشارکت‌کننده دسترسی push روی ریپازیتوری Fork شده وجود دارد. سپس باید به روشی، این تغییرات به ریپازیتوری اصلی منتقل شود. 

روال کار به این صورت است که در گیت‌هاب امکانی وجود دارد به نام pull request که مشارکت کننده می‌تواند یک درخواست pull request را به یکی از اعضای اصلی یا maintainerها بفرستد، به این معنی که یک نفر می‌خواهد در این پروژه open source مشارکت کرده و تغییراتش را به ریپازیتوری اصلی منتقل کند. همان‌طور که از اسم pull request معلوم است، عضو اصلی یا maintainer با دریافت این درخواست باید ریپازیتوری Fork شده را pull کرده و تغییرات انجام شده روی آن را بررسی کند و اگر مورد تایید بود، تغییرات انجام شده توسط مشارکت کننده را به ریپازیتوری اصلی push کند.

باز به این نکته توجه بفرمایید چون ریپازیتوری Fork شده به صورت عمومی در آمده است، maintainer به آن دسترسی خواهد داشت و می تواند کد های آن را pull کند و هم چنین تنها maintainerها دسترسی push کردن روی ریپازیتوری اصلی را دارند پس باید مشارکت‌کننده‌ها برای اعمال تغییرات خود روی ریپازیتوری اصلی، pull request ارسال کنند. در شکل زیر نمایی از این فرآیند را مشاهده می‌فرمایید.

 

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

(برای آشنایی بیشتر با سیستم کنترل نسخه‌ی گیت، می‌توانید به دوره‌ی آموزش گیت سکان آکادمی مراجعه کنید.)

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


online-support-icon