git cherry-pick কী করে
নাম থেকেই ধারণা পাওয়া যায় — গাছ থেকে বেছে বেছে একটা চেরি তোলা। Cherry-pick হলো অন্য কোনো branch থেকে নির্দিষ্ট একটা (বা কয়েকটা) commit তুলে এনে আপনার বর্তমান branch-এর মাথায় বসানো:
git checkout release-2.4
git cherry-pick a3f5c9d
ভেতরে আসলে কী ঘটে
এখানে প্রথম আলোচনার মানসিক মডেলটা কাজে লাগে। একটা সূক্ষ্ম কিন্তু গুরুত্বপূর্ণ বিষয়: Git commit-টা কপি করে না — করতে পারেও না, কারণ commit-এর hash-এ তার parent ঢুকে আছে; parent বদলালেই সেটা ভিন্ন commit।
Cherry-pick যা করে:
- Commit-টা আর তার parent-এর মধ্যে diff (patch) বের করে
- সেই patch আপনার বর্তমান branch-এর HEAD-এর উপর apply করে
- একই message, author নিয়ে নতুন commit বানায় — নতুন hash সহ
D---E---A---B---C feature (B = যে fix চাই)
\
F---G---B' release-2.4 (B' = B-এর জমজ, কিন্তু ভিন্ন hash)
অর্থাৎ rebase-এর মতোই এটা "commit replay" — আসলে rebase ভেতরে ভেতরে একগুচ্ছ cherry-pick-ই চালায়। আর যেহেতু patch apply হচ্ছে ভিন্ন প্রেক্ষাপটে, conflict এখানেও হতে পারে — সমাধান আগের আলোচনার মতোই: ঠিক করুন, git add, তারপর git cherry-pick --continue (বা --abort)।
কাজের কিছু flag:
git cherry-pick -x a3f5c9d # commit message-এ "(cherry picked from commit a3f5c9d)" যোগ করে — traceability-র জন্য দারুণ
git cherry-pick A^..C # একটা range-এর সব commit
git cherry-pick -n a3f5c9d # apply করবে কিন্তু commit করবে না — নিজে এডিট করে commit করতে চাইলে
বাস্তব দৃশ্যপট: Production Hotfix
এটাই সবচেয়ে ক্লাসিক ও বাস্তব ব্যবহার — interview-তে এই উদাহরণটাই দেবেন।
পরিস্থিতি: আপনার টিমের অবস্থা এমন:
main— সক্রিয় ডেভেলপমেন্ট, version 2.5-এর আধা-সম্পূর্ণ ফিচারে ভরাrelease-2.4— production-এ যা চলছে
হঠাৎ production-এ ক্রিটিক্যাল বাগ: ধরুন payment calculation-এ rounding error। আপনি fix করলেন main-এ (কারণ ভবিষ্যতের সব ভার্সনেও fix-টা লাগবে), commit হলো a3f5c9d।
সমস্যা: এখন production-এ fix পাঠাতে হবে। কিন্তু main-কে release-2.4-এ merge করা যাবে না — তাহলে ২.৫-এর সব অসম্পূর্ণ, untested ফিচার production-এ চলে যাবে। আপনার দরকার শুধু ওই এক commit।
সমাধান:
git checkout release-2.4
git cherry-pick -x a3f5c9d
# টেস্ট চালান, তারপর tag করে deploy
ব্যস — production পেল শুধু fix-টা, আর main-এও fix রয়ে গেল ভবিষ্যতের জন্য। -x flag-এর কারণে release branch-এর history দেখে ছয় মাস পরেও বলা যাবে fix-টা কোথা থেকে এসেছিল।
এই প্যাটার্নটা এতই প্রতিষ্ঠিত যে বড় প্রজেক্টগুলোতে (যেমন Kubernetes, LTS-ভিত্তিক যেকোনো সফটওয়্যার) "backporting" নামে আলাদা প্রক্রিয়াই আছে — নতুন ভার্সনের fix পুরোনো supported ভার্সনগুলোতে cherry-pick করা, অনেক জায়গায় বট দিয়ে স্বয়ংক্রিয়ভাবে।
আরো কয়েকটা বাস্তব ব্যবহার
- ভুল branch-এ commit করে ফেলেছেন:
feature-A-তে কাজ করতে করতে এমন একটা commit করলেন যেটা আসলেfeature-B-র। সঠিক branch-এ গিয়ে cherry-pick করুন, তারপর আগের branch থেকেgit resetদিয়ে সরান। - পরিত্যক্ত PR থেকে ভালো অংশ উদ্ধার: কোনো বড় PR বাতিল হলো, কিন্তু তার ভেতরের দুটো utility commit মূল্যবান — সেগুলো তুলে আনুন।
- সহকর্মীর branch থেকে dependency: আপনার কাজের জন্য সহকর্মীর অপ্রকাশিত branch-এর একটা commit দরকার — merge-এর অপেক্ষা না করে ওইটুকু cherry-pick করে এগোন (পরে merge হলে Git সাধারণত duplicate patch চিনে সামলে নেয়)।
সতর্কতা: কখন cherry-pick করবেন না
সিনিয়র উত্তরে এই দিকটাও থাকা চাই। Cherry-pick-এর মূল বিপদ — একই পরিবর্তনের দুটো ভিন্ন-hash কপি দুই branch-এ ঘুরে বেড়ায়:
- যদি প্রায়ই cherry-pick করতে হয়, সেটা branching strategy-র রোগের লক্ষণ। দুই branch-এর মধ্যে নিয়মিত commit বাছাই করে আনা মানে branch-গুলোর দায়িত্ব-ভাগ ঠিক নেই — সমাধান process ঠিক করা, cherry-pick-কে অভ্যাস বানানো নয়।
- Dependency ভুলে যাওয়া: commit B হয়তো commit A-র কোডের উপর নির্ভরশীল। শুধু B তুললে compile হবে না, বা আরো খারাপ — compile হবে কিন্তু ভুলভাবে চলবে (আগের আলোচনার সেই semantic conflict)। তাই cherry-pick-এর পর টেস্ট বাধ্যতামূলক।
- Merge-এর বিকল্প হিসেবে না: পুরো feature আনতে হলে merge/rebase-ই সঠিক পথ — history-তে সম্পর্কটা টিকে থাকে।
এক লাইনে
"Cherry-pick মানে নির্দিষ্ট commit-এর পরিবর্তনটুকু patch হিসেবে তুলে অন্য branch-এ নতুন commit বানানো — সবচেয়ে বাস্তব ব্যবহার release branch-এ hotfix backport করা, যেখানে পুরো main merge করা সম্ভব নয়; তবে এটা নিয়মিত workflow না, ব্যতিক্রমী পরিস্থিতির অস্ত্র।"