الخلاصة: git cherry-pick <sha> ينسخ commit واحدًا من أي فرع إلى فرعك الحالي — الرقعة نفسها، SHA جديد، بلا أي تاريخ يتحرك. لعدة commits، اسرد عناوين SHA أو استخدم نطاقًا (git cherry-pick A..B)؛ ولاحظ أن النطاق يستثني A، فاكتب A^..B لتضمينه. إذا توقف عند تعارض، فحلّه ثم git add ثم git cherry-pick --continue. الـ cherry-pick لنقل إصلاح محدد — وحين تريد كل شيء من الفرع الآخر، فاستخدم merge أو rebase بدلًا منه.
ماذا يفعل git cherry-pick فعلًا؟
يأخذ cherry-pick commitًا موجودًا ويطبق فرقه كـ commit جديد على فرعك الحالي. الـ commit الأصلي يبقى في مكانه؛ وتحصل النسخة على SHA طازج. لا “ينقل” git شيئًا — ومن يتساءل لاحقًا لماذا ما يزال الـ commit يظهر في الفرع القديم فهو يرى هذا بالضبط.
نموذج النسخ-لا-النقل هذا يحدد متى يكون cherry-pick الأداة الصحيحة:
- تحتاج إصلاحًا واحدًا من فرع ميزات إلى
mainالآن، دون دمج البقية. - إصلاح عاجل رُفع على الفرع الخطأ ويجب أن يهبط على الصحيح.
- رقعة يجب إعادة تشغيلها على فرع إصدار لا يدمج من
mainقط.
المهارة المكمّلة هي معرفة كيف تتراجع عن commit تبين خطؤه — وميكانيكا ذلك مشروحة في التراجع عن آخر commit مع الاحتفاظ بالتغييرات.
كيف ألتقط commit من فرع آخر؟
اعثر على الـ SHA، انتقل إلى الفرع الهدف، التقط:
# 1. حدّد مكان الـ commit على الفرع المصدر
git log feature/payment-fix --oneline -5
# 2. انتقل إلى الفرع الذي سيتلقاه
git switch main
# 3. انسخه
git cherry-pick 1a2b3c4 تيسيران يستحقان المعرفة:
git cherry-pick <branch>يلتقط قمة ذلك الفرع — مفيد، لكنه سهل الوقوع فيه خطأً مع نموذج ذهني قديم عن ماهية “القمة”.- بعد الالتقاط، يؤكد
git log -1 --statما هبط. ثانية قراءة توفّر تراجعًا كاملًا.
تبقى الـ commits على feature/payment-fix؛ واحذف ذلك الفرع متى شئت — فالنسخة الملتقطة على main لها SHA خاص ولا اعتماد على القديمة.
كيف ألتقط عدة commits؟
ثلاث صيغ، بترتيب شيوع الحاجة إليها:
# 1. سرد صريح — تُلتقط بترتيب سردها
git cherry-pick 1a2b3c4 5d6e7f8
# 2. نطاق — كل شيء بعد A حتى B ضمنًا
git cherry-pick A..B
# 3. نطاق شامل لـ A
git cherry-pick A^..B التمييز بين A..B وA^..B هو المفاجأة الكلاسيكية: النطاق A..B يستثني A. إذا تخيلت النطاق من git log واخترت oldest..newest فستتخطى أقدم commit بصمت. وحين يكون الهدف “أقدم بضعة commits بالترتيب”، فاكتب oldest^..newest ويختفي خطأ الإزاحة بواحد.
وطيّ عدة التقاطات في commit واحد بدل ثلاثة: جهّز بلا commit باستخدام -n / --no-commit ثم commit مرة واحدة:
git cherry-pick -n 1a2b3c4 5d6e7f8
git commit -m "Backport: payment retry fixes" لماذا لا يعمل git cherry-pick؟
أربعة أسباب حقيقية بترتيب التواتر:
1. تعارض أوقف الالتقاط. يطبق git الرقعة فيصطدم بسطر تغيّر في الفرعين، فيتوقف في منتصف التسلسل:
# حلّ الملفات، ثم:
git add <resolved-files>
git cherry-pick --continue # أو --abort للعودة إلى ما قبل الالتقاط الخيار --continue ليس اختياريًا ولا ضمنيًا — وقبل أن تشغّله فأنت داخل تسلسل cherry-pick موقوف، وسلازم git status أن يقول ذلك.
2. الالتقاط فارغ (“The previous cherry-pick is now empty”). التغيير موجود أصلًا على هذا الفرع، غالبًا من التقاط سابق أو دمج مضغوط. تخطَّه بـ git cherry-pick --skip، أو أفرِض commitًا فارغًا بـ --allow-empty إذا كنت تحتاج العلامة حقًا.
3. الـ commit هو commit دمج. للدمج أبوين، فعبارة “طبق هذا الفرَق” غامضة — يرفض git بدل أن يخمّن. قل أي الأبوين تجري المقارنة ضده:
git cherry-pick -m 1 <merge-sha> # الأب 1 = الفرع الذي دمجت *إليه* 4. شجرة عمل خاطئة أو HEAD مفصول. يهبط الالتقاط حيثما يشير HEAD. افحص git branch --show-current قبل الالتقاط؛ وإن لم يطبع شيئًا فأنت في HEAD مفصول وسيُشرَّد الـ commit عند مغادرتك.
cherry-pick مقابل merge مقابل rebase: أيها متى؟
| الأمر | ما يهبط على الهدف | التاريخ | استخدمه حين |
|---|---|---|---|
git cherry-pick <sha> | الـ commit المسمى وحده | نسخة، SHAs جديدة | يجب نقل إصلاح محدد الآن |
git merge <branch> | كل شيء على الفرع | commit دمج أو fast-forward | تريد الفرع كله وتمايزه ظاهرًا |
git rebase <base> | كل commits الفرع معاد تشغيلها | خطي، SHAs معاد كتابتها | تريد الفرع كسلسلة خطية نظيفة |
git revert <sha> | عكس الـ commit | يضيف commit إلغاء | commit هبط ويجب إلغاؤه على تاريخ مشترك |
القاعدة في سطر: cherry-pick ينقل انتقاءً؛ وmerge وrebase ينقلان كل شيء. مدّة يدك نحو cherry-pick “للمزامنة” مع فرع علامة أنك تريد merge في حقيقة الأمر — وإذا كان الفرع main في الـ fork مقابل upstream، فالروتين الكامل في مزامنة fork مع upstream خطوة بخطوة.
وعادة ينبغي تجنبها: التقاط الـ commit نفسه إلى عدة فروع على المدى البعيد. كل إصلاح مستقبلي على الفرع المصدر يتطلب التقاطًا جديدًا، وتنحرف الفروع حتمًا. النقل الخلفي إلى فروع الإصدارات نمط طبيعي؛ أما كون متوازٍ دائم فليس كذلك.
مسار cherry-pick، مكثفًا
git log <source-branch> --oneline -5 # اعثر على الـ SHA
git switch <target-branch> # هبوط في المكان الصحيح
git cherry-pick A^..B # نطاق أو سرد أو SHA واحد
# عند تعارض: حل → git add → git cherry-pick --continue
git log -1 --stat # أكد ما هبط اعثر، انتقل، التقط، تحقق. الأمر له سمعة خطورة لا يستحقها — إما أن تطبق الرقعة أو يتوقف ويخبرك لماذا. والخطأ المدمر الوحيد هو الالتقاط في الفرع الخطأ، وgit log -1 قبل الدفع يجعل ذلك يصعب إغفاله.
— mrsaynothing
— mrsaynothing
ملاحظات ميدانية في الذكاء الاصطناعي وLinux والاستضافة الذاتية.
ناقش هذا المقال على dev.to dev.to ↗
احصل على الشرح التطبيقي التالي بالبريد
رسالة واحدة لكل مقال. أصلح المشكلة وامضِ.
ما هذا؟cron مقابل مؤقتات systemd: أيهما تستخدم؟
أعجبتك هذه الكتابات؟ بناء مثل هذا هو عملي. وظّفني