rebase در برابر merge؛ کِی از کدام استفاده کنیم
آموزش

rebase در برابر merge؛ کِی از کدام استفاده کنیم

rebase و merge هر دو دو شاخه را یکی می‌کنند، ولی یکی‌شان تاریخچه را بازنویسی می‌کند و دیگری هیچ کامیتی را دست نمی‌زند

تحریریه‌ی دینا کد
نویسنده
۴ دقیقه مطالعه۶ بازدید
اشتراک گذاری۶
فهرست مطالب
  1. ۱یک تاریخچه‌ی واقعی
  2. ۲با merge هر دو تاریخچه کنار هم می‌مانند
  3. ۳با rebase تاریخچه صاف می‌شود ولی کامیت‌ها عوض می‌شوند
  4. ۴چرا همین تفاوت، قانونِ «rebase نزن روی شاخه‌ی push‌شده» را می‌سازد
  5. ۵قانون عملی

جواب را همین اول بدهم: روی شاخه‌ای که هنوز push نکرده‌اید یا کسی دیگر رویش کار نمی‌کند، rebase بزنید تا تاریخچه صاف بماند؛ روی شاخه‌ای که با بقیه مشترک است، فقط merge بزنید. تفاوتشان در همین یک چیز است: rebase کامیت‌های شما را دوباره می‌سازد؛ merge هیچ کامیتی را دست نمی‌زند.

یک تاریخچه‌ی واقعی

دو شاخه از یک نقطه جدا شده‌اند: main یک کامیت مستندات دارد، feature دو کامیت کد دارد.

bash$ git log --oneline --graph --all
* 98962d6 به‌روزرسانی مستندات
| * 6789051 افزودن logout
| * 712f76d افزودن login
|/  
* 467df03 کامیت پایه

با merge هر دو تاریخچه کنار هم می‌مانند

bash$ git checkout feature
$ git merge main
$ git log --oneline --graph --all
*   221d4b7 Merge branch 'main' into feature
|\  
| * 98962d6 به‌روزرسانی مستندات
* | 6789051 افزودن logout
* | 712f76d افزودن login
|/  
* 467df03 کامیت پایه

یک کامیت جدید (221d4b7) با دو والد ساخته شد. کامیت‌های login و logout دقیقاً همان هش قبلی را دارند؛ هیچ‌چیزی بازنویسی نشده و فقط یک نقطه‌ی اتصال اضافه شده.

با rebase تاریخچه صاف می‌شود ولی کامیت‌ها عوض می‌شوند

bash$ git checkout feature
$ git rebase main
$ git log --oneline --graph --all
* f8755f5 افزودن logout
* db44f8e افزودن login
* 98962d6 به‌روزرسانی مستندات
* 467df03 کامیت پایه

نتیجه یک خط راست می‌شود؛ انگار از اول روی main کار کرده بودید. ولی نگاه کنید به هش‌ها: login از 712f76d شد db44f8e، logout از 6789051 شد f8755f5. این‌ها کامیت‌های جدیداند با همان محتوا؛ کامیت‌های قبلی دیگر روی این شاخه نیستند. کامیت‌های خود main هم دست‌نخورده مانده‌اند؛ هش 98962d6 قبل و بعد از rebase یکی است.

چرا همین تفاوت، قانونِ «rebase نزن روی شاخه‌ی push‌شده» را می‌سازد

چون هش عوض شده، اگر همین شاخه را قبلاً push کرده باشید، push دوباره‌ی معمولی رد می‌شود:

bash$ git push origin feature
To ../project.git
 ! [rejected]        feature -> feature (non-fast-forward)
error: failed to push some refs to '../project.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

گیت شاخه‌ی remote را جلوتر از شاخه‌ی شما می‌بیند، چون کامیت‌های قدیمی هنوز آن‌جا هستند و شما دارید یک تاریخچه‌ی متفاوت با همان اسم می‌فرستید. hint پیشنهاد می‌دهد pull کنید، ولی این‌جا pull کردن تاریخچه‌ی قدیمی را دوباره وارد ماجرا می‌کند. تنها راه، push --force (یا امن‌ترش، --force-with-lease) است؛ اگر همکارتان همان کامیت‌های قدیمی را pull کرده باشد، کارش روی تاریخچه‌ای می‌ماند که دیگر وجود ندارد.

قانون عملی

وضعیت انتخاب
شاخه‌ی شخصی، هنوز push نشده rebase؛ تاریخچه تمیزتر می‌ماند
شاخه‌ای که دیگران هم رویش کار می‌کنند فقط merge
می‌خواهید commit-by-commit مرور کنید rebase قبل از باز کردن PR
مطمئن نیستید کسی دیگر pull کرده یا نه merge؛ همیشه امن است

اگر مطمئن نیستید، merge بزنید. یک کامیت merge اضافه در تاریخچه، خیلی کمتر از یک تاریخچه‌ی بازنویسی‌شده روی شاخه‌ی مشترک هزینه دارد.

اگر می‌خواهید کار تیمی روی گیت‌هاب را با پروژه‌ی واقعی تمرین کنید، دوره‌ی گیت و گیت‌هاب همین سناریوها را از شاخه و pull request تا حل تعارض، چند بار زیر دستتان می‌برد. معرفیِ کامل‌تر تعارض‌ها هم در پستِ چطور تعارض در Merge گیت را حل کنیم آمده است.

تحریریه‌ی دینا کد
نویسنده

نظرها

اولین نفری باشید که نظر می‌دهد
برای ثبت نظر وارد شوید

سؤالتان را بپرسید یا تجربه‌تان را بنویسید تا نویسنده‌ی مطلب پاسخ بدهد.

مطالب مرتبط

از همین دسته
دستور stash در گیت چیست و چه کاربردی دارد
آموزش

دستور stash در گیت چیست و چه کاربردی دارد

دستور stash در گیت تغییرات ثبت‌نشده شاخه کاری را موقتا کنار می‌گذارد تا بدون ثبت کامیت ناقص بتوانید روی وظایف فوری کار کنید.

تحریریه‌ی دینا کد۶ دقیقه
diff در گیت چیست و چه‌وقت استفاده می‌شود؟
آموزش

diff در گیت چیست و چه‌وقت استفاده می‌شود؟

git diff دو نسخه از کدها را کنار هم می‌گذارد و خط‌به‌خط نشان می‌دهد چه چیزی عوض شده. یک نگاه به diff قبل از هر add و commit کافی است

تحریریه‌ی دینا کد۷ دقیقه