Cherry-pick هو أمر Git يطبق التغييرات من التزام محدد على الفرع الحالي دون نقل التاريخ الكامل للفرع المصدر. على عكس merge أو rebase، يعمل cherry-pick مع كل التزام على حدة: يختار المطور التزاماً معيناً بواسطة hash الخاصة به وينقل تغييراته فقط. وفقاً لتوثيق Git (2026)، فإن cherry-pick مفيد بشكل خاص للنقل الموجه للإصلاحات بين فروع الإصدار عندما يكون الدمج الكامل مفرطاً أو محفوفاً بالمخاطر. يقوم الأمر بإنشاء التزام جديد مع hash جديدة، لكنه يحتفظ بالرسالة الأصلية والمؤلف.
الخلاصة
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 ...) إلى رسالة الالتزام، مما يسهل تتبع أصل التغييرات في التاريخ.
# تطبيق 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
السيناريو الرئيسي هو نقل الإصلاحات بين فروع الإصدار. تخيل: تم العثور على خطأ حاسم وإصلاحه في develop. فرع الإصدار release/v2.1 مفصول بالفعل ويحتوي أيضاً على هذا الخطأ. دمج develop بالكامل في release سيجلب الكثير من الكود غير المكتمل، بينما تطبيق cherry-pick على التزام الإصلاح الواحد هو حل آمن ودقيق.
السيناريو الثاني هو عكس التغييرات مع الاستعادة لاحقاً. إذا تم عكس التزام عبر git revert واتضح لاحقاً أن العكس كان خطأ — فإن تطبيق cherry-pick على الالتزام المعكوس يستعيد التغييرات. هذا أكثر صحة من عكس العكس لأنه لا ينشئ صراعات متكررة.
السيناريو الثالث هو دمج الالتزامات من فروع ميزات مختلفة في فرع اختبار واحد لاختبار التكامل. بدلاً من دمج عدة فروع غير مكتملة (مع كود غير منتهٍ)، يمكن اختيار الالتزامات الجاهزة فقط من كل منها واختبار كيفية عملها معاً.
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) الذي يتم حساب الفرق بناءً عليه.
# نطاق التزامات 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 تحدث عندما تؤثر تغييرات الالتزام المنقول على نفس الأسطر التي تم تغييرها في الفرع الهدف. يوقف 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 يسمح بتخطي مثل هذا الالتزام.
# صراع أثناء 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
القاعدة الأولى: تحقق دائماً من أن الالتزام المنقول مكتفي بذاته. إذا كان الالتزام A يعتمد على تغييرات في الالتزام B الذي لا يُنقل، فإن تطبيق cherry-pick على A قد يكسر البناء. قبل تطبيق cherry-pick، من المفيد التحقق من الملفات التي غيرها الالتزام عبر git show --stat <hash>.
القاعدة الثانية: وثق عمليات cherry-pick. استخدم الخيار -x لتحتفظ رسالة الالتزام بمرجع إلى الالتزام الأصلي. سيساعد هذا أثناء التحليل اللاحق للتاريخ في فهم مصدر التغيير. بدون -x، يبدو cherry-pick كالتزام عادي، ولا يمكن تحديد أصله إلا عبر git log --graph.
القاعدة الثالثة: تجنب cherry-pick بين الفروع التي تباعدت كثيراً. إذا مر وقت طويل منذ إنشاء الالتزام وتغيرت قاعدة الكود بشكل كبير، ستكون الصراعات عديدة ومعقدة. في مثل هذه الحالات، من الأفضل إعادة تنفيذ الإصلاح في الفرع الهدف — سيستغرق وقتاً أقل من حل عشرات الصراعات.
الأسئلة الشائعة
تطبيق cherry-pick يعني تطبيق تغييرات التزام محدد على الفرع الحالي عبر git cherry-pick. يقوم الأمر بإنشاء التزام جديد بنفس التغييرات ولكن مع hash جديدة. يبقى الالتزام الأصلي بدون تغيير في فرعه. هذا بديل لدمج فرع كامل عندما تحتاج إلى التزام واحد محدد فقط.
Cherry-pick يُختار عندما تحتاج إلى نقل التزام واحد أو أكثر دون نقل الفرع بأكمله. يُستخدم merge للدمج الكامل للفروع. سيناريو cherry-pick النموذجي هو نقل إصلاح خطأ من فرع التطوير إلى فرع الإصدار حيث التغييرات الأخرى ليست جاهزة بعد.
قبل الاكتمال — git cherry-pick --abort يلغي العملية بالكامل. بعد الاكتمال بنجاح — git revert <hash> ينشئ التزاماً يلغي تغييرات cherry-pick. الفرق عن --abort: revert لا يزيل الالتزام من التاريخ، بل ينشئ التزام إلغاء جديد.
يحدث الالتزام الفارغ عندما تكون التغييرات موجودة بالفعل في الفرع الهدف. استخدم git cherry-pick --skip لتخطي مثل هذا الالتزام، أو git cherry-pick --keep-redundant-commits لإنشاء التزام فارغ للحفاظ على تسلسل الهاشات.
Cherry-pick ينقل الالتزامات المحددة (واحداً تلو الآخر أو كقائمة) إلى الفرع الحالي. Rebase ينقل جميع التزامات الفرع إلى قاعدة جديدة. Cherry-pick لا يغير الفرع المصدر، rebase يعيد كتابة التاريخ. Cherry-pick دقيق لكنه يدوي؛ rebase تلقائي لكنه خطير للفروع العامة.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.