برای اضافه کردن یک feature جدید یا رفع یک باگ (bug) ، برنامه نویس ها معمولا از برنچ (branch) استفاده میکنند و باگ یا feature رو در این برنچ فرعی انجام میدهند تا برنچ اصلی تا زمانی که اصلاح و تست ها انجام نشده تغییر نکند و بعد از تموم شدن کار باید برنچ فرعی رو داخل برنچ اصلی( main یا master )اضافه کنیم
برای این کار دو روش وجود دارد : merge و rebase

با استفاده از merge میتونیم دو تا برنچ را با هم ادغام کنیم یعنی تمام تغییرات داخل برنچ فرعی را داخل برنچ اصلی اضافه میکنیم.
برای این کار به برنچ اصلی میرویم و دستور زیر را وارد میکنیم :
git checkout main #برای کسانی که برنچ اصلی با نام master هست از این به جای main استفاده میکنیم git merge chapter3 #براساس نام برنچ فرعی chapter3 تغییر میکند
زمانی که برنچ اصلی ما همزمان با برنچ فرعی تغییر نکرده است (یعنی تمام تغییرات ما در برنچ فرعی اتفاق افتاده) این قضیه مشکلی ایجاد نمیکنه ولی برای زمانی که برنچ اصلی هم همزمان با برنچ فرعی تغییر کرده برای ادغام این دو برنچ یک مشکل وجود داره

مشکل merge کردن برنچ :
مشکل اصلی اینه که هنگامی که میخواهیم برنچ رو merge کنیم گیت نمیتونه کامیت به کامیت رو دقیق در جای خودش قرار بده و نحوه قرار گیری کامیت های قبلی رو تغییر بده پس میاد یک کامیت جدید درست میکنه برای اضافه کردن برنچ فرعی به برنچ اصلی و یک ساختار درختی درست میکند یعنی از یه قسمت لاگ های پروژه دو شاخه میشه و با برنچ به هم متصل میشوند (همانند تصویر بالا که به دو شاخه تبدیل شده و در نهایت با هم merge شدن) این برای مدیر های پروژه اصلا خوب نیست چون ساختار تمیز پروژه خراب میشود (مثلا داخل یک پروژه بزرگ اگر بخواهیم چند برنامه نویس همزمان جداگانه هر کدام یک فیچر برای برنامه بنویسند و یک برنچ برای آن درست کنند یک ساختار درختی خیلی کثیف درست میشود)
برای اینکه این مشکل حل شود از rebase استفاده میکنیم
با استفاده از rebase میتوانیم مشکل merge کردن را حل کنیم با rebase تمام تغییرات را دوباره در بالای آخرین کامیت (commit) برنچ اصلی اضافه میکنیم
برای این کار به برنچ فرعی میرویم و دستور زیر را وارد میکنیم :
git checkout chapter3 // براساس نام برنچ فرعی chapter3 تغییر میکند git merge main //برای کسانی که برنچ اصلی با نام master هست از این به جای main استفاده میکنیم
این کار با عث میشود به جای اضافه کردن کامیت جدید و ساختار درختی تمام کامیت ها برنچ فرعی رو به داخل برنچ اصلی بریزد و دیگر کامیت اضافه تری نمیزارد و هم ساختار نا مرتب و درختی ایجاد نمی کند

در اینجا کامیت c31d33b51406 بعد از کامیت abd4840f34d33 نوشته شده است ولی بعد از rebase کردن کامل تاریخچه مربوط به برنچ فرعی در بالا کامیت های برنچ اصلی قرار میگیرد و بازنویسی میشود
نکته : با rebase تمام کامیت های شما دوباره از اول باز نویسی میشود که میتواند برای شما مشکلاتی ایجاد کند چون تاریخ کامیت ها را به طور کامل تغییر پیدا میکند و دوباره نویسی می شود به این نکته هم باید توجه داشت.
تاریخچه (History) :
در merge تاریخچه پروژه به صورت درختی و غیر خطی هست ولی در rebase تاریخچه مرتب و خطی می ماند
تغییرات :
در merge تغییرات پروژه دست نخورده باقی میماند و یک کامیت برای اتصال دو برنچ به هم استفاده میکنیم و غیر خطی هست ولی در rebase تغییرات پروژه از قسمت برنچ فرعی به طور کامل بازنویسی میشود
ترتیب کامیت ها :
در merge ترتیب کامیت ها دست نخورده باقی میماند و با همان ترتیب ایجاد شده باقی میماند ولی در rebase ترتیب کامیت ها ممکن تغییر کند و کامیت های برنچ فرعی کامل در بالا آخرین کامیت برنچ اصلی بازنویسی میشود .
نکته مهم : برای merge کردن باید داخل برنچ اصلی نام برنچ فرعی رو بنویسید ولی برای rebase کردن باید در برنچ فرعی نام برنچ اصلی را بنویسید (این نکته را خیلی از مواقع اشتباه میشود)
این مقاله هم برای تمیز کردن تاریخچه گیت با Git squash هست اگر دوست داشتین میتونید این مقاله را هم مطالعه کنید
امیدوارم این مقاله ها بتواند در یادگیری مفاهیم گیت کمک شما کند.