” وقتی یک پروژه بزرگتر میشه و چند نفر همزمان روی اون کار میکنن، دیگه مدیریت روند توسعه به سادگی یک پروژه شخصی نیست. Git Flow کمک میکنه برای توسعه featureها، آمادهسازی نسخههای جدید و رفع مشکلات production مسیر مشخصی داشته باشیم. “
وقتی روی یک پروژه شخصی کار میکنی، احتمالاً مدیریت Git خیلی پیچیده نیست.
یک Branch داری، تغییراتت رو انجام میدی، commit میزنی و در نهایت تغییرات رو push میکنی.
همه چیز ساده هست.
اما...
فرض کن پروژه بزرگتر شده و چند نفر همزمان روی اون کار میکنن.
یکی داره روی صفحه ورود کار میکنه.
یکی دیگه مشغول ساخت داشبورد هست و خودت هم داری یک قابلیت جدید به پروژه اضافه میکنی.
اگه همه مستقیماً روی main کار کنن، خیلی زود با مشکلات مختلفی روبهرو میشید.
ممکنه یک feature هنوز کامل نشده باشه، اما وارد نسخه اصلی پروژه بشه.
یا یک تغییر جدید باعث خراب شدن بخشی از پروژه بشه.
یا چند نفر همزمان روی یک بخش کار کنن و Merge کردن تغییراتشون تبدیل به یک دردسر بزرگ بشه.
از طرف دیگه، ممکنه تیم در حال توسعه نسخه بعدی باشه، در حالی که نسخه فعلی پروژه روی production در حال اجراست و باید همچنان پایدار باقی بمونه.
اینجاست که یک سؤال مهم به وجود میاد:
چطور باید Branchهای پروژه رو مدیریت کنیم تا توسعه، انتشار و رفع مشکلات production مسیر مشخصی داشته باشن؟
یکی از روشهایی که برای حل این مشکل به وجود اومده، Git Flow هست.
Git Flow یک روش برای مدیریت Branchها در Git هست.
به جای اینکه همه تغییرات رو مستقیماً روی یک Branch انجام بدیم، برای هر نوع کاری Branch مخصوص خودش رو داریم.
مثلاً:
یک Branch برای نسخه اصلی و production
یک Branch برای توسعه
Branchهای جداگانه برای featureها
Branchهایی برای آمادهسازی نسخه جدید
و Branchهایی برای رفع مشکلات فوری production
در واقع Git Flow به ما میگه:
هر نوع تغییر، باید مسیر مشخص خودش رو در پروژه داشته باشه.
در ادامه، قدمبهقدم با هرکدوم از این Branchها آشنا میشیم و میبینیم هرکدوم چه کاربردی دارن و چه زمانی ازشون استفاده میکنیم.
برای اینکه بهتر متوجه بشیم، اول با یه مثال ببینیم اصلاً چرا به چنین ساختاری نیاز داریم.
فرض کن پروژهای داریم که نسخه فعلی اون روی main قرار داره.
امروز تصمیم میگیریم یک سیستم احراز هویت جدید به پروژه اضافه کنیم.
قبل از اینکه شروع کنیم به کار روی پروژه، معمولاً اولین کاری که انجام میدیم اینه که مطمئن بشیم همه چیز بهروز هست و آخرین تغییرات تیم رو داریم.
برای همین میایم آخرین وضعیت پروژه رو از مخزن میگیریم:
git checkout main
git pullgit checkout main → رفتن روی Branch به اسم main
git pull → گرفتن آخرین تغییرات از Remote Repository
در نسخههای جدید Git میتونیم برای جابهجایی بین Branchها از git switch هم استفاده کنیم:
git switch main
git pullدر این مقاله برای ساده موندن مثالها بیشتر از
git checkoutاستفاده میکنیم، چون هنوز هم در بسیاری از پروژهها و آموزشهای Git دیده میشه.
بعد از اینکه مطمئن شدیم پروژه بهروز هست، کار روی feature جدید رو شروع میکنیم.
حالا فرض کن چند ساعت روی یک قابلیت جدید کار کردیم.
مثلاً صفحه ورود رو جلو بردیم، اما هنوز بخشهایی مثل ثبت نام و بازیابی رمز عبور کامل نشده.
در این حالت اگه بخوایم تغییرات رو commit و push کنیم، در واقع داریم یک feature نیمهکاره رو وارد main میکنیم.
ممکنه پروژه همچنان اجرا بشه، اما این تغییرات میتونن نسخه اصلی پروژه رو ناپایدار کنن.
حالا فرض کن یک نفر دیگه همزمان روی پروژه کار میکنه و تغییرات خودش رو وارد main میکنه.
کمکم مدیریت پروژه سخت میشه.
البته این به معنی بد بودن کار با main نیست.
در بعضی Workflowها (روش کار و مدیریت پروژه)، مثل GitHub Flow،
main دقیقاً Branch اصلی توسعه هست و تغییرات از طریق Branchهای موقتی و Pull Request وارد اون میشن.
مسئله اینجاست که اگه تیم بخواد بین توسعه، نسخه در حال آمادهسازی و production مرز مشخصی داشته باشه، یک ساختار ساده مثل main و Feature Branch ممکنه کافی نباشه.
اینجاست که develop وارد داستان میشه.
در Git Flow کلاسیک، دو Branch اصلی داریم:
main
developهر کدوم هم وظیفه متفاوتی دارن.
main نماینده نسخه اصلی و قابل انتشار پروژه است.
به زبان ساده:
چیزی که داخل
mainقرار داره، باید نماینده یک نسخه قابل انتشار از پروژه باشه.
قرار نیست هر feature ناقصی مستقیماً وارد این Branch بشه.
develop جاییه که تغییرات جدید پروژه در اون جمع میشن.
featureهای مختلف در Branchهای جداگانه توسعه پیدا میکنن و وقتی آماده شدن، وارد develop میشن.
پس اگه خیلی ساده بخوایم بگیم:
┌── feature/login
│
main ───────────── develop ─── feature/dashboard
│
└── feature/profileدر این ساختار، main نماینده نسخه منتشرشده هست و develop محل جمع شدن تغییرات نسخه بعدی پروژه هستش.
Feature Branch برای توسعه یک قابلیت یا بخش جدید از پروژه استفاده میشه، بدون اینکه تغییرات اون مستقیماً وارد Branch اصلی توسعه بشن.
حالا فرض کن میخوایم قابلیت ورود رو به پروژه اضافه کنیم.
به جای اینکه مستقیم روی develop کار کنیم، یک Branch جدید میسازیم:
git checkout develop
git checkout -b feature/logingit checkout develop → رفتن روی Branch توسعه
git checkout -b feature/login → ساختن یک Branch جدید به اسم feature/login و رفتن روی اون
پس این دستور:
git checkout -b feature/loginتقریباً یعنی:
«از Branch فعلی یک شاخه جدید بساز و برو داخلش.»
در نسخههای جدید Git میتونیم همین کار رو با switch انجام بدیم:
git switch develop
git switch -c feature/loginحالا تغییرات مربوط به قابلیت ورود داخل همین Branch انجام میشن.
مثلاً:
develop
│
└── feature/loginدر طول توسعه میتونیم چندین commit داشته باشیم:
git add .
git commit -m "add login form"
git commit -m "add authentication logic"
git commit -m "handle login validation"تا زمانی که feature کامل نشده، کاری با develop نداریم.
این موضوع یک مزیت مهم داره.
اگه وسط کار متوجه بشیم قابلیت ورود هنوز آماده نیست، تغییرات ما همچنان از develop جدا هستن و روی Branch اصلی توسعه تأثیری ندارن.
فرض کن ورود کامل شده.
حالا وقتشه تغییرات رو وارد develop کنیم.
اینجا معمولاً دو روش داریم.
اگر تیم تصمیم گرفته باشه Merge رو مستقیم انجام بده، میتونیم بنویسیم:
git checkout develop
git merge feature/loginیعنی:
اول میریم روی develop
بعد تغییرات feature/login رو وارد develop میکنیم
بعد از Merge کردن، Feature Branch دیگه لزوماً مورد نیاز نیست و میتونیم اون رو حذف کنیم:
git branch -d feature/loginالبته این کار به Workflow تیم بستگی داره.
در بسیاری از پروژههای تیمی، به جای Merge مستقیم، تغییرات از طریق Pull Request بررسی میشن.
Pull Request یعنی:
«من تغییراتم رو آماده کردم، لطفاً اونها رو بررسی کن و اگه مورد تأیید بود، وارد Branch مقصد کن.»
مثلاً:
feature/login
│
│ Pull Request
▼
developPull Request خودش یک دستور Git نیست.
معمولاً روی سرویسهایی مثل GitHub یا GitLab ساخته میشه و اعضای تیم میتونن:
کد رو بررسی کنن
درباره تغییرات نظر بدن
تستها رو اجرا کنن
مشکلات احتمالی رو پیدا کنن
و در نهایت تغییرات رو Merge کنن
پس Pull Request بیشتر بخشی از فرآیند همکاری تیمی و Code Review هست.
حالا فرض کن همزمان سه نفر روی پروژه کار میکنن.
یکی ورود رو توسعه میده.
یکی داشبورد.
و نفر سوم سیستم Notification رو.
ساختار Branchها میتونه چیزی شبیه این باشه:
feature/login
/
develop ──────────┼──── feature/dashboard
\
feature/notificationهر توسعهدهنده روی Branch خودش کار میکنه.
تغییرات تا زمانی که آماده نباشن، وارد develop نمیشن.
این یعنی افراد مختلف میتونن همزمان روی بخشهای مختلف پروژه کار کنن، بدون اینکه هر commit مستقیماً روی Branch توسعه تأثیر بذاره.
حالا فرض کن چند feature مختلف توسعه پیدا کردن.
مثلاً:
Login
Dashboard
Notification
Profile
همه اینها وارد develop شدن.
حالا تیم تصمیم میگیره نسخه جدید پروژه رو منتشر کنه.
مثلاً:
نسخه 2.0.0
آیا همین الان باید develop رو Merge کنیم داخل main؟
نه لزوماً.
ممکنه هنوز نیاز داشته باشیم:
تستهای نهایی انجام بشن.
باگها برطرف بشن.
Version Number تغییر کنه.
Changelog آماده بشه.
تنظیمات مربوط به انتشار بررسی بشن.
آخرین بررسیهای مربوط به production انجام بشه.
اینجاست که Release Branch وارد داستان میشه.
Release Branch برای زمانی استفاده میشه که توسعه نسخه جدید تقریباً تموم شده و میخوایم اون رو برای انتشار آماده کنیم.
برای آماده کردن یک نسخه جدید، از develop یک Branch جدید میسازیم:
git checkout develop
git checkout -b release/2.0.0حالا:
develop
│
└── release/2.0.0از اینجا به بعد، تمرکز این Branch روی آماده کردن نسخه 2.0.0 هست.
مثلاً اگر یک باگ کوچیک پیدا بشه، میتونیم همینجا برطرفش کنیم.
اما قرار نیست در این مرحله featureهای کاملاً جدید و بزرگ اضافه کنیم.
چون هدف از Release Branch اینه که نسخهای که قبلاً توسعه پیدا کرده رو تثبیت و برای انتشار آماده کنیم، نه اینکه قابلیتهای جدید و بزرگ به اون اضافه کنیم.
فرض کن تستهای نهایی انجام شده و نسخه 2.0.0 آماده است.
حالا Release Branch باید وارد main بشه.
git checkout main
git merge release/2.0.0حالا main شامل نسخهایه که آماده انتشار شده.
در Git Flow کلاسیک، معمولاً نسخه منتشرشده رو با یک Tag هم مشخص میکنیم:
git tag v2.0.0
git push origin v2.0.0Tag باعث میشه بتونیم دقیقاً مشخص کنیم کدوم commit مربوط به نسخه 2.0.0 بوده.
مثلاً اگه چند ماه بعد بخوایم وضعیت نسخه 2.0.0 رو بررسی کنیم، میتونیم به همون Tag مراجعه کنیم.
اما کار هنوز تمام نشده.
ممکنه در Release Branch تغییراتی انجام داده باشیم که در develop وجود ندارن.
مثلاً یک باگ کوچیک رو در مرحله release برطرف کردیم.
پس باید این تغییرات رو به develop هم برگردونیم:
git checkout develop
git merge release/2.0.0چرا؟
چون نمیخوایم اصلاحاتی که هنگام آمادهسازی release انجام دادیم، فقط داخل main باقی بمونن.
بعد از اینکه Release Branch در هر دو مسیر Merge شد، معمولاً میتونیم اون رو حذف کنیم:
git branch -d release/2.0.0در نتیجه جریان کلی چیزی شبیه اینه:
develop
│
▼
release/2.0.0
│
├──────────► main
│
└──────────► developفرض کن چند روز از انتشار نسخه 2.0.0 گذشته.
یک کاربر گزارش میده که در production، هنگام پرداخت سفارش یک باگ جدی وجود داره.
تیم هم در حال توسعه نسخه 2.1.0 روی develop هست.
آیا باید باگ رو روی develop برطرف کنیم و بعد منتظر انتشار نسخه بعدی بمونیم؟
نه.
این باگ همین الان روی نسخه production وجود داره.
اینجاست که Hotfix Branch وارد داستان میشه.
Hotfix برای زمانی استفاده میشه که یک مشکل فوری در نسخه production پیدا شده و باید بدون منتظر موندن برای release بعدی برطرف بشه.
برای رفع یک مشکل فوری در نسخه منتشرشده، از main یک Branch جدید میسازیم:
git checkout main
git checkout -b hotfix/payment-errorحالا:
main
│
└── hotfix/payment-errorباگ رو برطرف میکنیم، تستها رو اجرا میکنیم و بعد Hotfix رو وارد main میکنیم:
git checkout main
git merge hotfix/payment-errorحالا میتونیم نسخه جدیدی منتشر کنیم.
مثلاً:
v2.0.1برای مشخص کردن این نسخه هم Tag ایجاد میکنیم:
git tag v2.0.1
git push origin v2.0.1اما یک کار دیگه هم باید انجام بدیم.
تغییر Hotfix باید وارد develop هم بشه:
git checkout develop
git merge hotfix/payment-errorچون اگه فقط main رو اصلاح کنیم، این تغییر وارد develop نمیشه و ممکنه همون باگ دوباره در نسخههای بعدی برگرده.
پس مسیر Hotfix به شکل زیره:
┌──────────► main
hotfix ──────┤
└──────────► developبعد از اینکه Hotfix در هر دو Branch قرار گرفت، میتونیم Branch مربوط به اون رو هم حذف کنیم:
git branch -d hotfix/payment-errorتا اینجا چند نوع Branch رو شناختیم:
main
develop
feature/*
release/*
hotfix/*اگه بخوایم خیلی خلاصه وظیفه هرکدوم رو ببینیم:
main نسخه پایدار و قابل انتشار پروژه
develop جمع شدن تغییرات نسخه بعدی
feature/* توسعه قابلیتهای جدید
release/* آمادهسازی یک نسخه برای انتشار
hotfix/* رفع مشکلات فوری production
پس میتونیم هسته Git Flow رو اینطوری در ذهن داشته باشیم:
┌── feature/*
│
main ─────────────── develop
│ │
│ └── release/*
│
└── hotfix/*البته این نمودار مسیر واقعی commitها رو به صورت کامل نمایش نمیده؛ فقط رابطه و نقش کلی Branchها رو نشون میده.
featureها از develop ساخته میشن و بعد از تکمیل، دوباره به develop برمیگردن.
feature/login
/
develop ───────────┼──── feature/dashboard
\
feature/profileوقتی زمان انتشار نسخه جدید رسید:
develop
│
▼
release/2.0.0
│
├──────────► main
│
└──────────► developو اگه یک مشکل فوری در production پیدا شد:
main
│
└── hotfix/payment-error
│
├──────────► main
│
└──────────► developهمین چند Branch، هسته اصلی Git Flow رو تشکیل میدن.
حالا بیایم همه چیز رو در قالب یک سناریوی واقعی مرور کنیم.
فرض کن پروژه ما یک فروشگاه اینترنتیه.
نسخه فعلی:
v1.0.0و main همین نسخه رو نگه میداره.
تیم تصمیم گرفته نسخه 1.1.0 رو توسعه بده.
ساختار فعلی:
main
│
└── developحالا یک نفر روی صفحه پروفایل کار میکنه:
git checkout develop
git checkout -b feature/profileنفر دوم هم روی سیستم تخفیفها کار میکنه:
git checkout develop
git checkout -b feature/discountحالا:
┌── feature/profile
│
develop ─────┤
│
└── feature/discountبعد از چند روز هر دو feature آماده میشن.
از طریق Pull Request وارد develop میشن.
حالا تغییرات نسخه بعدی داخل develop قرار گرفتن.
تیم تصمیم میگیره نسخه جدید رو آماده کنه.
پس:
git checkout develop
git checkout -b release/1.1.0در Release Branch چند باگ کوچیک برطرف میشه.
تستهای نهایی انجام میشن و نسخه آماده انتشار میشه.
حالا release وارد main میشه:
git checkout main
git merge release/1.1.0بعد Tag نسخه رو ایجاد میکنیم:
git tag v1.1.0
git push origin v1.1.0حالا تغییرات release رو هم به develop برمیگردونیم:
git checkout develop
git merge release/1.1.0و در نهایت Release Branch رو حذف میکنیم:
git branch -d release/1.1.0حالا پروژه در production نسخه 1.1.0 رو اجرا میکنه.
چند روز بعد یک باگ جدی در پرداخت پیدا میشه.
از main یک Hotfix میسازیم:
git checkout main
git checkout -b hotfix/paymentباگ برطرف میشه و بعد:
git checkout main
git merge hotfix/paymentنسخه جدید:
v1.1.1رو با Tag مشخص میکنیم:
git tag v1.1.1
git push origin v1.1.1بعد Hotfix رو به develop هم Merge میکنیم:
git checkout develop
git merge hotfix/paymentو در نهایت Branch مربوط به Hotfix رو حذف میکنیم:
git branch -d hotfix/paymentاین چرخه میتونه بارها و بارها تکرار بشه.
حالا که کل فرآیند رو دیدیم، بهتره برگردیم به سؤال اول مقاله.
چرا اصلاً Git Flow به وجود اومده؟
یکی از مهمترین دلایلش اینه که بین توسعه، آمادهسازی نسخه و production مرز مشخصی ایجاد کنه.
با این ساختار:
main میتونه وضعیت نسخه منتشرشده و production رو نگه داره.
develop محل جمع شدن تغییرات نسخه آینده است.
feature/* برای توسعه قابلیتهای جدید استفاده میشه.
release/* برای آماده کردن یک نسخه جدید استفاده میشه.
و hotfix/* برای رفع مشکلات فوری Production.
در نتیجه، هر Branch هدف مشخصی داره.
این ساختار میتونه به تیم کمک کنه که بدونه:
«این تغییر الان کجای چرخه توسعه قرار داره؟»
مثل هر روش دیگهای، استفاده اشتباه از Git Flow هم میتونه مشکلات خودش رو ایجاد کنه.
یکی از سادهترین اشتباهها اینه که برای راحتی، featureها رو مستقیماً روی main توسعه بدیم.
اگر پروژه تیمی باشه و فرآیند مشخصی برای review و انتشار نداشته باشیم، این کار خیلی زود باعث ایجاد مشکل میشه.
بهتره تغییرات جدید از مسیر Branch مناسب خودشون وارد پروژه بشن.
البته این به معنی ممنوع بودن کار مستقیم روی main در تمام Workflowها نیست.
Feature Branch قرار نیست ماهها از develop جدا بمونه.
هرچه یک Branch مدت بیشتری مستقل بمونه، احتمال ایجاد Conflict هنگام Merge بیشتر میشه.
اگه یک feature خیلی بزرگه، بهتره اون رو به بخشهای کوچکتر تقسیم کنیم.
این کار باعث میشه Branchها زودتر Merge بشن و احتمال ایجاد Conflict هم کمتر بشه.
وقتی Release Branch ساخته شد، هدف اصلی اون آماده کردن نسخه برای انتشاره.
اگر وسط این مرحله دوباره چند feature جدید بهش اضافه کنیم، کمکم مرز بین توسعه و انتشار از بین میره.
feature جدید بهتره در develop توسعه پیدا کنه و در release بعدی منتشر بشه.
فرض کن باگ رو در main برطرف کردی، اما تغییر رو به develop برنگردوندی.
چند هفته بعد نسخه جدید منتشر میشه و ممکنه همون باگ دوباره در نسخه جدید ظاهر بشه.
پس Hotfix باید بعد از اصلاح production، به Branch توسعه هم برگرده.
بعد از اینکه یک Feature، Release یا Hotfix کامل شد، اگه دیگه به Branch اون نیاز نداریم، بهتره حذفش کنیم.
مثلاً:
git branch -d feature/loginBranchهای زیاد و بلااستفاده میتونن پیدا کردن Branchهای فعال رو سخت کنن.
البته حذف Branch به معنی حذف commitهای Mergeشده از تاریخچه Git نیست.
اینجا شاید بعد از خوندن مقاله این سؤال برات پیش بیاد:
«پس همه پروژهها باید از Git Flow استفاده کنن؟»
نه.
و اتفاقاً این نکته خیلی مهمه.
Git Flow فقط یکی از روشهای مدیریت Branchهاست.
برای پروژههایی که Releaseهای مشخص دارن و معمولاً نسخههای مختلف رو در بازههای مشخص منتشر میکنن، Git Flow میتونه انتخاب مناسبی باشه.
اما برای پروژههایی که مرتب Deploy میشن، ممکنه این ساختار بیش از اندازه پیچیده باشه.
در چنین پروژههایی روشهایی مثل GitHub Flow یا Trunk-Based Development میتونن انتخاب سادهتری باشن.
در GitHub Flow معمولاً ساختار سادهتره.
به جای داشتن main و develop و Release و Hotfix، بیشتر کارها حول main و Branchهای موقتی انجام میشن.
مثلاً:
main
│
└── feature/login
│
▼
Pull Request
│
▼
mainیعنی feature توسعه پیدا میکنه، Pull Request ساخته میشه، کد بررسی میشه و بعد وارد main میشه.
اگر پروژه به Continuous Deployment نزدیک باشه، حتی میشه بعد از Merge شدن تغییرات، فرآیند Deploy رو به صورت خودکار انجام داد.
این مدل برای تیمهایی که مرتباً تغییرات کوچیک منتشر میکنن، میتونه بسیار مناسب باشه.
پس نمیتونیم بگیم:
Git Flow بهتر از GitHub Flow است.
یا برعکس.
سؤال درست اینه:
کدوم روش با فرآیند توسعه و انتشار پروژه ما سازگارتره؟
در Trunk-Based Development، توسعهدهندهها معمولاً روی Branchهای موقتی و کوتاه کار میکنن و تغییراتشون رو در بازههای کوتاه وارد یک Branch اصلی، یا اصطلاحاً Trunk، میکنن.
هدف این روش اینه که تغییرات سریعتر با هم ترکیب بشن و Branchها برای مدت طولانی از Branch اصلی جدا نمونن.
این روش معمولاً در تیمهایی استفاده میشه که فرآیند Continuous Integration (ادغام مداوم تغییرات) و Continuous Delivery (آماده نگه داشتن پروژه برای انتشار) رو به شکل منظم اجرا میکنن.
به زبان ساده، تیم مرتب تغییرات کوچک رو وارد Branch اصلی میکنه و سیستمهای تست و انتشار هم کمک میکنن که این تغییرات سریع بررسی و آماده انتشار بشن.
اما برای پروژهای که Releaseهای مشخص، نسخهبندی رسمی و فرآیند انتشار مرحلهای داره، Git Flow ممکنه ساختار واضحتری ایجاد کنه.
باز هم یک جواب واحد برای همه پروژهها وجود نداره.
اگر پروژهای داری که:
Releaseهای مشخص و نسبتاً رسمی داره.
چند Feature همزمان توسعه داده میشن.
بین نسخه توسعه و نسخه production تفاوت مشخصی وجود داره.
نیاز داری فرآیند Release رو جداگانه مدیریت کنی.
گاهی Hotfix فوری برای نسخه production داری.
Git Flow میتونه انتخاب مناسبی باشه.
اما اگر:
مرتب Deploy میکنی.
Featureها کوچک هستن.
تیم کوچیکه.
میخوای ساختار Branchها ساده باشه.
تغییرات خیلی سریع وارد Production میشن.
احتمالاً GitHub Flow یا یک مدل سادهتر انتخاب بهتریه.
در نهایت، قرار نیست Branchهای بیشتری داشته باشیم فقط برای اینکه پروژه حرفهایتر به نظر برسه.
هدف Git Flow اینه که مدیریت تغییرات پروژه قابل پیشبینیتر و منظمتر بشه.
Git Flow در ابتدا توسط Vincent Driessen معرفی شد و برای سالها یکی از شناختهشدهترین روشهای مدیریت Branch در Git بود.
اما دنیای توسعه نرمافزار تغییر کرده.
امروزه خیلی از تیمها به سمت روشهایی رفتن که در اونها تغییرات کوچیکتر و سریعتر وارد پروژه میشن و فرآیند تست و انتشار هم تا حد زیادی خودکار شده.
در این روشها معمولاً مفاهیمی مثل Continuous Integration (ادغام مداوم تغییرات)، Continuous Delivery (آماده نگه داشتن پروژه برای انتشار) و Continuous Deployment (انتشار خودکار تغییرات) استفاده میشن.
همچنین تیمها بیشتر از Branchهای موقتی و کوتاه استفاده میکنن تا تغییرات برای مدت طولانی از Branch اصلی جدا نمونن.
به همین دلیل Git Flow رو نباید به عنوان یک قانون همیشگی در نظر بگیریم.
بهتره اون رو به عنوان یکی از روشهای مدیریت فرآیند توسعه ببینیم.
ممکنه برای یک پروژه عالی باشه و برای پروژهای دیگه فقط پیچیدگی اضافه ایجاد کنه.
چیزی که در این مقاله دیدیم، نسخه کلاسیک Git Flow بود.
یعنی ساختاری شامل:
main
develop
feature/*
release/*
hotfix/*اما Git Flow یک قانون رسمی و اجباری در خود Git نیست.
Git فقط ابزار کنترل نسخه است.
Git Flow یک روش برای مدیریت فرآیند توسعه است که روی Git استفاده میشه.
پس اگر پروژهای داری که به همه این Branchها نیاز نداره، لازم نیست صرفاً به خاطر اسم Git Flow همه اونها رو ایجاد کنی.
ممکنه یک پروژه فقط به این ساختار نیاز داشته باشه:
main
│
└── feature/*و یک پروژه دیگه واقعاً به:
main
develop
feature/*
release/*
hotfix/*نیاز داشته باشه.
مهم اینه که Workflow به جای ایجاد پیچیدگی، یک مشکل واقعی رو حل کنه.
در این مقاله با Git Flow آشنا شدیم و دیدیم چطور میشه با استفاده از Branchهای مختلف، فرآیند توسعه و انتشار یک پروژه رو مدیریت کرد.
یاد گرفتیم که:
main برای نسخه پایدار و قابل انتشار پروژه است.
develop محل جمع شدن تغییرات در حال توسعه است.
feature/* برای توسعه قابلیتهای جدید استفاده میشه.
release/* برای آمادهسازی یک نسخه جدید ساخته میشه.
و hotfix/* برای رفع مشکلات فوری Production استفاده میشه.
همچنین دیدیم که Pull Request میتونه قبل از Merge شدن تغییرات، امکان Code Review و اجرای تستها رو فراهم کنه.
با Release Branch یاد گرفتیم که میشه مرحله آمادهسازی نسخه رو از توسعه Featureهای جدید جدا کرد.
و با Hotfix دیدیم که چطور میشه یک مشکل فوری production رو بدون متوقف کردن توسعه نسخه بعدی برطرف کرد.
اما مهمتر از همه فهمیدیم که هدف Git Flow، زیاد کردن تعداد Branchهای پروژه نیست.
هدف اینه که هر تغییر، مسیر مشخص خودش رو داشته باشه.
وقتی چند نفر همزمان روی یک پروژه کار میکنن، داشتن یک فرآیند مشخص میتونه جلوی خیلی از مشکلات رو بگیره.
اما در نهایت:
بهترین Workflow، پیچیدهترین Workflow نیست؛ روشی است که با نیازهای واقعی پروژه شما هماهنگ باشد.
پس قبل از اینکه Git Flow رو وارد پروژه کنی، اول به فرآیند توسعه، اندازه تیم، نحوه انتشار و سرعت Deploy پروژه نگاه کن.
ممکنه Git Flow دقیقاً چیزی باشه که بهش نیاز داری.
و ممکنه یک Workflow سادهتر، انتخاب بهتری باشه.
اگر جایی سوالی داری، نکتهای به ذهنت رسید، یا حتی اگه فکر میکنی یه قسمتی از این مقاله رو میشه بهتر نوشت، حتماً تو نظرات بهم بگو.
همه با هم یاد میگیریم! 🙏
دیدگاه و یا پرسش خود را برای ما ارسال کنید.
هنوز دیدگاه یا پرسشی ایجاد نشده است :/
تجربهها، دیدگاهها و نکات الهامبخشی که با شما به اشتراک میگذاریم.