یه روش خوب برای استفاده از گیت

تا حالا شده که توی کار تیمی یا حتی انفرادی خودت به خودت بگی «از دست این گیت لعنتی» خب مشکل کجاست؟ چرا ما نمی تونیم از حداکثر قابلیت های گیت استفاده بکنیم؟ چرا این merge ها و branch ها اینقدر دردسر ساز هستن؟ چرا این commit کردن ها و ... به نظرمون بی فایده هستن.

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

برنچ ها

ما ۲ تا branch اصلی داریم که تا آخر پروژه همراهمون هستن: develop و master

قرارداد ما برای نام گذاری برنچ های release ،hotfix و feature اینه:

release-*, hotfix-*, feature-*

برنچ master

شما (به عنوان lead developer) همون اول ممکنه دو تا کار بکنی، اولیش اینه که بیای یه پروژه خالی توی گیت ایجاد کنی (بدون هیچ فایلی/دایرکتوری)، توش اولین commit رو بزنی و بعدش بری تو برنچ develop و شروع به توسعه دادن بکنی.

یا که یه template داری/از template های پیش فرض (مثلا برای نود.جی‌اس یه سری فایل و دایرکتوری داری که به عنوان custom template به گیت هابت (یا هر سرویس دهنده دیگه ای) معرفی کردی) استفاده می کنی. حالا میای اولین commit رو میزنی و بعدش توسعه پروژه.

نکته مهم اینه شما باید همیشه توی برنچ origin/master یه ورژن production داشته باشی که بتونن باهاش کار بکنن. پس هر وقت پروژه به یه مرحله ای از توسعه رسید که میشد ارائه کردش میتونی اونو توی برنچ master آوردش و بعدش تگ زد.



نکته مهم: اگه میخوای یه brasnch ای رو merge کنی و اون برنچ مقصد برنچ release یا develop و master هست باید از فلگ no fast forward استفاده بکنی.

همون طوری که میبینید وقتی برنچ develop رو با f1 میخوای merge کنی اگه به صورت معمولی merge کنی (git merge (plain)) میاد تاریخچه لاگ های commit هات رو هم توی برنچ develop نمایش میده. به بیان ساده تر وقتی git log میزنی بهت commit هایی رو که توی برنچ f1 زدی نمایش میده.

ولی ما این رو نمیخواهیم. میخوایم که لاگ های برنچ develop فقط نشان دهنده merge ها باشه. به همین دلیل از git merge --no-ff استفاده می کنیم.

برنچ develop

برنچ توسعه ما هست که فقط یه دونه هم هست. فرض کنید میخواهیم که قابلیت خرید محصول رو به پروژه اضافه کنیم. برای همین منظور یه برنچ feature-order رو میسازیم و توش این قابلیت رو پیاده سازی میکنیم. حالا وقت merge کردن برنچ feature-order با برنچ develop هست.

توی این برنچ ما همیشه آخرین تغییرات رو که برای ورژن بعدی توسعه داده ایم داریم. وقتی که تغییرات stable شدن میایم اونا رو با برنچ master (البته با واسطه) merge میکنیم و بعدش تگ هم میزنیم که مشخص بشه کدوم ورژنه.

برنچ های release

کاربرد این نوع branch ها آماده سازی برای بیرون دادن یه production ورژن هست. توی این دسته از branch ها میتونی باگ های minor رو درست کنی. خوبی این برنچ اینه که باعث میشه برنچ develop تمیز بمونه و بتونیم توش ویژگی های جدید رو توسعه بدیم.

وقتی یه برنچ release از برنچ develop بیرون میاد (برنچ release جدید میسازیم) که برنچ develop به اون حدی رسیده باشه که بتونیم بگیم این یه release جدیده.

پس ابتدا میایم همه ی برنچ های feature ای رو که برای این release لازمه با برنچ develop مرج (merge) می کنیم و برنچ های feature دیگه ای که برای این release نیستن باید صبر کنن تا اول برنچ release مورد نظر ساخته بشه و بعدش اونا با برنچ develop مرج (merge) بشن.

این دسته از برنچ ها merge شون فقط با برنچ develop یا master اتفاق میفته. بعدش باید تگ بزنی روی اون merge تا ورژن مشخص بشه. برنچ های release مختلفی ممکنه بوجود بیاد.

git checkout -b release-v1.2 develop

حالا میای کار های مورد نظرت رو میکن و بعدش commit شون میکنی.

git commit -a -m &quotsome changes&quot

وقتی که برنچ release به وضعیتی میرسه که دیگه یه release واقعی هست اون برنچ بسته میشه. برای بستن یه برنچ release باید چند تا کار کرد:

  • اون برنچ release رو با برنچ master مرج (merge) کرد.
  • کامیت (commit) اون merge رو باید تگ زد تا رفرنس دادن بهش ساده تر بشه.
  • در نهایت باید اون برنچ release با برنچ develop مرج (merge) بشه.
git checkout master
git merge --no-ff release-v1.2
git tag -a 1.2

برای اینکه بتونی تغییرات برنچ release رو توی برنچ develop داشته باشی لازمه که merge شون بکنی. البته ممکنه به conflict هایی هم بخوری که طبیعی هست. پس درست کنشون و ادامه بده. حذف کردن برنچ هم یه توافقی هست که توی تیم صورت میگیره.

git checkout develop
git merge --no-ff release-v1.2
git branch -d release-v1.2

برنچ های hotfix

این نوع برنچ ها معمولا از برنچ master ایجاد میشن (branch off میشن). این برنچ ها آماده سازی های قبل از بیرون دادن یه production release هستن. توی این دسته از branch ها میای گند کاری هایی که نیاز به اصلاح شدن ضربتی دارن رو درست میکنی. علت وجودی این برنچ، این طرز تفکره که، در حالی که بقیه اعضای تیم دارن توی برنچ develop پروژه رو توسعه میدن یه نفر بره اون باگ رو درست کنه.

git checkout -b hotfix-v1.2.1 master

حالا مثلا باگ رو درست کردیم.

git commit -a -m &quotBumped version number to v1.2.1&quot
git commit -m &quotFixed severe production problem&quot

در نهایت پس از اینکه کارمون توی این نوع برنچ ها تموم شد باید اونا رو با برنچ develop و master مرج بکنیم. دلیل merge کردن با برنچ develop اینه که مطمئن بشیم تو ورژن های بعدی اون باگ رو نداریم.

git checkout master
git merge --no-ff hotfix-v1.2.1
git tag -a 1.2.1
git checkout develop
git merge --no-ff hotfix-v1.2.1
git branch -d hotfix-v1.2.1

فقط یادتون باشه که اگه در حال حاظر یه برنچ release دارید باید بجای merge کردن با برنچ develop برنچ hotfix رو با برنچ release مرج کنید مگه اینکه توی برنچ develop به اون hotfix نیاز شدیدی وجود داشته باشه.

برنچ های feature

این برنچ ها محلی هست که شما واقعا میاید کد می زنید و git commit می کنید. شروع این برنچ ها از برنچ develop هس و در نهایت merge شدنشون هم تو برنچ develop هس. این برنچ ها محلی برای افزودن ویژگی های جدید به پروژه هست. پس تا زمانی که اون ویژگی به صورت کامل پیاده سازی نشده وجود دارن.

مثلا میخوای یه ویژگی به پروژه اضافه بکنی:

git checkout -b feature-create-order develop

حالا زمان ادغام کردن این ویژگی توی برنچ develop هست:

git checkout develop
git merge --no-ff feature-create-order
git branch -d feature-create-order
git push origin develop

البته حذف کردن برنچ اختیاری هست و شما ممکنه تصمیم بگیری حذفش نکنی.

نکته بعدی: اگه دو تا برنچ feature-1 و feature-2 رو میخوای با هم merge کنی دو راه داری که هر کدومشون تو یه شرایطی استفاده میشن:

  • اگه مثلا تکمیل شدن برنچ feature-1 به feature-2 نیازی نداره، feature-1 رو با برنچ develop مرج کرده و بعدش میایم تغییرات رو از روی برنچ develop روی برنچ feature-2 میاریم.
git checkout feature-1
git commit -m &quotfeature-1 completed&quot
git checkout develop
git merge feature-1
git checkout feature-2
git merge develop
  • ولی اگه کامل شدن feature-1 به کامل شدن feature-2 وابسته باشه و کامل شدن feature-2 به کامل شدن feature-1 وابسته باشه میایم یه برنچ جدید ایجاد می کنیم و توی اون branch هر دو برنچ رو merge میکنیم و بعد از اینکه تغییرات کامل شد branch جدید رو با برنچ develop مرج می کنیم.
git checkout -b merge-feature-1-and-feature-2
git merge feature-1
git merge feature-2
git commit -m &quotfeature-1 & feature-2 completed.&quot
git checkout develop
git merge merge-feature-1-and-feature-2



نحوه کامیت زدن

چند تا نکته خیلی مهم رو باید به خاطر داشته باشید و اونم ایناس:

  • حفظ ACIDE بودن کامیت ها؛ یعنی وقتی چند تا کامیت میزنید هر کامیت فقط به کامیت های قبل از خودش وابسته باشه نه کامیت های بعدی. حتی اگه چند تا تغییر رو با هم انجام داده اید که به هم وابسته هستن رو سعی کنید به چند تا کامیت بشکنید. برای اینکار می تونید برنچ های temporary ایجاد کنید و توشون سعی کنید کارتون رو بشکنید.
  • توی message هر کامیت مسیر کامل فایلی که تغییر داده شده رو ننویسید.
  • برای نوشتن message هر کامیت از این الگو پیروی کنید:
process (scope): your message

برای process

  • مقدار add یعنی اینکه قابلیت جدید یا کد جدیدی داریم
  • مقدار init یعنی اینکه فایل/کد جدیدی داریم
  • مقدار refactor یعنی یه تیکه کد رو به نحوی کردیم که روی بقیه کد ها تاثیر داره
  • مقدار update یعنی یه تیکه کد عوض شده ولی روی بقیه کد ها تاثیر نداره
  • مقدار remove یعنی یه تیکه کد یا فایلی رو حذف کردی
  • مقدار cleanup یعنی consle.log ها یا code smell ها رو حذف کردی.
  • مقدار doc برای زمانی که داکیومنت می نویسی (کامنت میزاری)
  • مقدار log برای زمانی فقط لاگ میندازی


https://dev.to/helderburato/patterns-for-writing-better-git-commit-messages-4ba0
https://dev.to/helderburato/patterns-for-writing-better-git-commit-messages-4ba0



برای scope

توی پرانتز میای محدوده تغییر رو مشخص میکنی. معمولا اسم پکیج هست ولی میتونی ریز ترش هم بکنی و بگی توی اون پکیج‌ کدوم بخش رو تغییر دادی. یعنی توی اون scope کدوم بخش رو عوض کردی

مثال:

init (auth model): user.js
update (blog controller): post's view counter updated.
cleanup (mail): duplicate code for send mail removed.

منابع

رفرنس