Cherry-pick: ما هو، كيفية تنفيذه وأوامر Git

المؤلف: IT Sectr نُشر: 2026-08-01 وقت القراءة: 8 دق

Cherry-pick هو أمر Git يطبق التغييرات من التزام محدد على الفرع الحالي دون نقل التاريخ الكامل للفرع المصدر. على عكس merge أو rebase، يعمل cherry-pick مع كل التزام على حدة: يختار المطور التزاماً معيناً بواسطة hash الخاصة به وينقل تغييراته فقط. وفقاً لتوثيق Git (2026)، فإن cherry-pick مفيد بشكل خاص للنقل الموجه للإصلاحات بين فروع الإصدار عندما يكون الدمج الكامل مفرطاً أو محفوفاً بالمخاطر. يقوم الأمر بإنشاء التزام جديد مع hash جديدة، لكنه يحتفظ بالرسالة الأصلية والمؤلف.

الخلاصة

  • Cherry-pick — نقل التزام فردي من فرع إلى آخر بواسطة hash الخاصة به.
  • Hash جديدة — كل cherry-pick ينشئ التزاماً جديداً مع التغييرات المنسوخة من الأصل.
  • التزامات متعددة في وقت واحد — git cherry-pick A B C ينقل الالتزامات المحددة بالتسلسل.
  • فروع الإصدار — السيناريو الرئيسي: نقل إصلاح الخلل من develop إلى release بدون كود غير ضروري.
  • الصراعات ممكنة — عند تطبيق التزام، قد يطلب Git حل الصراعات.

ما هو cherry-pick في Git

Cherry-pick هو أمر git cherry-pick الذي يأخذ التغييرات من التزام موجود ويطبقها كالتزام جديد في الفرع الحالي. يبقى الالتزام الأصلي في مكانه في فرعه الخاص، بينما يتم إنشاء نسخة من التغييرات في الفرع الهدف. الأمر مفيد عندما تحتاج إلى نقل إصلاح محدد دون نقل فرع كامل.

الصيغة: git cherry-pick <commit-hash>. يحلل Git الفرق (diff) للالتزام المحدد مع والده ويطبق هذا الفرق على الفرع الحالي. إذا تم تغيير عدة ملفات، يتم نقلها جميعاً معاً. يقبل الأمر أيضاً نطاقات: git cherry-pick A..B — جميع الالتزامات من A إلى B، باستثناء A.

الخيارات توسع الإمكانيات: -n (--no-commit) يطبق التغييرات على دليل العمل والفهرس دون إنشاء التزام — مفيد عندما تحتاج إلى دمج تغييرات عدة التزامات في التزام واحد. الخيار -x يضيف سطراً (cherry picked from commit ...) إلى رسالة الالتزام، مما يسهل تتبع أصل التغييرات في التاريخ.

bash
# تطبيق cherry-pick على التزام واحد بواسطة hash
git cherry-pick a1b2c3d

# تطبيق cherry-pick على التزامات متعددة (بالتسلسل)
git cherry-pick a1b2c3d e4f5g6h i6j7k8l

# تطبيق cherry-pick بدون التزام تلقائي
git cherry-pick -n a1b2c3d

# الخيار -x يضيف مرجعاً للالتزام الأصلي
git cherry-pick -x a1b2c3d

متى يُستخدم cherry-pick

السيناريو الرئيسي هو نقل الإصلاحات بين فروع الإصدار. تخيل: تم العثور على خطأ حاسم وإصلاحه في develop. فرع الإصدار release/v2.1 مفصول بالفعل ويحتوي أيضاً على هذا الخطأ. دمج develop بالكامل في release سيجلب الكثير من الكود غير المكتمل، بينما تطبيق cherry-pick على التزام الإصلاح الواحد هو حل آمن ودقيق.

السيناريو الثاني هو عكس التغييرات مع الاستعادة لاحقاً. إذا تم عكس التزام عبر git revert واتضح لاحقاً أن العكس كان خطأ — فإن تطبيق cherry-pick على الالتزام المعكوس يستعيد التغييرات. هذا أكثر صحة من عكس العكس لأنه لا ينشئ صراعات متكررة.

السيناريو الثالث هو دمج الالتزامات من فروع ميزات مختلفة في فرع اختبار واحد لاختبار التكامل. بدلاً من دمج عدة فروع غير مكتملة (مع كود غير منتهٍ)، يمكن اختيار الالتزامات الجاهزة فقط من كل منها واختبار كيفية عملها معاً.

  • إصلاحات الأخطاء — نقل إصلاح من develop إلى release بدون كود غير مكتمل.
  • Hotfix — تطبيق إصلاح من فرع hotfix إلى main و develop في وقت واحد.
  • إلغاء عكس خاطئ — تطبيق cherry-pick على الالتزام المعكوس لاستعادة التغييرات.
  • الاختبار — جمع التزامات محددة من فروع مختلفة لاختبار التكامل.

Cherry-pick مقابل rebase و merge

Cherry-pick يختلف عن rebase و merge في أنه يعمل على مستوى الالتزامات الفردية بدلاً من الفروع بأكملها. بينما rebase ينقل جميع التزامات الفرع و merge يدمج فرعين، cherry-pick يختار فقط ما هو مطلوب. وهذا يجعله أداة أكثر دقة، ولكنها أيضاً أكثر يدوية.

فرق آخر هو التأليف. أثناء cherry-pick، يحتفظ Git افتراضياً بمؤلف الالتزام الأصلي، ولكن committer يصبح المستخدم الحالي. يمكن تتبع أصل الالتزام في الرسالة عبر الخيار -x. أثناء rebase، يصبح كل من المؤلف و committer المستخدم الحالي مع hash جديدة.

الأداء: تطبيق cherry-pick على التزام واحد أسرع من دمج فرعين مع العديد من الالتزامات. ولكن إذا كنت بحاجة إلى نقل عشرات الالتزامات، فمن الأفضل إنشاء فرع مؤقت وتنفيذ rebase — سيكون أكثر كفاءة ولن يتطلب تحديد عشرات الهاشات.

العمليةالنطاقالآثار الجانبية
Cherry-pickالتزامات فرديةHash جديدة، تكرار الكود
Rebaseجميع التزامات الفرعإعادة كتابة التاريخ، هاشات جديدة
Mergeدمج كامل للفروعالتزام دمج، حفظ التاريخ

نقل التزامات متعددة

التزامات متعددة يمكن نقلها بأمر واحد عن طريق سرد هاشاتها مفصولة بمسافات: git cherry-pick A B C. يطبق Git الالتزامات بالتسلسل بالترتيب المحدد. إذا تسبب أي التزام في صراع، يتوقف cherry-pick، ويجب على المطور حل الصراع، ثم المتابعة بـ git cherry-pick --continue.

نطاق الالتزامات: git cherry-pick A..B (جميع الالتزامات بعد A حتى B، باستثناء A) و git cherry-pick A^..B (جميع الالتزامات من A شاملاً حتى B). النطاقات مفيدة عندما تحتاج إلى نقل جميع الالتزامات من فرع دون علاقة الوالد — على سبيل المثال، عند نقل ميزة مكتملة من فرع قديم إلى فرع جديد.

الخيار --strategy يحدد كيف يطبق Git التغييرات. افتراضياً، تُستخدم استراتيجية recursive، ولكن يمكن تحديد ours أو theirs لاختيار جانب الصراع تلقائياً. الخيار --mainline يُستخدم عند تطبيق cherry-pick على التزام دمج — يحدد رقم الوالد (1 أو 2) الذي يتم حساب الفرق بناءً عليه.

bash
# نطاق التزامات cherry-pick
git cherry-pick develop~5..develop~2

# تطبيق cherry-pick على التزام دمج (تحديد الوالد)
git cherry-pick -m 1 m9n0o1p

# استخدام استراتيجية theirs
git cherry-pick --strategy=recursive \
  --strategy-option=theirs a1b2c3d

# المتابعة بعد حل الصراع
git cherry-pick --continue

الصراعات أثناء cherry-pick

الصراعات أثناء cherry-pick تحدث عندما تؤثر تغييرات الالتزام المنقول على نفس الأسطر التي تم تغييرها في الفرع الهدف. يوقف Git التنفيذ، ويضع علامة على الملفات المتعارضة، وينتظر الحل. في الحالة، تظهر هذه الملفات كـ both modified.

خطوات حل الصراع: افتح الملف المتعارض، ابحث عن علامات الصراع (<<<<<<<، =======، >>>>>>>)، حرر المحتوى، أزل العلامات، نفذ git add للملفات التي تم حلها، ونفذ git cherry-pick --continue. إذا تعذر حل الصراع — git cherry-pick --abort يلغي عملية cherry-pick بأكملها، ويعيد الفرع إلى حالته الأصلية.

مشكلة شائعة: الالتزام يحتوي بالفعل على تغييرات مكافئة للموجودة. في هذه الحالة، يبلغ Git عن «nothing to commit» أو «empty commit» عند محاولة cherry-pick. الخياران --keep-redundant-commits و --empty=keep يجبران Git على إنشاء التزام فارغ للحفاظ على التسلسل، بينما --skip يسمح بتخطي مثل هذا الالتزام.

bash
# صراع أثناء cherry-pick — توقف
git cherry-pick a1b2c3d
# error: لا يمكن تطبيق a1b2c3d... رسالة الالتزام

# حل الصراع → إضافة إلى الفهرس
git add src/conflicted_file.swift
git cherry-pick --continue

# تخطي التزام فارغ (مطبق بالفعل)
git cherry-pick --skip

# إلغاء كامل
git cherry-pick --abort

أفضل ممارسات cherry-pick

القاعدة الأولى: تحقق دائماً من أن الالتزام المنقول مكتفي بذاته. إذا كان الالتزام A يعتمد على تغييرات في الالتزام B الذي لا يُنقل، فإن تطبيق cherry-pick على A قد يكسر البناء. قبل تطبيق cherry-pick، من المفيد التحقق من الملفات التي غيرها الالتزام عبر git show --stat <hash>.

القاعدة الثانية: وثق عمليات cherry-pick. استخدم الخيار -x لتحتفظ رسالة الالتزام بمرجع إلى الالتزام الأصلي. سيساعد هذا أثناء التحليل اللاحق للتاريخ في فهم مصدر التغيير. بدون -x، يبدو cherry-pick كالتزام عادي، ولا يمكن تحديد أصله إلا عبر git log --graph.

القاعدة الثالثة: تجنب cherry-pick بين الفروع التي تباعدت كثيراً. إذا مر وقت طويل منذ إنشاء الالتزام وتغيرت قاعدة الكود بشكل كبير، ستكون الصراعات عديدة ومعقدة. في مثل هذه الحالات، من الأفضل إعادة تنفيذ الإصلاح في الفرع الهدف — سيستغرق وقتاً أقل من حل عشرات الصراعات.

  • Cherry-pick فقط الالتزامات المكتفية بذاتها دون تبعيات خارجية.
  • الخيار -x إلزامي لتوثيق أصل الالتزام في الرسالة.
  • تجنب تطبيق cherry-pick على الالتزامات القديمة مع تباعد كبير في قاعدة الكود.
  • CI/CD تحقق من البناء بعد cherry-pick: قد لا يحدث صراع، لكن الكود قد لا يترجم.
  • تعليق في PR عند إنشاء pull request، حدد الالتزامات التي تم نقلها عبر cherry-pick.

الأسئلة الشائعة

ماذا يعني تطبيق cherry-pick على التزام؟

تطبيق cherry-pick يعني تطبيق تغييرات التزام محدد على الفرع الحالي عبر git cherry-pick. يقوم الأمر بإنشاء التزام جديد بنفس التغييرات ولكن مع hash جديدة. يبقى الالتزام الأصلي بدون تغيير في فرعه. هذا بديل لدمج فرع كامل عندما تحتاج إلى التزام واحد محدد فقط.

متى يُستخدم cherry-pick بدلاً من merge؟

Cherry-pick يُختار عندما تحتاج إلى نقل التزام واحد أو أكثر دون نقل الفرع بأكمله. يُستخدم merge للدمج الكامل للفروع. سيناريو cherry-pick النموذجي هو نقل إصلاح خطأ من فرع التطوير إلى فرع الإصدار حيث التغييرات الأخرى ليست جاهزة بعد.

هل يمكن إلغاء cherry-pick؟

قبل الاكتمال — git cherry-pick --abort يلغي العملية بالكامل. بعد الاكتمال بنجاح — git revert <hash> ينشئ التزاماً يلغي تغييرات cherry-pick. الفرق عن --abort: revert لا يزيل الالتزام من التاريخ، بل ينشئ التزام إلغاء جديد.

ماذا تفعل إذا أنشأ cherry-pick التزاماً فارغاً؟

يحدث الالتزام الفارغ عندما تكون التغييرات موجودة بالفعل في الفرع الهدف. استخدم git cherry-pick --skip لتخطي مثل هذا الالتزام، أو git cherry-pick --keep-redundant-commits لإنشاء التزام فارغ للحفاظ على تسلسل الهاشات.

كيف يختلف cherry-pick عن rebase؟

Cherry-pick ينقل الالتزامات المحددة (واحداً تلو الآخر أو كقائمة) إلى الفرع الحالي. Rebase ينقل جميع التزامات الفرع إلى قاعدة جديدة. Cherry-pick لا يغير الفرع المصدر، rebase يعيد كتابة التاريخ. Cherry-pick دقيق لكنه يدوي؛ rebase تلقائي لكنه خطير للفروع العامة.

الملخص

  • Cherry-pick — أمر لنقل الالتزامات الفردية بين الفروع مع الحفاظ على التغييرات وإنشاء hash جديدة.
  • السيناريو الرئيسي — نقل الإصلاحات بين فروع الإصدار دون نقل التاريخ الكامل أو الكود غير المكتمل.
  • التزامات متعددة تُنقل بأمر واحد عن طريق سرد الهاشات أو استخدام نطاق A..B.
  • الصراعات تُحل بنفس الطريقة كما في merge: تحرير الملفات، git add، git cherry-pick --continue.
  • الخيار -x يضيف مرجعاً للالتزام الأصلي في الرسالة لشفافية التاريخ.
  • الإلغاء يتم عبر --abort قبل الاكتمال أو git revert بعد ذلك.
  • المخاطر: تطبيق cherry-pick على التزامات تابعة وتغييرات قديمة جداً قد يسبب صراعات متعددة.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا