گیت چیست؟

گیت یا git یک برنامه آزاد و متن باز برای مدیریت پروژه های برنامه نویسی هست که بسیار سریع و موثر می تواند به برنامه نویسان برای مدیریت پروژه های کوچک تا بزرگ کمک دهد. یادگیری و استفاده از گیت بسیار ساده است و امکانات بسیار قابل توجهی در اختیار برنامه نویسان قرار می دهد.

از توانایی های این نرم افزار می توان به نمونه های زیر اشاره کرد:

  • به شما امکان مدیریت پروژه های چند نفره را می دهد
  • به سادگی می توان تغییرات را ثبت، دنبال، و بازگردانی کرد
  • می تواند به یک سرور وصل شود تا علاوه بر داشتن یک بکاپ از کل پروژه آن را با دیگران به اشتراک بگذارید
  • امکان استفاده از چند شاخه، ادغام و مدیریت شاخه ها
  • و ...

من خودم به شخص قبلا فکر می کردم که گیت فقط برای پروژه های گروهی مناسب هست و زمانی از گیت و سایت هایی مانند گیتهاب و notabug استفاده کردم که برای اولین بار با فاروق کریمی زاده پروژه مشترک داشتیم؛ و از آن جا که شیوه یادگیری من و فاروق شبیه به پریدن وسط چهارمتری برای یادگیری شنا هست اول پروژه را آغاز و بعد به فکر یادگیری گیت افتادیم! برای همین گاها (دو سه باری) اشتباهاتی رخ می داد که برای جبران اون مجبور بودیم ساعت ها تو سایت های مختلف روش های مختلف رو امتحان کنیم و با پیغام خطا های مختلف روبرو بشیم! ولی به هر حال تونستیم تجربیات خوبی به دست بیاریم.

البته که یادگیری گیت بسیار فراتر از این مطلب است و تمام آموزش ها در مستندات خود گیت و در سوالاتی که در سایت هایی مثل stackoverflow.com هستند قابل جست و جو هستند و تمام آن ها در این مطلب قابل گنجاندن نیست، ولی در این مطلب سعی شده تا بخشی از پرکاربردترین و نکات اولیه گیت گنجانده شود تا برنامه نویسان تازه کار بتوانند سریع تر و راحت تر آن را یاد بگیرند و از آن استفاده کنند.

فضای ابری

یکی از رایج ترین روش های استفاده از گیت راه اندازی مخازن (repository) با میزبانی سایت هایی مانند github.com, gitlab.com, bitbucket.org, notabug.org و ... است که هر کدام علاوه بر گیت امکانات دیگری هم دارند. در این میان گیتهاب بسیار بسیار معروف است و امکانات جالبی دارند (که البته از وقتی که مایکروسافت اون رو خریده خیلی ها ازش رفتن و اون رو بد می دونن).

به هر حال؛ یک مخزن می تواند عمومی و یا خصوصی باشد، همان طور که مشخص است در حالت عمومی همه می توانند کد های شما را ببینند، مواردی (issue) را با شما در میان بگذارند، از شما در خواست ویرایش (pull request) کنند (مثلا می توانند بخشی از کدتان را ویراش کنند و از شما بخواهند تا آن را درصورت تمایل به کدتان اضافه کنید) و یا حتی پروژه شما را چنگال (fork) کنند (در این مورد ترجمه بهتری به ذهنم نرسید، مفهومش این هست که دیگران می تونن پروژه شما را با ذکر منبع کپی و نسخه ای از آن را خودشان توسعه دهند و شخصی کنند) و همچنین فرصت خوبی برای معرفی خودتان، ایده هایتان و کیفیت کارتان است. شما همچنین می توانید مستنداتی ارائه دهید تا برای عموم نمایش داده شود. از این مستندات می توانید برای اهداف بسیاری استفاده کنید مثلا برای راهنمایی کاربران یا توضیحاتی برای برنامه نویسانی که قصد همکاری دارند و ... از همه مهم تر شما می توانید لایسنس پروژه تان را انتخاب و آن را رسما اعلام کنید. لایسنس ها شرایط و ضوابط استفاده از نرم افزارتان توسط بقیه برنامه نویسان را توضیح می دهد. این همان چیزی است که تعیین می کند پروژه شما آزاد است یا نه

توجه شود که سه مورد متن باز (open-source)، آزاد (free)، و رایگان(free) با هم متفاوت هستند؛ پروژه های متن باز یعنی کد ها برای عموم قابل نمایش است، گاها پروژه های تجاری هم بخشی از کد را برای عموم به نمایش می گذارند ولی این به این معنا نیست که دیگران هم می توانند از آن نسخه برداری کنند، آزاد یعنی طبق شراط و ضوابطی دیگران نیز می توانند از بخشی یا کل پروژه تان نسخه برداری کنند، و رایگان هم که دیگر مشخص است. در دو مورد آخر چون در زبان انگلیسی free به هر دو معنی است گاها با هم اشتباه می شوند ولی در نهایت این لایسنس است که تعیین کننده است. اگر لایسنسی تعیین نکنید به صورت پیش فرض تمامی حقوق مادی و معنوی برای ناشر محفوض است و شما حق شکایت از افرادی که کپی برداری می کنند دارید. البته این در کشور هایی که قانون کپی رایت (copyright) سفت و سخت است مهم است.

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

اگر می خواهید از فضای ابری استفاده کنید باید یک حساب کاربری در یکی از سایت های میزبان گیت (git host) ثبت نام کنید و حساب کاربری بسازید.

شروع کار

قبل از هرچیز باید باید نرم افزار git را نصب کنید.

اگر از یکی از سایت های میزبان استفاده می کنید، یکی از راه ها این است که ابتدا یک مخزن (repository) بسازید. در روند ایجاد مخزن نام پروژه، وضعیت عمومی یا خصوصی و امکان افزودن فایل های اولیه ای که در ادامه به آن ها نیز خواهیم پرداخت را تعیین می کنید. معمولا خود سایت ها شما را راهنمایی می کنند که چگونه از مخزن استفاده کنید.

دو حالت کلی برای شروع وجود دارد؛ اگر مخزن ساخته شده دارای محتویاتی است مثلا یک مخزن مال فرد دیگریست و شما می خواهید آن را بارگیری کنید و یا این که مخزن تان را با فایل های اوله نمونه ساختید باید آن را با دستور git clone {ripository URL} پروژه را بر روی سیستمتان بارگزاری کنید، معمولا آدرس مخازن به .git ختم می شوند مانند git clone https://github.com/bsimjoo/hello_world.git توجه کنید که این دستور برای بارگیری کل مخزن بر روی سیستم شما است، یعنی صرفا مخزن را از طریق گیت دانلود می کند، این کار را می توان برای استفاده از یک برنامه هم انجام داد و تنها برای ویرایش مخزن نیست.

اگر هم مخزن خالی است و هیچ فایلی ندارد و یا مخزنی نساختید یک پوشه بر سیستمتان با اسم پروژه تان بسازید. حال باید git را در پوشه ای که ساختید اجرا کنید، در ویندوز می توانید این کار را با باز کردن پوشه، کلیک راست در محیط خالی پوشه و انتخاب گزینه git bash انجام دهید؛ با این کار کنسولی برای اجرای دستورات در آدرس فعلی باز می شود. از طریق خط فرمان هم می توانید با دستور cd ابتدا به دایرکتوری رفته و سپس می توانید دستورات بعدی را در دایرکتوری فعلی اجرا کنید (نیازی به دستور git bash یا چیز دیگری نیست) حال دستور git init را در کنسول بزنید تا گیت فایل های مورد نیاز خود را بسازد. از حالا به بعد این پوشه یک مخزن بر روی سیستم شما است.

برای این که مخزن را به یک remote که در واقع همان سایت های میزبان است وصل کنید باید از دستور git remote add origin {ropository URL} استفاده کنید برای مثال git add origin https://github.com/bsimjoo/helloworld.git به طور معمول ریموت اصلی را origin نام گذاری می کنند ولی به هر حال شما می توانید هر نام دیگری را هم انتخاب کنید. البته که افزودن ریموت برای زمانی که از git clone استفاده کردید لازم نیست مگر آن که بخواهید بیش از یک ریموت اضافه کنید و پروژه تان را بر روی چند سایت هاست کنید.

حال می توانید اولین فایل پروژه را بسازید و یا فایل های موجود رو تغییر دهید. بعد از انجام هر میزان تغییر برای آن که تغییرات را در گیت اضافه یا اصتلاحا stage کنید دستور git add {file dir} را وارد کنید، شما می توانید از این دستور به شکل های زیر استفاده کنید:

git add my_file.txt                     #add one file
git add "my file with space.txt"
git add file1 file2 "file 3" ...        #add multiple files
git add *                               #add any file using wildcard
git add *.txt                           #add any txt file with wildcard
git add *.txt *.py                      #add mutilple files by using more wildcards

این دستور باعث میشود تا گیت فایل های قید شده را بررسی و تغییرات را به صورت موقتی ثبت کند. حال شما باید برای تغییرات توضیح کوتاهی بدهید (می توانید شرح بلندی هم اضافه کنید که اختیاری است). پیدا کردن توضیح مناسب در بعضی مواقع سخت است و یکی از مشکلات اکثر برنامه نویس هاست! خیلی اوقات واقعا نمی دانید چی بنویسید! ولی این کار الزامی است و باعث می شود تا هم شما و هم بقیه (اگر عمومی باشد یا همکار داشته باشید) بدانند هدف این این تغییر چه بوده. این کار با دستور git commit انجام می شود. در این حالت این دستور یک ویرایشگر متن برای افزودن توضیح کوتاه و در صورت تمایل شرح بیشتر باز می کند ولی می توانید با دستور git commit -m {message} در همان خط توضیح را هم اضافه کنید. برای مثال: fit commit -m "bug fix"

حال اگر از یک مخزن آنلاین استفاده می کنید باید تغییرات را به آن ارسال کنید این کار با عمل push انجام می شود. در حالت کلی این دستور به این شکل است git push {remote-name} {branch} برای مثال: git push origin master سه نکته: یک این که برای آن که هربار  remote را وارد نکنید می تواید به این شکل دستور را بزنید: git push -u {remote-name} و دیگر آن که نام شاخه (branch) فقط برای اولین push لازم است و نکته دیگر این که branch چی هست؟ این موضوع را کمی پایین تر خواهم گفت فقط این را بگویم که این سه دستور گفته شده پر استفاده ترین دستورات هستند، شما می توانید تعدادی تغییرات را با هم جمع کنید و همه آن ها را یکجا push کنید.

برای آن که بتوانید تغییرات را از ریموت دریافت و مخزنی که در سیستم شما است را بروز کنید باید از دستور git pull استفاده کنید. این دستور تغییرات جدید را از ریموت دریافت و درصورت نیاز با تغییرات فعلی ادغام می کند. در مورد ادغام کردن در ادامه بیشتر توضیح میدم.

شاخه ها (branch)

همان طور که بالا تر در مقدمه گفتم، در گیت شما می توانید یک یا چند شاخه داشته باشید. شما می توانید با دستور git brach -c {branch-name} یک شاخه جدید در مخزن سیستم خودتان (محلی) بسازید و با push آن را به ریموت بفرستید ک هدر بخش قبلی شاخه اصلی در ریموت بوجود می آید. شما می توانید با دستور git checkout {destination} بین شاخه های مختلف جابجا شوید. از این دستور می توان برای کار های مختلف دیگری مانند سفر به زمان یک کامیت! یا رفتن به گذشته یک فایل قبل از حذف و ... استفاده کرد. شاخه ها می توانند با هم ادغام شوند، یعنی شما می توانید هر دو شاخه را به صورت موازی تغییر دهید و سپس زمانی که لازم داشتید تمام تغییراتی یک شاخه را بر دیگری اعمال کنید و دوباره به ایجاد تغییرات جدید ادامه دهید. این کار را merge می گویند. البته در ابتدا و زمانی که مبتدی هستید شاید این کار کمی دشوار و حتی در صورت استفاده ناصحیح و دقت نکردن کمی خطرناک باشد و اتفاقات ناخواسته ای رخ دهد. به خصوص زمانی که افراد دیگر به شما در خواست pull request می دهند شما باید ادغام انجام دهید تا تغییرات آن را قبول کنید و درصورتی که دقت نکنید ممکن است اتفاقات بدی رخ دهد. ولی به هر حال با استفاده از ادغام می توان کار های بسیار مفیدی انجام داد که یاد گرفتن آن را با ارزش می کند و از اوجب واجبات است!

شما در هر شاخه ای که هستید دستور main شاخه فعلی را با یک شاخه دیگر ادغام می کند و تغییرات آن شاخه را در شاخه فعلی اعمال می کند. توجه کنید تغییرات شاخه فعلی بر شاخه دیگر تاثیر ندارد. این دستور به صورت git merge {branch} استفاده می شود. برای مثال اگر طبق استراتژی که در ادامه توضیح خواهم داد اگر دو شاخه develop و main داشتید و می خواهید تغییرات را از develop به main منتقل کنید، ابتدا با دستور checkout به شاخه main می روید و سپس دستور git merge develop را وارد کنید تا تغییرات به این شاخه منتقل شود. البته بهترین کار این است که برای دقت بیشتر این دستور را با به صورت git merge --no-ff --no-commit develop اجرا کرد تا قبل از ثبت تغییرات در شاخه فعلی آن ها را بررسی، تناقض ها (conflict) را رفع و سپس کامیت کنید. تناقض ها زمانی به وجود می آیند که یک یا چند فایل به صورت موازی در هر دو شاخه تغییر کرده. در این صورت گیت نمی داند کدام تغییر را باید ذخیره کند و از شما می خواهد تا در این باره تصمیم بگیرید شما می تواند هردو و یا یکی از تغیرات را بپذیرید و یا هیچ کدام را قبول نکنید. در هر حال تا زمانی که تناقض ها رفع نشوند ادغام تمام نمی شود و شما نمی توانید آن را commit یا push کنید. زمانی که conflict رخ می دهد گیت پیغام به این شکل نمایش می دهد:

$ git merge develop
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.

در این صورت با دستور git status می توانید اطلاعات بیشتری کسب کنید. زمانی که فایلی که گیت با آن به مشکل برخورده مثل test.txt در مثال بالا را باز می کنید متنی به این شکل خواهید دید:

$ cat test.txt
<<<<<<< HEAD
this is some content to mess with
content to append
=======
totally different content to merge later
>>>>>>> develop

بخش بالایی که با <<<<<<< HEAD در بالای آن مشخص شده و با ======= جدا شده بخشی است که در حال حاضر در شاخه فعلی وجود دارد و قسمت پایینی در شاخه ای که می خواهید تغییرات را از آن وارد کنید. با ویرایش این بخش ها و حذف <<<<<<< HEAD و ======= و >>>>>> develop می تونید تناقض ها را برطرف کنید و با git add * و سپس git commit کار را تمام کنید. می توانید پیامی در نظر نگیرید تا پیام پیشفرض ادغام انتخاب شود.

یک استراتژی پیشنهادی

اگر کار با شاخه ها را یاد بگیرید می توانید هم خودتان و هم به دیگران کمک کنید تا بهتر پروژه را انجام دهید. شاخه ها با اهداف مختلفی ایجاد می شوند. در ادامه یک استراتژی خوب و قابل اطمینان برای شما به عنوان برنامه نویس و کاربران ارائه می دهم.

  • شاخه main یا master

این شاخه، شاخه پیشفرض مخزن شماست و باید شامل مستندات و یک نسخه پایدار از پروژه شما باشد. این شاخه برای کاربران نمایش داده می شود و کاربران با دستور git clone در ابتدا این شاخه را بارگیری می کنند.

  • شاخه develop

شاخه در حال توسعه شما این شاخه است. شما و تمام برنامه نویسان باید تغییرات را در این شاخه ثبت کنند و پس از انجام تست ها و در صورت نبود خطا های اولیه برای تست بیشتر آن را با شاخه های alpha و یا beta ادغام می کنید

  • شاخه beta و alpha

این شاخه ها برای انشار نسخه های نا پایدار و آزمایشی هستند. زمانی که شما یک قابلید جدید را به پروژه خود در شاخه develop اضافه می کنید و تست های اولیه را انجام می دهید آن را با شاخه alpha ادغام می کند تا نسخه alpha پروژه را با یک برچسب (tag) مشخص و منتشر کنید. برای این کار از دستور git tag {tag-name} استفاده کنید. برای آن که این tag را به ریموت ارسال کنید از دستور git push --tags استفاده کنید. نسخه آلفا نسخه ای است که شما در آن قصد دارید امکان جدیدی اضافه کنید. زمانی که یکی از امکانات موجود را در شاخه develop ویرایش می کنید آن را با ادغام در شاخه beta و ایجاد برچسب منتشر می کنید. در نسخه بتا امکان جدیدی اضافه نمی شود. زمانی که تمام تست ها انجام شدند و از پایداری مطمئن شدید آن را با main ادغام می کنید.

  • شاخه release

این شاخه برای ایجاد و انتشار نسخه ها هستند. زمانی که می خواهید یک نسخه جدید را منتشر کنید شاخه main را با آن ادغام کنید و یک tag جدید بسازید تا نسخه جدید نام گذاری شود. ممکن است بخواهید چند امکان را اضافه کنید و بعد یک نسخه ارائه دهید. از طرفی این شاخه شامل تمام نسخه های پایدار است.

  • شاخه doc

وجود این کاملا اختیاری است و اصولا زیاد واجب نیست چرا که شاخه main که شاخه پیشفرض است و ابتدا شاخه main برای کاربر نمایش داده می شود و لازم است تا مستندات در همان ورود کاربر برای او قابل مشاهده باشد. از طرفی می توان مستندات را مستقیما در همان شاخه main ویرایش کرد ولی این شاخه بیشتر برای زمانی است که شما کار با git را به خوبی یاد گرفتید در این صورت می توانید این شاخه را به وجود آورید تا در صورت نیاز مستندات را از این طریق به روز و با شاخه main ادغام کنید. همچنین اگر از گیتهاب استفاده می کنید می توانید از این شاخه برای github-page استفاده کنید تا یک صفخه وب برای پروژه تان بسازید.