Rebase — این عملیاتی در Git است که کامیتها را از یک شاخه به بالای شاخه دیگر منتقل میکند و تاریخچه خطی بدون merge-commitهای اضافی ایجاد میکند. برخلاف ادغام، rebase تاریخچه را بازنویسی میکند: هر کامیت منتقلشده هش جدیدی دریافت میکند، زیرا والد آن تغییر میکند. به گفته مستندات Git (2026)، rebase برای همگامسازی شاخههای feature با وضعیت فعلی main قبل از ایجاد pull request استفاده میشود. دستور git rebase یکی از ابزارهای اصلی برای حفظ تاریخچه تمیز در پروژههایی است که از Git Flow استفاده میکنند.
نکات اصلی
Rebase — این دستوری در Git است که شاخه جاری را روی شاخه مشخصشده بازنشانی میکند: تمام کامیتهای شاخه جاری را میگیرد، موقتاً ذخیره میکند، اشارهگر شاخه را به کامیت هدف منتقل میکند و کامیتهای ذخیرهشده را بهصورت متوالی روی آن اعمال میکند. نتیجه — تاریخچه طوری به نظر میرسد که گویی توسعهدهنده مستقیماً از آخرین کامیت شاخه هدف کار کرده است.
سینتکس اصلی: git rebase main — وقتی در شاخه feature هستید، این دستور تمام کامیتهای feature را به بالای main منتقل میکند. Git برای هر کامیت جداگانه از استراتژی three-way merge استفاده میکند. اگر کامیت A از قبل در شاخه هدف وجود داشته باشد (با هش شناسایی میشود)، Git بهطور خودکار از آن عبور میکند که از تکراری شدن تغییرات جلوگیری میکند.
Rebase همچنین حالت onto را برای انتقال بخشی از کامیتها پشتیبانی میکند: git rebase --onto target start end — این فرم به شما امکان میدهد محدودهای از کامیتها را از یک شاخه استخراج کرده و روی شاخه دیگر اعمال کنید. به عنوان مثال، git rebase --onto main feature~3 feature سه کامیت آخر شاخه feature را به بالای main منتقل میکند.
# به شاخه feature بروید
git checkout feature
# Feature را روی main بازنشانی کنید
git rebase main
# پس از rebase موفق — تاریخچه خطی است
git log --oneline --graph
# 3 کامیت آخر را به main منتقل کنید
git rebase --onto main HEAD~3 HEAD
Rebase و merge یک کار را حل میکنند — ترکیب تغییرات از شاخههای مختلف — اما این کار را به روشهای اساساً متفاوتی انجام میدهند. Merge تاریخچه کامل ادغامها را با ایجاد merge-commit با دو والد حفظ میکند. Rebase تاریخچه را بازنویسی میکند و آن را خطی میکند. انتخاب بین آنها به گردش کار تیم و قوانین کار با مخزن بستگی دارد.
تفاوت اصلی — چگونگی ثبت واقعیت ادغام. Merge حفظ میکند: «در این نقطه feature را در main ادغام کردیم» — این برای تاریخچه پروژه informative است، اما در ادغامهای مکرر لاگ را شلوغ میکند. Rebase نشان میدهد: «کامیتهای feature بهصورت متوالی از آخرین وضعیت main انجام شدند» — این تمیز است، اما واقعیت موازی بودن کار را پنهان میکند.
تفاوت دوم — مدیریت تعارضات. در merge تعارضات یک بار حل میشوند و راهحل در merge-commit ثبت میشود. در rebase تعارضات ممکن است برای هر کامیت منتقلشده ایجاد شود و هر کدام نیاز به حل جداگانه دارند. این کار زمانبرتر است اما کنترل دقیقتری بر اینکه کدام تغییرات به نسخه نهایی وارد میشوند فراهم میکند.
| معیار | Rebase | Merge |
|---|---|---|
| تاریخچه | خطی، بدون merge-commit | غیرخطی، با merge-commit |
| هش کامیتها | بازنویسی میشوند (جدید) | اصلی حفظ میشوند |
| تعارضات | برای هر کامیت جداگانه | یک بار در merge-commit |
| شاخههای عمومی | ممنوع | مجاز |
| دستور لغو | git rebase --abort | git merge --abort |
Rebase تعاملی (git rebase -i) — حالتی است که Git ویرایشگری با لیست کامیتها و اقدامات موجود برای هر یک باز میکند. توسعهدهنده میتواند قبل از ارسال به مخزن راه دور تاریخچه را بازنویسی کند. این ابزار اصلی برای تمیز نگه داشتن کامیتها در شاخه feature است.
دستورات موجود در حالت تعاملی: pick (کامیت را به همان صورت نگه دار)، reword (پیام کامیت را تغییر بده)، edit (برای تغییرات توقف کن)، squash (با کامیت قبلی ادغام کن، هر دو پیام را حفظ کن)، fixup (با دور انداختن پیام ادغام کن)، drop (کامیت را حذف کن). هر دستور قبل از هش کامیت در ویرایشگر باز شده وارد میشود.
Squash و fixup — پرکاربردترین دستورات برای ترکیب کامیتها. اگر توسعهدهنده در حین کار 5 کامیت کوچک با اصلاحات انجام داده باشد، squash آنها را در یک کامیت منطقی با یک پیام معنادار ترکیب میکند. Fixup برای تصحیح غلطهای تایپی مفید است: تغییرات بدون ذخیره پیام خود وارد کامیت قبلی میشوند.
# ویرایشگر را برای 4 کامیت آخر باز کنید
git rebase -i HEAD~4
# ویرایشگر نشان خواهد داد:
pick a1b2c3d Add authentication
pick e4f5g6h Fix typo in login
squash i6j7k8l Additional login fixes
pick m9n0o1p Add auth tests
# پس از ذخیره — Git rebase را انجام میدهد
# و ویرایشگر را برای پیام کامیت ادغامشده باز میکند
# Auto-squash بدون باز کردن ویرایشگر
git rebase -i HEAD~4 --autosquash
پرچم --autosquash بهطور خودکار fixup/squash را برای کامیتهایی که پیامشان با fixup! یا squash! شروع میشود تنظیم میکند. این کار را در صورتی که توسعهدهنده از قبل کامیتها را برای ادغام بعدی علامتگذاری کند سرعت میبخشد. پرچم --committer-date-is-author-date تاریخ اصلی کامیت را در بازنشانی حفظ میکند — برای حفظ ترتیب زمانی در تاریخچه مفید است.
تعارضات هنگام rebase زمانی رخ میدهد که Git نمیتواند بهطور خودکار کامیت منتقلشده را به دلیل تضاد با تغییرات شاخه هدف اعمال کند. برخلاف merge که تعارض یک بار حل میشود، در rebase هر کامیت ممکن است باعث تعارض شود و باید برای هر کامیت از قدیمیترین به جدیدترین بهصورت متوالی حل شود.
وقتی تعارضی رخ میدهد، Git rebase را متوقف میکند و اعلام میکند کدام کامیت مشکل ایجاد کرده است. توسعهدهنده فایل دارای تعارض را باز میکند (Git بخشهای متعارض را با نشانگرهای <<<<<<<, =======, >>>>>>> مشخص میکند)، آن را ویرایش میکند، به ایندکس اضافه میکند (git add) و rebase را با دستور git rebase --continue ادامه میدهد. اگر راهحلی یافت نشد — git rebase --abort بهطور کامل بازنشانی را لغو میکند.
نکته: در تعارضات متعدد، استفاده از git mergetool که ویرایشگر بصری برای حل تضادها باز میکند مؤثرتر است. همچنین میتوان کامیت مشکلدار را رد کرد (git rebase --skip)، اما این تغییرات آن را از تاریخچه نهایی حذف میکند که به ندرت راهحل درستی است.
# شروع rebase با تعارض
git rebase main
# Auto-merging file.txt
# تعارض (محتوا): تعارض ادغام در file.txt
# بررسی وضعیت
git status
# هر دو تغییر یافته: file.txt
# بخشهای متعارض را ویرایش کنید → git add → ادامه دهید
git add file.txt
git rebase --continue
# در صورت تردید — لغو کنید
git rebase --abort
قاعده طلایی rebase: هرگز کامیتهایی را که قبلاً به مخزن راه دور ارسال شده و برای سایر توسعهدهندگان در دسترس هستند بازنشانی نکنید. از آنجا که rebase هش کامیتها را بازنویسی میکند، همکاران در تلاش برای همگامسازی با تعارض مواجه خواهند شد — تاریخچه محلی آنها با تاریخچه بازنویسیشده راه دور ناسازگار خواهد بود.
وضعیتی که rebase بهطور قطعی ممنوع است: اگر کسی قبلاً شاخهای بر اساس کامیتهای شما ایجاد کرده باشد (مثلاً همکارتان از feature شما یک feature ساخته باشد)، تغییر تاریخچه کار او را خراب میکند. در چنین مواردی باید از merge استفاده کرد. همچنین انجام rebase درست قبل از ددلاین توصیه نمیشود — اشتباه در حل تعارضات ممکن است بیش از حد انتظار وقت بگیرد و انتشار را مسدود کند.
استثنا: اگر شاخه فقط توسط یک توسعهدهنده استفاده میشود (شاخه feature شخصی، منتشرنشده یا منتشرشده در حالت draft)، rebase قبل از push یک روش استاندارد است. پس از انتشار و شروع کار گروهی — فقط merge. GitHub و GitLab بهطور پیشفرض squash merge را به عنوان یک راهحل میانی پیشنهاد میدهند: کامیتها را در یکی ادغام میکند اما تاریخچه شاخه هدف را بازنویسی نمیکند.
در تیمهای مدرن، بیشتر از گردش کار مبتنی بر rebase در ترکیب با GitHub Flow استفاده میشود. فرآیند به این صورت است: توسعهدهنده یک شاخه feature از main ایجاد میکند، در آن کار میکند، بهطور دورهای با git rebase main همگامسازی میکند و قبل از ایجاد pull request یک rebase تعاملی برای تمیز کردن تاریخچه انجام میدهد.
پس از ایجاد PR (در صورت نیاز به دریافت تغییرات جدید از main) به جای git pull معمولی از git pull --rebase main استفاده میشود. این امکان را فراهم میکند که تغییرات بدون ایجاد merge-commit اضافی دریافت شوند. Git pull با پرچم --rebase معادل git fetch + git rebase است — Git ابتدا کامیتهای جدید را بارگیری میکند، سپس تغییرات محلی را روی آنها بازنشانی میکند.
Git امکان تنظیم rebase به عنوان رفتار پیشفرض برای pull را فراهم میکند: git config --global pull.rebase true. پس از این تنظیم، git pull همیشه به جای merge از rebase استفاده میکند. اگر pull معمولی نیاز باشد — از git pull --no-rebase استفاده میشود. بسیاری از تیمها همچنین autostash را فعال میکنند: git config --global rebase.autoStash true — این بهطور خودکار تغییرات تأییدنشده را قبل از rebase پنهان میکند و پس از آن بازیابی میکند.
سوالات متداول
Rebase کردن — به معنای اجرای git rebase است: انتقال کامیتهای شاخه جاری به بالای شاخه دیگر. در نتیجه تاریخچه خطی میشود، هر کامیت هش جدیدی دریافت میکند و merge-commit ایجاد نمیشود. این دستور برای همگامسازی شاخهها بدون نقاط ادغام اضافی در لاگ استفاده میشود.
Merge یک merge-commit با دو والد ایجاد میکند، تاریخچه موازی و هشهای اصلی را حفظ میکند. Rebase تاریخچه را بازنویسی میکند — کامیتها هشهای جدیدی دریافت میکنند و تاریخچه خطی میشود. Merge برای شاخههای عمومی ایمنتر است، rebase لاگ تمیزتری ارائه میدهد.
دستور git rebase -i HEAD~N ویرایشگری با N کامیت آخر باز میکند. برای هر کامیت میتوان عملی را انتخاب کرد: pick (نگه دار)، reword (تغییر نام)، edit (تغییر)، squash (ادغام با قبلی)، fixup (ادغام بدون پیام)، drop (حذف). پس از ذخیره، Git تغییرات انتخابشده را اعمال میکند.
Rebase هش کامیتها را بازنویسی میکند، که تاریخچه را با کپیهای همان کامیتها در سایر توسعهدهندگان ناسازگار میکند. اگر همکاری قبلاً کامیتهای شما را از طریق git pull دریافت کرده باشد و شما بعداً آنها را بازنشانی کرده باشید، git push او رد میشود و git pull کامیتهای تکراری و تعارض ایجاد میکند.
قبل از اتمام — git rebase --abort کاملاً لغو میکند. پس از اتمام میتوان وضعیت قبلی را از طریق git reflog بازیابی کرد — هش کامیت قبل از rebase را پیدا کنید و git reset --hard را روی آن اجرا کنید. Reflog تاریخچه جابجاییهای HEAD را بهطور پیشفرض به مدت 30 روز نگه میدارد.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.