با اجازه من مطلب رو کپی میکنم !
کپی رایتش هم که بالا هست !
مقایسهی Git با Subversion
امروز بعد از مدتها یادم اومدم وبلاگ هم دارم. گفتم یه چیزی بنویسم تا اینجا از این وضع در بیاد.
توی شرکت داریم پروژهها رو از svn به git سوئیچ میکنیم. دیدم بهانهی خوبیه تا دربارهی git بنویسم.
از اونجایی که اکثر برنامهنویسها با svn آشنایی دارن به جای نوشتن در مورد git به مقایسهی git با svn میپردازم. اینجوری راحتتر میتونید تصمیم بگیرید که آیا نیازی به تغییر سیستم کنترل سورس فعلیتون به git هست یا نه.
این روزها سیستمهای توزیع شدهی کنترل سورس (Distributed Version Control) کم کم دارن جای سیستمهای کنترل سورس سنتی متمرکز (Centralized) مثل svn رو میگیرن. از جمله git یکی از این سیستمهای کنترل سورس توزیع شده است که محبوبیت زیادی پیدا کرده.
قسمت عمدهای از تفاوتهای git و svn برمیگرده به تفاوت مدل توزیع شده و مدل متمرکز، برای همین ابتدا این دو مدل رو توضیح میدم.
مدل متمرکز
در این مدل یک مخزن (Repository) داریم که روی یک سرور قرار میگیره که شامل کل پروژه با تاریخچهاش است. هر کس که میخواد روی پروژه کار کنه یک کپی از آخرین نسخهی پروژه رو از سرور دریافت میکنه (همون working copy)، تغییراتی میده و بعد تغییراتش رو به سرور ارسال (commit) میکنه تا در مخزن قرار بگیره. همچنین میتونه آخرین تغییرات سایرین رو از مخزن دریافت (update) کنه و به این ترتیب هر کس میتونه آخرین نسخهی پروژه رو روی کامپیوتر خودش داشته باشه.
با توجه به لزوم وجود سرور در این مدل به این مدل، مدل کلاینت-سرور هم میگن.
مدل توزیع شده
در این مدل نیازی به وجود سرور برای نگهداری مخزن نیست و هر کس به جای working copy یک مخزن از پروژه رو داره. که این مخزن میتونه شامل working directory هم باشه.
برای مثال با git وقتی یک نفر یک پروژه رو شروع میکنه یک مخزن روی کامپیوتر خودش ایجاد میکنه و شروع به کار میکنه. حالا نفر دوم میتونه از این مخزن یک کلون (clone) تهیه کنه به عبارت دیگه یک مخزن عین مخزن نفر اول روی کامپیوتر خودش ایجاد کنه و در توسعه پروژه مشارکت کنه. حالا هر یک از این دو نفر هر موقع که خواستند میتونن از مخزن یکدیگر تغییرات یکدیگر را دریافت (fetch) و یا برای دیگری تغییرات خود را ارسال (push) کنند و تغییرات را ادغام (merge) کنند. وقتی نفر سوم میخواد وارد پروژه بشه، از هر یک از دو مخزن نفرات قبل میتونه کلون تهیه کنه و کار رو شروع کنه و میتونه تغییرات خودش رو با هر یک از اونها مبادله کنه. و این روند ادامه پیدا میکنه.
در واقع در این روش مخزن بین تمام مشارکت کنندگان در پروژه توزیع شده، برای همین به این مدل، مدل توزیع شده گفته میشه.
حتما با خودتون فکر میکنید که این روش شاید برای یک گروه سه یا چهار نفره مناسب باشه ولی برای تیم های بزرگتر کارایی نداره چون هماهنگ کردن مخازن کار خیلی مشکلی میشه. در جواب باید گفت گرچه در مدل توزیع شده وجود سرور الزامی نیست ولی محدودیتی برای استفاده از این مدل به صورت کلاینت-سروری وجود نداره. یعنی شما میتونید یک مخزن روی یک سرور بگذارید و به صورت توافقی همهی توسعهدهندهها به جای مبادله تغییرات با یکدیگر، تغییرات را با مخزن روی سرور مبادله کنند. خوب حالا حتما با خودتون میگین این که همون مدل متمرکز شد! عجله نکنید. تا انتهای مطلب رو بخونید بعد قضاوت کنید.
مزایای مدل توزیع شده
عدم نیاز به شبکه
با توجه به اینکه در این روش مخزن روی کامپیوتر شما قرار داره برای انجام خیلی از عملیاتها نیازی به اتصال به شبکه نیست. مثلا commit کردن، log گرفتن، diff گرفتن، و خیلی عملیاتهای دیگه نیازی به ارتباط با شبکه نداره. که باعث کاهش ترافیک شبکه میشه و در عین حال این امکان رو به شما میده که در هنگامی که شبکه قطع است و یا هنگامی که با لپتاپ خود به مسافرتی و یا جایی میروید که دسترسی به شبکه ندارید همچنان به کار خودتون روی پروژه ادامه بدید.
سرعت بیشتر
عدم نیاز به شبکه در انجام اکثر عملیاتها باعث افزایش قابل توجه سرعت در اینگونه عملیاتها میشه.
مشارکت در پروژه بدون نیاز به دسترسی کامیت
با توجه به ماهیت توزیع شده در این مدل برای مشارکت در یک پروژه نیازی به دسترسی کامیت نیست. به این صورت که شما یک clone از یک پروژه تهیه میکنید و تغییراتی را در آن میدهید و روی مخزن خود کامیت میکنید. حالا میتونید از یک نفر که دسترسی کامیت داره بخواهید که کامیتهای شما رو بررسی کنه و اگر صلاح دونست توی مخزن اصلی merge کنه. در نتیجه بدون اینکه شما دسترسی مستقیم کامیت داشته باشید کامیتهای شما با نام خودتان در مخزن اصلی ثبت میشه. این مزیت برای پروژههای بازمتن خیلی مفیده و به گسترش و توسعه پروژه با افزایش مشارکت داوطلبین کمک میکنه. بگذارید یک مثال عینی بزنم. من برای ارسال patch به پروژه cakephp که قبلا از svn استفاده میکردند فایل patch تغییرات رو ضمیمهی تیکت کردم(؟). یکی از برنامه نویسان تغییرات رو بررسی و روی پروژه کامیت کرد(؟). در اینجور مواقع از اونجایی که svn این کامیت رو به نام شخص کامیت کننده ذخیره میکنه نه مولف اصلی، معمولا برای مشخص شدن نویسندهی اصلی توی کامنت مینویسند “applying patch from x” و ضمن اینکه اگر تغییرات زیاد باشه بررسی تغییرات کار سختی میشه. حالا ببینیم git چطور این مشکل رو حل میکنه. بعد از اینکه cakephp به git منتقل شد من یک باگ گزارش دادم(؟) و برای نوشتن testcase برای این باگ یک fork از پروژه گرفتم، testcase رو نوشتم و کامیت کردم(؟) و لینک تغییرات رو به تیکت اضافه کردم. یکی از برنامه نویسان تغییرات رو بررسی و در مخزن اصلی ادغام میکنه(؟). اینجا git این کامیت رو با نام مولف اصلی و تاریخ اصلی تغییرات ذخیره میکنه و در عین حال نام کامیت کننده و تاریخ کامیت رو هم ذخیره میکنه. ضمن اینکه اینجا اگر تغییرات زیاد باشه میشه به کامیتهای مختلف تفکیک بشه که هر کدوم توضیحات خودش رو داره و بررسی این تغییرات کار راحت تری میشه.
کاهش خطر از دست رفتن اطلاعات
در این مدل با توجه به اینکه هر توسعه دهنده یک مخزن از پروژه رو داره در صورت ترکیدن سرور و از دست رفتن کل اطلاعات هیچ مشکلی پیش نمیاد و میتونید مجددا یکی از مخازن موجود رو روی سرور قرار داده و بدون هیچ مشکلی کار رو ادامه بدید.
پشتیبانی از مدلهای کاری(workflow) متعدد
با استفاده از سیستم های توزیع شده تقریبا هر نوع مدل کاری رو میشه پیاده سازی کرد. مثلا شما میتونید مثل سیستم های متمرکز به صورت کلاینت-سرور کار کنید. البته این مبحث خودش یک مقاله جداگانه رو میطلبه. اگر حوصله داشتید برای کسب اطلاعات بیشتر اینجا و اینجا رو مطالعه کنید.
امکان داشتن مخزن خصوصی از یک پروژه
برای مثال شما میتونید یک clone از یک پروژه بگیرید و یکسری تغییرات خصوصی برای خودتون بدید ولی در پروژه اصلی اعمال نکنید. و در عین حال همیشه میتونید آخرین تغییرات پروژه اصلی رو روی مخزن خصوصیتان ادغام کنید.
تمیزتر بودن مخزن اصلی
با توجه به اینکه در این روش کامیتها را روی مخزن محلی خودتان انجام میدهید. در صورت بروز اشتباه در کامیت دیگه اون کامیت رو در مخزن سرور اصلی ادغام نمیکنید. ولی در سیستم هایی مثل svn در صورتی که اشتباها یک فایل cd.iso رو توی مخزن کامیت کنید. حتی بعد از حذفش هم حجم مخزن کاهش پیدا نمیکنه و اون فایل برای همیشه در تاریخچه مخزن باقی میمونه و حجم مخزن به مرور زمان در اثر این اشتباهات افزایش پیدا میکنه و تاریخچهی مخزن شلوغ و کثیف میشه.
معایب مدل توزیع شده
مشکل درک مفاهیم
گفته میشه اکثر افراد در درک مفاهیم سیستمهای توزیع شده مشکل دارند و کمی طول میکشه تا بتونن بهش عادت کنند. البته علت اصلی اینه که اکثرا به سیستمهای متمرکز عادت کردند و همون انتظاراتی رو از سیستمهای توزیع شده دارند که از یک سیستم متمرکز دارند. این باعث میشه مثلا به نظرشون بیاد بعضی از مراحل و عملیاتها اضافه است.
در صورتی که ساختار و نحوه عملکرد سیستمهای توزیع شده رو زیربنایی یاد بگیرید درک مفاهیم اون خیلی برایتان ساده خواهد شد.
مشکل کنترل دسترسی
با توجه به اینکه در مدل توزیع شده کل مخزن در اختیار توسعه دهندگان قرار میگیره هر کس که بتونه به یکی از این مخازن دسترسی داشته باشه به کل پروژه دسترسی پیدا میکنه. ولی در مدل متمرکز میشه مطمئن بود که فقط کسانی به مخزن دسترسی دارند که به مخزن سرور اصلی دسترسی داشته باشند. البته این مسئله در مورد پروژههای بازمتن مشکل به حساب نمیاد.
امروزه سیستمهای کنترل سورس توزیع شدهی متعددی وجود داره که هر کدوم طرفدارهای خاص خودش رو داره از جمله معروفترین اونها Git و Bazaar و Mercurial هستند.
همهی این سیستمها تفاوتهای گفته شده رو نسبت به سیستمهای متمرکز دارند. علاوه بر این، این سیستمها کم و بیش مزایای دیگری هم دارند که در این بین Git از جایگاه بهتری نسبت به بقیه برخوردار است.
مزایای Git
سرعت فوق العاده
یکی از اهداف اولیه طراحی git سرعت بوده. و از این نظر واقعا git موفق بوده.
در کل سیستمهای توزیع شده از سرعت بهتری نسبت به سیستمهای متمرکز برخوردارند. و در بین سیستمهای توزیع شده git بهترین جایگاه رو از نظر سرعت داره. یکی از دلایل سرعت git اینست که با زبان C نوشته شده که نسبت به زبانهای سطح بالا نظیر python سرعت بهتری داره. (Bazaar و Mercurial با python نوشته شدهاند.)
حجم کم
حجم یک working directory به همراه مخزن در git به ندرت از یک working copy در svn بیشتر میشه. برای مثال مخزن Mozilla در svn چیزی حدود 12GB بوده در حالیکه حجم همین مخزن در git حدود 420MB بیشتر نیست. یعنی حدود 30 بار کوچکتر از svn. مخزن پروژه Ruby on Rails در git که شامل کل تاریخچه فایلهاست حدود 13MB بیشتر نیست درحالیکه حجم پروژه (بدون مخزن) 9MB است یعنی حجم کل مخزن فقط یک ونیم برابر حجم پروژه است. و مخزن همین پروژه قبلا در svn حدود 115MB بوده.
حتی در بین سیستمهای توزیع شده هم git از نظر حجم بهترین جایگاه رو داره.
پایداری
معماری داخلی git از سادگی و پایداری فوقالعادهای برخورداره که تقریبا امکان خراب شدن مخزن در اون وجود نداره. ولی تا به حال موارد زیادی از خراب شدن خود به خود مخازن svn مشاهده شده.
راحتی کار با شاخه ها (branch)
یکی از قابلیتهای فوق العادهی git پشتیبانی خیلی خوب از شاخه هاست. در git میتونید برای تست یک ایدهی جدید شاخهی محلی بسازید و در حین کار هر زمان خواستید به شاخه اصلی برگردید و یکسری کامیت انجام دهید و مجددا به شاخه تست برگردید و میتونید هر زمان خواستید شاخه ها رو با هم ادغام کنید و یا حذف کنید. و تمام این عملیاتها بدون نیاز به ارتباط با سرور انجام میشود. و به خاطر معماری فوق العادهی git در مقایسه با سایر سیستمها از سرعت و کارایی فوق العاده ای برخوردار است.
دنبال کردن محتوای فایل به جای نام فایل
git محتوای فایلها را دنبال میکند. یعنی اگر فایلی را بدون استفاده از دستورات git تغییر نام داده، جابهجا و یا کپی کنید git با توجه به این ویژگی، این عملیات را تشخیص داده و ثبت میکند و لذا تاریخچه مربوط به اینگونه فایلها را حفظ میکند.
کامیت با جزئیات بیشتر
در git یک کامیت علاوه بر نام کامیت کننده و تاریخ کامیت شامل نام مولف و تاریخ تغییرات هم هست. برای مثال این قابلیت git باعث میشه که در اعمال patch ها نام مولف اصلی و تاریخ تغییرات حفظ شود.
شلوغ نکردن working directory با پوشههای .git
اگر با svn کار کرده باشید میدانید که svn در تمام پوشههای پروژه یک پوشه به نام .svn ایجاد میکند که باعث بوجود آمدن مشکلات زیادی میشود. مثلا اینکه نمیتوانید شاخهها را کپی کنید و باید از دستورات خود svn استفاده نمایید. و در صورت عدم استفاده از دستورات svn چنانچه تغییراتی در کپی بدهید، بر روی شاخهی اصلی کامیت میشود و یا تغییرات شاخهی اصلی روی کپی شما هم اعمال میشود. این مشکل معمولا برای اکثر برنامه نویسان تازهکار اتفاق میافتد.
اما در git فقط یک شاخه به نام .git در پوشهی اصلی پروژه ایجاد میشود که مانع از به وجود آمدن مشکلاتی نظیر مشکلات فوق میشود.
نمایش میزان پیشرفت عملیات
در اکثر عملیاتهای شبکهای در git مراحل و میزان پیشرفت عملیات نمایش داده میشود و میتوانید بفهمید چه میزان از کار انجام شده و چه مقدار باقی ماده است. اما در svn این امکان وجود ندارد.
تنوع در مجموعه دستورات و امکانات (feature-rich)
درgit مجموعه دستورات متعددی (بالغ بر 140 دستور) وجود دارد که با یادگیری آنها میتوان کارهایی را انجام داد که در سایر سیستمها یا قابل انجام نیست و یا بسیار دشوار است. قابلیتهای منحصر به فردی نظیر stage area و stash و local branching که با یادگیری آنها در روش کارتان تحولاتی ایجاد خواهد شد و دیگر قادر به برگشتن به سایر سیستمها نخواهید بود.
معایب Git
کدهای طولانی SHA1 به جای شمارههای متوالی revision
در واقع این مورد ایراد به حساب نماید و حتی معماری git به گونهای است که از این شناسههای SHA1 به عنوان امضای دیجیتال برای کامیتها و سایر آبجکتهای داخلی گیت استفاده شده که باعث بالا رفتن امنیت و جلوگیری از دستکاری مخازن خواهد شد.
اما معمولا در شروع کار با git اولین چیزی است که، عجیب و غیرعادی به نظر میرسد و اکثر تازهکارها را دچار سردرگمی میکند.
از آنجایی که در معماری توزیع شده کامیتها در یک مکان انجام نمیشود امکان تخصیص شماره های منحصر به فرد و متوالی به کامیتها وجود ندارد. در git از کدهای 40 کاراکتری SHA1 به عنوان شناسهی کامیت استفاده میشود. از آنجایی که به خاطر سپردن این کدها کار دشواری است میتوان فقط از چند کاراکتر اول آن استفاده کرد. و چنانچه این چند کاراکتر در مورد دو شناسه تکراری نباشد git میتواند شناسهی مورد نظر شما را پیدا کند. معمولا از 7 کاراکتر اول استفاده میشود که احتمال تکراری بودن آن در یک پروژه بسیار کم است.
در git راههای مختلفی برای ارجاع به آبجکتهای داخلی(از جمله کامیتها) وجود دارد که به اصلاح به آن ها Treeish گفته میشود. مثلا برای ارجاع به کامیتها میتوان از tag ها و یا میانبرهایی نظیر^ و ~ و @ استفاده کرد.
عدم سازگاری دستورات با سیستمهای سنتی
اکثر دستورات git یا عملکرد کاملا متفاوتی با دستورات هم نام خود در سیستمهای دیگر نظیر svn دارند و یا اینکه اسامی متفاوتی با معادلهای رایج در سیستمهای دیگر دارند. و این باعث میشود برنامه نویسانی که به سیستمهایی نظیر svn عادت کردهاند در ابتدای کار با git دچار سردرگمی شوند. تعدد دستورات git که بالغ بر 140 دستور میشود نیز مزید بر علت است.
امکان checkout جزئی وجود ندارد
در svn میتوانید فقط از یک شاخه از پروژه checkout بگیرید ولی در git این امکان وجود ندارد و باید کل پروژه clone گرفته شود. البته با استفاده از قابلیت submodule در git میتوان قسمتهای مختلف پروژه را در مخازن جداگانه ذخیره کرد و این مخازن را در مخزن اصلی به صورت submodule استفاده کرد. که در این حالت میتوان برای کار کردن روی یکی از این قسمتها به جای clone گرفتن از کل پروژه فقط از submodule مربوطه clone گرفت.
امکان افزودن پوشه خالی به مخزن وجود ندارد
مبنای کار git بر اساس محتوای فایلهاست و در معماری git امکان تعریف پوشهی خالی وجود ندارد. لذا برای رفع این مشکل معمولا به صورت قراردادی یک فایل خالی به نام empty در این پوشهها قرار میدهند.
عدم سازگاری با ویندوز
git را نویسندهی لینوکس(لینوس تروالدز) برای میزبانی پروژهی کرنل لینوکس نوشته است. و از همان ابتدا قابلیت حمل(portability) جزو اهداف پروژه نبوده است و فقط روی سیستم های *nix اجرا میشود. و رسما از ویندوز پشتیبانی نمیکند. البته این مشکل امروز تا حدود زیادی با کمک پروژه msysgit برطرف شده است. msysgit در واقع با پیاده سازی gcc و دستورات مورد نیاز در ویندوز قابلیت اجرا شدن git در ویندوز را فراهم میکند.
کمبود رابط گرافیکی قوی
برای svn تاکنون رابطهای گرافیکی فوقالعادهای نظیر TortoiseSVN نوشته شده است. ولی در مورد git هنوز در ابتدای راه هستیم. البته به تازگی نسخههای اولیهای از TortoiseGit که تلاشی برای شبیه سازی رابط گرافیکی محبوب TortoiseSVN برای git است منتشر شده است که هنوز تمام امکانات و دستورات git را پوشش نمیدهد.
یکی از دلایلی که قبلا برنامهنویسان کمتر به سیستمهای کنترل سورس توزیع شده روی میآوردند عدم پشتیبانی میزبانهایی نظیر SourceForge و Google Code بود. اما امروز تقریبا این مشکل حل شده است.
هم اکنون SourceForge از CVS و SVN و Git و Mercurial و Bazaar پشتیبانی میکند. و Google Code هم از SVN و Mercurial پشتیبانی میکند.
GitHub هم به عنوان یک میزبان برای پروژههای Git محبوبیت زیادی پیدا کرده و البته بیشتر از اینکه یک میزبان باشه یک شبکه اجتماعی برای میزبانی کدهاست.
در نهایت اگر تصمیم گرفتید از git استفاده کنید. خوندن کتابهای Git Internals و Version Control with Git رو توصیه میکنم.