Rebase هي عملية في Git تنقل الـ commits من فرع إلى قمة فرع آخر، مما ينشئ تاريخًا خطيًا بدون commits merge غير ضرورية. على عكس الدمج، يعيد rebase كتابة التاريخ: كل commit منقول يحصل على تجزئة جديدة لأن والده يتغير. وفقًا لوثائق Git (2026)، يُستخدم rebase لمزامنة فروع الميزات مع أحدث حالة لـ main قبل إنشاء طلب سحب. أمر git rebase هو أحد الأدوات الرئيسية للحفاظ على تاريخ نظيف في المشاريع التي تستخدم Git Flow.
النقاط الرئيسية
Rebase هو أمر Git يعيد توجيه الفرع الحالي إلى فرع محدد: يأخذ جميع commits الفرع الحالي، يحفظها مؤقتًا، ينقل مؤشر الفرع إلى commit الهدف، ويطبق الـ commits المحفوظة تباعًا فوقه. النتيجة — يبدو التاريخ كما لو أن المطور عمل مباشرة من آخر commit للفرع الهدف.
الصيغة الأساسية: git rebase main — أثناء وجودك في فرع ميزات، هذا الأمر ينقل جميع commits الفرع إلى قمة main. يستخدم Git استراتيجية الدمج ثلاثي الاتجاه لكل commit على حدة. إذا كان commit A موجودًا بالفعل في الفرع الهدف (يُحدد بالتجزئة)، يتخطاه Git تلقائيًا، متجنبًا التغييرات المكررة.
يدعم Rebase أيضًا وضع onto لنقل مجموعة جزئية من الـ commits: git rebase --onto target start end — هذه الصيغة تسمح باستخراج نطاق من الـ commits من فرع وتطبيقها فوق فرع آخر. على سبيل المثال، git rebase --onto main feature~3 feature ينقل آخر ثلاثة commits من فرع feature فوق main.
# Switch to feature branch
git checkout feature
# Rebase feature onto main
git rebase main
# After successful rebase — history is linear
git log --oneline --graph
# Move last 3 commits to main
git rebase --onto main HEAD~3 HEAD
Rebase و merge يحلان نفس المهمة — دمج التغييرات من فروع مختلفة — لكنهما يفعلان ذلك بطرق مختلفة جوهريًا. Merge يحافظ على تاريخ الدمج الكامل عن طريق إنشاء commit merge بوالدين. Rebase يعيد كتابة التاريخ، مما يجعله خطيًا. يعتمد الاختيار بينهما على سير عمل الفريق وقواعد إدارة المستودع.
الفرق الرئيسي هو كيفية تسجيل حقيقة الدمج. Merge يحافظ: «في هذه النقطة دمجنا feature في main» — هذا مفيد لتاريخ المشروع لكنه يثقل السجل بعمليات دمج متكررة. Rebase يظهر: «تم عمل commits feature تباعًا من آخر حالة لـ main» — هذا نظيف لكنه يخفي حقيقة أن التطوير تم بالتوازي.
الفرق الثاني هو معالجة التعارضات. مع merge، تُحل التعارضات مرة واحدة ويُسجل الحل في commit merge. مع rebase، يمكن أن تنشأ تعارضات لكل commit منقول، وكل منها يتطلب حلاً منفصلاً. هذا أكثر استهلاكًا للوقت لكنه يتيح تحكمًا أدق في التغييرات التي تصل إلى النسخة النهائية.
| المعيار | Rebase | Merge |
|---|---|---|
| التاريخ | خطي، بدون commits merge | غير خطي، مع commits merge |
| تجزئات commits | تُعاد كتابتها (جديدة) | تُحفظ الأصلية |
| التعارضات | لكل commit على حدة | مرة واحدة في commit merge |
| الفروع العامة | محظور | مسموح |
| أمر التراجع | git rebase --abort | git merge --abort |
Rebase التفاعلي (git rebase -i) هو وضع يفتح فيه Git محررًا بقائمة من الـ commits والإجراءات المتاحة لكل منها. يمكن للمطور إعادة كتابة التاريخ قبل الإرسال إلى مستودع بعيد. هذه هي الأداة الرئيسية للحفاظ على commits نظيفة في فرع الميزات.
الأوامر المتاحة في الوضع التفاعلي: pick (إبقاء commit كما هو)، reword (تغيير رسالة commit)، edit (التوقف للتغيير)، squash (الدمج مع commit السابق مع الاحتفاظ بكلتا الرسالتين)، fixup (الدمج مع تجاهل الرسالة)، drop (حذف commit). يوضع كل أمر قبل تجزئة commit في المحرر المفتوح.
Squash و fixup هما الأمران الأكثر استخدامًا لدمج الـ commits. إذا قام المطور بعمل 5 commits صغيرة للتصحيح أثناء العمل، squash يدمجها في commit منطقي واحد برسالة ذات معنى. Fixup مفيد لتصحيح الأخطاء المطبعية: تذهب التغييرات إلى commit السابق دون الاحتفاظ برسالتها الخاصة.
# Open editor for last 4 commits
git rebase -i HEAD~4
# Editor will show:
pick a1b2c3d Add authentication
pick e4f5g6h Fix typo in login
squash i6j7k8l Additional login fixes
pick m9n0o1p Add auth tests
# After saving — Git performs rebase
# and opens editor for squashed commit message
# Auto-squash without opening editor
git rebase -i HEAD~4 --autosquash
العلم --autosquash يرتب تلقائيًا fixup/squash للـ commits التي تبدأ رسائلها بـ fixup! أو squash!. هذا يُسرع العمل إذا كان المطور يحدد الـ commits مسبقًا للدمج لاحقًا. العلم --committer-date-is-author-date يحافظ على تاريخ commit الأصلي عند إعادة التوجيه — مفيد للحفاظ على الترتيب الزمني في التاريخ.
التعارضات أثناء rebase تحدث عندما لا يستطيع Git تطبيق commit منقول تلقائيًا بسبب تعارض مع التغييرات في الفرع الهدف. على عكس merge، حيث يُحل التعارض مرة واحدة، مع rebase يمكن لكل commit أن يسبب تعارضًا، ويجب حله تباعًا لكل commit من الأقدم إلى الأحدث.
عند حدوث تعارض، Git يوقف rebase ويُبلغ عن commit الذي تسبب بالمشكلة. يفتح المطور الملف المتعارض (يحدد Git مناطق التعارض بعلامات <<<<<<<, =======, >>>>>>>)، يحرره، يضيفه إلى الفهرس (git add)، ويواصل rebase بأمر git rebase --continue. إذا لم يُوجد حل — git rebase --abort يلغي rebase بالكامل.
نصيحة: مع تعارضات متعددة، من الأكثر فعالية استخدام git mergetool، الذي يفتح محررًا مرئيًا لحل التعارضات. يمكن أيضًا تخطي commit المشكل (git rebase --skip)، لكن هذا يزيل تغييراته من التاريخ النهائي، وهو نادرًا ما يكون القرار الصحيح.
# Start rebase with conflict
git rebase main
# Auto-merging file.txt
# CONFLICT (content): Merge conflict in file.txt
# Check status
git status
# both modified: file.txt
# Edit conflicted sections → git add → continue
git add file.txt
git rebase --continue
# If uncertain — abort
git rebase --abort
القاعدة الذهبية لـ rebase: لا تعيد توجيه commits تم إرسالها بالفعل إلى مستودع بعيد ومتاحة لمطورين آخرين. نظرًا لأن rebase يعيد كتابة تجزئات commits، سيواجه الزملاء تعارضات عند محاولة المزامنة — سيتعارض تاريخهم المحلي مع التاريخ البعيد المعاد كتابته.
موقف يكون فيه rebase محظورًا تمامًا: إذا كان شخص ما قد أنشأ بالفعل فرعًا بناءً على commits الخاصة بك (على سبيل المثال، زميل أنشأ فرعًا من فرع الميزات الخاص بك)، إعادة كتابة التاريخ ستعطل عمله. في هذه الحالات، استخدم merge. كما لا يُنصح بعمل rebase قبل موعد التسليم مباشرة — خطأ في حل التعارضات قد يستغرق وقتًا أطول من المتوقع ويعطل الإصدار.
استثناء: إذا كان الفرع يستخدمه مطور واحد فقط (فرع ميزات شخصي، غير منشور أو منشور في وضع المسودة)، rebase قبل الدفع هو ممارسة قياسية. بعد النشر وبدء العمل الجماعي — فقط merge. تقدم GitHub و GitLab افتراضيًا squash merge كحل وسط: يدمج commits في واحد لكنه لا يعيد كتابة تاريخ الفرع الهدف.
تستخدم الفرق الحديثة غالبًا سير عمل موجه نحو rebase مع GitHub Flow. تبدو العملية كالتالي: ينشئ المطور فرع ميزات من main، يعمل فيه، يتزامن دوريًا عبر git rebase main، وقبل إنشاء طلب سحب يقوم بـ rebase تفاعلي لتنظيف التاريخ.
بعد إنشاء PR (إذا لزم الأمر سحب تغييرات جديدة من main)، يُستخدم git pull --rebase main بدلاً من git pull العادي. هذا يسحب التغييرات دون إنشاء commit merge غير ضروري. Git pull مع العلم --rebase يعادل git fetch + git rebase — يقوم Git أولاً بتنزيل commits جديدة، ثم يعيد توجيه التغييرات المحلية فوقها.
يسمح Git بتكوين rebase كسلوك افتراضي لـ pull: git config --global pull.rebase true. بعد هذا الإعداد، git pull دائمًا ينفذ rebase بدلاً من merge. إذا لزم الأمر pull عادي — يُستخدم git pull --no-rebase. العديد من الفرق تفعل autostash أيضًا: git config --global rebase.autoStash true — هذا يخفي تلقائيًا التغييرات غير الملتزمة قبل rebase ويعيدها بعده.
الأسئلة الشائعة
إعادة التأسيس تعني تنفيذ git rebase: نقل commits الفرع الحالي إلى قمة فرع آخر. النتيجة — يصبح التاريخ خطيًا، كل commit يحصل على تجزئة جديدة، ولا تُنشأ commits merge. يُستخدم الأمر لمزامنة الفروع دون نقاط دمج غير ضرورية في السجل.
Merge ينشئ commit merge بوالدين، محافظًا على التاريخ المتوازي والتجزئات الأصلية. Rebase يعيد كتابة التاريخ — تحصل commits على تجزئات جديدة ويصبح التاريخ خطيًا. Merge أكثر أمانًا للفروع العامة، rebase يعطي سجلاً أنظف.
أمر git rebase -i HEAD~N يفتح محررًا بآخر N commits. لكل commit يمكن اختيار إجراء: pick (إبقاء)، reword (إعادة تسمية)، edit (تعديل)، squash (دمج مع السابق)، fixup (دمج بدون رسالة)، drop (حذف). بعد الحفظ، يطبق Git التغييرات المختارة.
Rebase يعيد كتابة تجزئات commits، مما يجعل التاريخ غير متوافق مع نسخ نفس commits على أجهزة المطورين الآخرين. إذا كان زميل قد حصل بالفعل على commits الخاصة بك عبر git pull، ثم قمت بإعادة توجيهها، سيتم رفض git push الخاص به، وسينشئ git pull commits مكررة وتعارضات.
قبل الاكتمال — git rebase --abort يلغي بالكامل. بعد الاكتمال، يمكن استعادة الحالة السابقة عبر git reflog — العثور على تجزئة commit قبل rebase وتنفيذ git reset --hard إليه. Reflog يخزن تاريخ حركات HEAD لمدة 30 يومًا افتراضيًا.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.