آنچه در این مقاله میخوانید [پنهانسازی]
تفاوت Git Rebase و Merge در این است که Merge تاریخچه را حفظ میکند و یک «merge commit» میسازد، اما Rebase تاریخچه را بازنویسی میکند و کامیتها را روی مبنای جدید میچیند تا خطی شود. قاعده عملی: برای شاخههای عمومی و ادغام نهایی از Merge استفاده کنید؛ برای شاخههای شخصی و تمیزکردن تاریخچه قبل از انتشار، Rebase انتخاب بهتری است. هرگز شاخهای را که دیگران از آن pull میگیرند Rebase نکنید.
تفاوت Git Rebase و Merge به زبان ساده
هر دو روش هدف مشترکی دارند: همگام کردن تغییرات شاخهها. اما نحوه برخورد با تاریخچه متفاوت است:
- Merge: دو شاخه را به هم متصل میکند و یک merge commit میسازد. تاریخچه به صورت شاخهای باقی میماند و مسیر دقیق توسعه حفظ میشود.
- Rebase: پایه شاخه شما را تغییر میدهد و کامیتها را یکی یکی روی مبنای جدید «اعمال» میکند. تاریخچه خطی، اما شناسههای کامیت (SHA) تغییر میکنند.
نتیجه عملی: Merge امنتر برای همکاری است، Rebase مرتبتر برای خوانایی تاریخچه و قبل از اشتراکگذاری.
چه زمانی از Merge استفاده کنیم؟
- ادغام ویژگی در شاخههای عمومی مثل main یا develop: تاریخچه واقعی حفظ میشود، خطر کمتری برای همتیمیها دارد.
- زمانی که شواهد ادغام (context) مهم است: در پروژههای پیچیده، merge commitها نقاط ادغام را شفاف میکنند.
- وقتی امضای کامیتها یا ارجاع به SHAs اهمیت دارد: Rebase شناسهها را عوض میکند؛ Merge آنها را نگه میدارد.
- انتشار نسخه و hotfixهای حساس: حداقل ریسک برای تاریخچه مشترک.
چه زمانی از Rebase استفاده کنیم؟
- بهروزرسانی شاخه شخصی قبل از باز کردن PR: تغییرات main را روی شاخه خودتان Rebase کنید تا تاریخچه خطی و تعارضها زودتر حل شوند.
- تمیز کردن تاریخچه قبل از اشتراکگذاری: با interactive rebase کامیتهای ویرایشی را squash/fixup کنید.
- هماهنگ نگه داشتن مخزن محلی: تنظیم pull با –rebase تاریخچه محلی شما را بدون merge commitهای اضافی خطی نگه میدارد.
توجه مهم: شاخهای که روی ریموت منتشر شده و دیگران از آن pull میگیرند را Rebase نکنید. اگر مجبور شدید، فقط با --force-with-lease و بعد از هماهنگی تیمی.
نمونه عملی: یک فلو روزمره تیمی
هدف
روی شاخه feature کار میکنید؛ main جلوتر رفته. میخواهید ویژگی را با تاریخچه تمیز و کمریسک ادغام کنید.
مراحل
- ایجاد شاخه ویژگی و چند کامیت:
git checkout -b feature/login
git commit -m "feat: add login form"
git commit -m "fix: validation edge cases"
- همگامسازی با main با Rebase (فقط شاخه شخصی):
git fetch origin
git rebase origin/main
# در صورت تعارض:
# فایلها را اصلاح کنید
git add path/to/file
git rebase --continue
# در صورت پشیمانی:
# git rebase --abort
- تمیز کردن تاریخچه (اختیاری، قبل از انتشار):
git rebase -i HEAD~4
# در ویرایشگر:
# pick c1 feat: add login form
# squash c2 fix: address review comments
# fixup c3 style: lint
# pick c4 feat: remember me
- انتشار شاخه (در صورت Rebase، به push دقت کنید):
git push -u origin feature/login --force-with-lease
- ادغام در main روی سرور:
- استراتژی «Merge commit» اگر حفظ تاریخچه شاخهها مهم است.
- «Squash and merge» اگر میخواهید یک کامیت تمیز در main داشته باشید.
- «Rebase and merge» اگر تیم تاریخچه کاملا خطی در main میخواهد و تعارضها قبلا حل شدهاند.
تاریخچه چه شکلی میشود؟
# قبل از Rebase
A---B---C main
\
D---E feature
# بعد از Rebase (روی main)
A---B---C---D'---E' feature
# اگر حالا merge کنید و fast-forward ممکن باشد، merge commit لازم نیست.
با Merge مستقیمِ main در feature (بدون Rebase)، یک گره ادغام میگیرید:
# merge feature into main (بدون rebase)
A---B---C-------F main (F یک merge commit است)
\ /
D---E feature
مزایا و معایب بهصورت خلاصه
| معیار | Merge | Rebase |
|---|---|---|
| شکل تاریخچه | شاخهای، با merge commit | خطی و مرتب |
| حفظ SHA و امضا | بله | خیر (بازنویسی میشود) |
| ریسک برای شاخه عمومی | کم | زیاد (در صورت استفاده اشتباه) |
| خوانایی برای مرور تغییرات | خوب در پروژههای بزرگ | عالی در نگاه کلان |
| بازگشت (revert) و ردیابی با bisect | قابل پیشبینی | ممکن است دشوارتر شود |
نکات ایمنی و خطاهای رایج
- هیچوقت شاخهای که دیگران از آن pull میگیرند را Rebase نکنید. اگر ناچار شدید: هماهنگی تیمی +
git push --force-with-lease. - به جای
--forceاز--force-with-leaseاستفاده کنید تا روی کار جدید همکاران overwrite نکنید. - تنظیم pull:
# خطی نگه داشتن pull محلی
git config --global pull.rebase true
# یا فقط برای یک مخزن
git config pull.rebase true
- تعارضهای Rebase را مرحله به مرحله حل کنید و هر بار
git rebase --continueبزنید. برای رها کردن Rebase:git rebase --abort. - کامیتهای امضا شده یا ارجاع شده در issue tracker با Rebase بیاعتبار میشوند؛ در این شرایط Merge مطمئنتر است.
- در CI/CD ممکن است بازنویسی تاریخچه، buildهای اضافی یا گیجکنندگی ایجاد کند؛ سیاست تیمی مشخص تعریف کنید.
تصمیم سریع: کدام مناسبتر است؟
- در شاخه شخصی و قبل از انتشار: Rebase برای بهروزرسانی روی main و تمیز کردن تاریخچه.
- برای ادغام نهایی در شاخههای مشترک: Merge (یا Squash and merge) برای کاهش ریسک.
- اگر نیاز به ردیابی دقیق نقاط ادغام دارید: Merge commit.
- اگر تیم تاریخچه کاملا خطی در main میخواهد و همه با قواعد موافقند: «Rebase and merge» روی سرور، با انضباط بالا.
دو مثال کاربردی تکمیلی
پاکسازی تاریخچه قبل از PR با interactive rebase
git rebase -i HEAD~6
# pick اولین کامیت اصلی
# squash یا fixup برای کامیتهای ریز اصلاحی
# reword برای ویرایش پیام کامیت
خروجی: یک یا دو کامیت تمیز و قابل مرور. این کار را قبل از انتشار شاخه انجام دهید.
ادغام بدون fast-forward برای نگه داشتن «گِره ادغام»
git checkout main
git merge --no-ff feature/login -m "merge: feature/login"
این کار نشان میدهد این تغییرات یک بسته منسجم بودهاند.
ارتباط با ابزارهای تیمی
- GitHub/GitLab سه گزینه ارائه میدهند: Merge commit، Squash and merge، Rebase and merge. انتخاب را با توجه به سیاست تیم و حساسیت به تاریخچه انجام دهید.
- Protected branchها را طوری پیکربندی کنید که Rebase یا force-push ناخواسته روی main ممکن نباشد.
گام بعدی چیست؟
اگر میخواهید Git را نظاممندتر یاد بگیرید و این الگوها را تمرین کنید، مسیر آموزش گیت و گیت هاب نقطه شروع منظمی است. برای رفع اشکالهای تاریخچه یا یافتن کامیت خراب، آشنایی با ابزار bisect بسیار کمککننده است؛ راهنمای عملی را در آموزش Git Bisect: پیدا کردن سریع Commit خراب ببینید.
جمعبندی عملی: Rebase برای شاخههای شخصی و نظم تاریخچه، Merge برای همکاری ایمن در شاخههای عمومی. با این قانون ساده، هم تعارضها کمتر غافلگیرتان میکنند و هم تاریخچه پروژه قابل اتکاتر میماند.







