Rebase: چیست، تفاوت با Merge و اصل کار

نویسنده: IT Sectr منتشر شده: 2026-05-10 زمان مطالعه: 10 دقیقه

Rebase — عملیاتی در Git است که دنباله‌ای از commitها را به یک commit پایه جدید منتقل می‌کند و تاریخچه شاخه را بازنویسی می‌کند. برخلاف Merge، Rebase یک commit ادغام ایجاد نمی‌کند، بلکه commitها را روی وضعیت فعلی شاخه مقصد دوباره اعمال می‌کند. به گزارش git-scm.com، 2026، از rebase در 58% پروژه‌های Git برای حفظ تاریخچه commit خطی و تمیز استفاده می‌شود.

نکات اصلی

  • Rebase — commitها را به پایه جدید منتقل می‌کند و تاریخچه شاخه را بازنویسی می‌کند
  • تاریخچه خطی — مزیت اصلی rebase: git log بدون انشعاب خوانده می‌شود
  • نه برای شاخه‌های عمومی — rebase commitها را بازنویسی می‌کند که تاریخچه همکاران را خراب می‌کند
  • Interactive rebase امکان ترکیب، تغییر نام و حذف commitها را فراهم می‌کند
  • قانون طلایی: هرگز شاخه‌ای را که کسی قبلاً push کرده است rebase نکنید

Rebase چیست؟

Rebase (تغییر پایه) — عملیات Git است که commitها را از شاخه فعلی به یک نقطه مرجع جدید (پایه) منتقل می‌کند. به جای ایجاد commit ادغام، rebase هر commit را از شاخه مبدأ گرفته و به ترتیب روی پایه جدید اعمال می‌کند. نتیجه یک دنباله خطی از commitها بدون انشعاب است.

نام rebase از «re-base» — تغییر پایه گرفته شده است. اگر merge دو شاخه را در یک نقطه ترکیب کند، rebase در واقع کل شاخه شما را به مکان جدیدی منتقل می‌کند و این توهم را ایجاد می‌کند که کار را از وضعیت فعلی شاخه مقصد شروع کرده‌اید. این امر توهم کار کاملاً متوالی را ایجاد می‌کند.

به گزارش Atlassian، 2025، تیم‌هایی که از rebase برای شاخه‌های feature استفاده می‌کنند، 30% زمان کمتری برای تحلیل تاریخچه commit نسبت به تیم‌هایی که صرفاً از merge استفاده می‌کنند، صرف می‌کنند. تاریخچه خطی git blame، bisect و مشاهده لاگ از طریق git log --oneline را ساده می‌کند.

تفاوت اساسی با Merge

Merge شاخه‌ها را با ایجاد یک commit با دو والد ترکیب می‌کند. Rebase تاریخچه را بازنویسی می‌کند: commitهای جدید با hashهای جدید از نو ایجاد می‌شوند، اگرچه تغییرات در آنها با اصل یکسان است. این بدان معناست که rebase شناسه‌های SHA commitها را تغییر می‌دهد که برای شاخه‌های عمومی حیاتی است.

Rebase چگونه کار می‌کند

مکانیزم rebase از چهار مرحله تشکیل شده است: Git جد مشترک (merge base) شاخه فعلی و مقصد را تعیین می‌کند، سپس هر commit از شاخه فعلی را به ترتیب روی شاخه مقصد اعمال می‌کند. اگر در هر مرحله تعارضی رخ دهد — rebase متوقف می‌شود و منتظر حل آن می‌ماند.

bash
# وضعیت اولیه: feature از develop 3 commit عقب است
git checkout feature/new-login
git rebase develop

# Git 3 commit از feature می‌گیرد و آنها را روی develop اعمال می‌کند
# اگر تعارضی نباشد — rebase خودکار تمام می‌شود
# اگر باشد — Git روی commit مشکل‌دار متوقف می‌شود

پس از rebase، شاخه feature شامل تمام commitهای develop به اضافه commitهای خودش است که به نظر می‌رسد ادامه develop هستند. این امکان را فراهم می‌کند که بدون ایجاد commit ادغام، از طریق fast-forward در develop ادغام شود.

فرآیند گام به گام

مثال دقیق: توسعه‌دهنده یک شاخه feature از develop ایجاد کرد، دو commit انجام داد و در این مدت سایر توسعه‌دهندگان سه commit به develop اضافه کردند. Rebase دو commit feature را به مکان جدید منتقل می‌کند و کپی‌هایی با SHA جدید ایجاد می‌کند.

bash
# 1. ایجاد شاخه feature
git checkout -b feature/payment-refactor develop

# 2. انجام commit در feature
git commit -m "refactor: extract payment validation"
git commit -m "refactor: add payment gateway interface"

# 3. به‌روزرسانی develop (کار همکاران)
git checkout develop
git pull

# 4. بازنشانی feature روی develop جدید
git checkout feature/payment-refactor
git rebase develop

# 5. اکنون feature از طریق fast-forward قابل ادغام است
git checkout develop
git merge feature/payment-refactor

اگر در مرحله 4 تعارضی رخ دهد، Git روی commit مشکل‌دار متوقف می‌شود. توسعه‌دهنده تعارض را حل می‌کند، git add انجام می‌دهد و git rebase --continue را اجرا می‌کند. اگر نیاز به رد شدن از commit است — git rebase --skip، اگر لغو کل rebase — git rebase --abort.

رد شدن خودکار از commitهای خالی

پرچم --empty رفتار rebase را در commitهای خالی کنترل می‌کند — شرایطی که تمام تغییرات commit قبلاً در شاخه مقصد وجود دارد. به طور پیش‌فرض rebase متوقف می‌شود و درخواست تصمیم می‌کند. با پرچم --empty=drop، Git به طور خودکار چنین commitهایی را بدون توقف رد می‌کند که بازنشانی انبوه با تعداد زیادی commit را سرعت می‌بخشد.

Rebase تعاملی

Interactive rebase (git rebase -i) — ابزاری قدرتمند برای ویرایش تاریخچه commitها. این ابزار یک ویرایشگر با لیست commitها و دستورات کلیدی باز می‌کند: pick (نگه‌داشتن)، reword (تغییر پیام)، edit (تغییر محتوا)، squash (ترکیب با قبلی)، fixup (ترکیب بدون پیام)، drop (حذف).

bash
# rebase تعاملی 4 commit آخر
git rebase -i HEAD~4

# در ویرایشگر برنامه rebase باز می‌شود:
# pick a1b2c3 feat: add login screen
# pick d4e5f6 fix: login validation
# pick g7h8i9 fix: login layout
# pick j0k1l2 docs: add login comments

# تغییر می‌دهیم به:
# pick a1b2c3 feat: add login screen
# squash d4e5f6 fix: login validation
# squash g7h8i9 fix: login layout
# drop j0k1l2 docs: add login comments

نتیجه: سه commit (صفحه ورود، اعتبارسنجی، چیدمان) در یکی فشرده شدند و commit با توضیحات حذف شد. این امکان را فراهم می‌کند که یک تاریخچه تمیز بدون پیش‌نویس و اصلاحات برای بازبینی کد ارائه دهید. Interactive rebase ابزار استاندارد آماده‌سازی شاخه feature قبل از Pull Request است.

Rebase در مقابل Merge: مقایسه

Rebase و Merge یک وظیفه — ادغام تغییرات — را حل می‌کنند، اما به روش‌های اساساً متفاوت. انتخاب بین آنها بستگی به این دارد که چه نوع تاریخچه‌ای را می‌خواهید در git log ببینید و چه کسی دیگری با شاخه شما کار می‌کند.

معیارMergeRebase
تاریخچهانشعاب را حفظ می‌کندخطی، بدون شاخه
commit ادغامایجاد می‌شود (به جز ff)ایجاد نمی‌شود
SHA commitهاتغییر نمی‌کنندجدید ایجاد می‌شوند
ایمنیبرای شاخه‌های عمومی ایمنخطرناک — تاریخچه را بازنویسی می‌کند
خوانایی لاگگراف انشعابخط مستقیم
git bisectراحت — نقطه ادغام قابل مشاهده استراحت — دنباله خطی

قاعده عملی: برای ادغام در شاخه‌های مشترک (develop، main) از merge و برای به‌روزرسانی شاخه‌های شخصی feature به وضعیت فعلی از rebase استفاده کنید. بسیاری از تیم‌ها ترکیب می‌کنند: rebase feature روی develop، سپس --no-ff merge به develop.

تأثیر بر git bisect

Git bisect — ابزاری برای یافتن commitی که باعث پسرفت شده است. هنگام استفاده از merge، git bisect به درستی از commitهای ادغام با در نظر گرفتن هر دو والد عبور می‌کند. در rebase، bisect سریع‌تر کار می‌کند زیرا تاریخچه خطی است و نیازی به انشعاب ندارد. اما اگر rebase پس از آنکه commitها برای تیم شناخته شدند انجام شده باشد، SHAهای اصلی از بین می‌روند و bisect ممکن است commit مشکل‌دار را پیدا نکند.

چه زمانی از Rebase استفاده کنیم

Rebase در سه سناریو بهینه است: آماده‌سازی شاخه feature برای Pull Request، به‌روزرسانی شاخه شخصی به وضعیت فعلی main/develop و تمیز کردن تاریخچه قبل از ادغام. در هر مورد، rebase خوانایی تاریخچه را بدون خطر برای کار تیمی بهبود می‌بخشد.

قبل از Pull Request توصیه می‌شود interactive rebase را انجام دهید تا commitهای کاری (WIP، اصلاحات پس از بازبینی) را در واحدهای منطقی معنادار ترکیب کنید. این کار بازبینی کد را آسان‌تر می‌کند: بازبین به جای 15 commit کوچک، 3-5 تغییر ساختاریافته با پیام‌های قابل فهم می‌بیند.

برای به‌روزرسانی شاخه feature، rebase بر merge ترجیح داده می‌شود زیرا commitهای ادغام اضافی ایجاد نمی‌کند. اگر به طور دوره‌ای git rebase develop را در شاخه feature انجام دهید، پس از ادغام نهایی آبشاری از 10 commit ادغام وجود نخواهد داشت — فقط commitهای تمیز feature روی develop.

تمیز کردن تاریخچه از طریق interactive rebase قبل از ادغام به شما امکان می‌دهد اصلاحات جزئی (غلط املایی، قالب‌بندی) را پنهان کنید و commitها را بر اساس عملکرد گروه‌بندی کنید. پیام‌های Git باید طبق قرارداد Conventional Commits (fix:، feat:، refactor:، docs:) باشند که changelog خودکار تولید می‌کند.

ریسک‌ها و قوانین Rebase

Rebase — عملیات خطرناکی است اگر نادرست اعمال شود. ریسک اصلی — بازنویسی تاریخچه منتشر شده. اگر توسعه‌دهنده شاخه‌ای را که دیگران قبلاً push کرده و استفاده می‌کنند rebase کند، نسخه‌های محلی آنها از همگام‌سازی خارج می‌شوند و مجبور به انجام force-pull با خطر از دست دادن داده‌ها می‌شوند.

  • قانون طلایی: هرگز commitهایی را که قبلاً در مخزن مشترک وجود دارند rebase نکنید. این به هر شاخه‌ای که سایر اعضای تیم به آن دسترسی دارند مربوط می‌شود
  • Force push: پس از rebase شاخه محلی feature، push با پرچم --force-with-lease لازم است که از --force ایمن‌تر است زیرا بررسی می‌کند آیا کسی شاخه را روی سرور به‌روز کرده است
  • از دست دادن زمینه: rebase اطلاعات مربوط به زمان و از چه شاخه‌ای feature ایجاد شده را از بین می‌برد. اگر حفظ تاریخ ایجاد شاخه مهم است — از merge استفاده کنید
  • تعارضات: در rebase، تعارضات باید برای هر commit جداگانه حل شوند که می‌تواند با تعداد زیاد commit خسته‌کننده باشد

برای به حداقل رساندن ریسک‌ها، قانون زیر را رعایت کنید: rebase فقط برای شاخه‌های شخصی که منتشر نشده‌اند. اگر شاخه قبلاً در مخزن مشترک است — از merge با --no-ff استفاده کنید. در صورت نیاز به rebase شاخه منتشر شده — تیم را مطلع کنید و force push را از قبل هماهنگ کنید.

حفاظت خودکار در برابر rebase خطرناک از طریق server-side hooks پیاده‌سازی می‌شود: pre-receive hook در سمت سرور Git می‌تواند بررسی کند که آیا push commitهای منتشر شده را بازنویسی می‌کند. GitHub و GitLab حفاظت داخلی برای شاخه‌های محافظت شده ارائه می‌دهند — force push مسدود می‌شود مگر اینکه حفاظت توسط مدیر لغو شود.

سوالات متداول

اگر rebase یک شاخه عمومی انجام دهم چه اتفاقی می‌افتد؟

تاریخچه شاخه تغییر می‌کند — SHA commitها متفاوت می‌شوند. هر کسی که قبلاً این شاخه را push کرده یا شاخه‌های فرزند از آن ایجاد کرده است، هنگام git pull با تعارضات مواجه می‌شود. بازیابی نیاز به مداخله دستی دارد و می‌تواند منجر به از دست دادن commitها شود.

آیا می‌توان rebase را لغو کرد؟

قبل از اتمامgit rebase --abort. پس از اتمام — فقط از طریق git reflog، اگر rebase اخیراً انجام شده باشد. reflog تاریخچه جابجایی‌های HEAD را ذخیره می‌کند که با آن می‌توان به وضعیت قبل از rebase بازگشت: git reset --hard HEAD@{1}.

تفاوت rebase و cherry-pick چیست؟

Rebase دنباله commitها را به پایه جدید منتقل می‌کند. Cherry-pick یک یا چند commit خاص را در شاخه فعلی اعمال می‌کند. Rebase برای کل زنجیره خودکار است، cherry-pick — انتخاب دستی هر commit.

آیا قبل از هر Pull Request باید rebase انجام داد؟

توصیه می‌شود، اما اجباری نیست. Rebase قبل از PR شاخه را به وضعیت فعلی main/develop به‌روز می‌کند و تاریخچه را تمیز می‌کند. اگر شاخه اخیراً ایجاد شده و نیازی به به‌روزرسانی ندارد — interactive rebase برای تمیز کردن commitها کافی است.

rebase چه تأثیری بر برچسب‌ها دارد؟

برچسب‌ها در rebase جابجا نمی‌شوند. اگر روی commitی که rebase شده است برچسبی وجود داشت، این برچسب روی commit قدیمی که اکنون در تاریخچه شاخه نیست باقی می‌ماند. توصیه می‌شود commitهای شاخه‌های feature را برچسب‌گذاری نکنید، فقط در main.

خلاصه

  • Rebase — بازنشانی commitها به پایه جدید با ایجاد تاریخچه خطی
  • برخلاف Merge commit ادغام ایجاد نمی‌کند و SHA commitها را بازنویسی می‌کند
  • Interactive rebase امکان فشرده‌سازی، تغییر نام و حذف commitها را فراهم می‌کند
  • قانون طلایی: فقط شاخه‌های شخصی را rebase کنید، هرگز شاخه‌های عمومی را
  • پس از rebase force push لازم است (ترجیحاً --force-with-lease)
  • برای Pull Request توصیه می‌شود rebase + تمیز کردن تاریخچه با -i
  • رویکرد ترکیبی: rebase برای به‌روزرسانی شاخه feature، --no-ff merge برای تثبیت

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید