ব্লগে ফিরুন

Git cherry-pick: একাধিক commit, branch, conflict

১২ সেপ্টেম্বর, ২০২৬

TL;DR: git cherry-pick <sha> যেকোনো branch থেকে একটি commit আপনার বর্তমান branch-এ কপি করে — একই patch, নতুন SHA, history কিছু নড়ে না। একাধিক commit-এর জন্য SHA-গুলো লিখুন বা range দিন (git cherry-pick A..B); খেয়াল রাখুন, range-এ A বাদ যায় — সেটিও ধরতে লিখুন A^..B। Conflict-এ থেমে গেলে সমাধান করুন, git add, তারপর git cherry-pick --continue। Cherry-pick আসলে একটি নির্দিষ্ট ফিক্স সরানোর জন্য — অন্য branch-এর সবকিছু চাইলে merge বা rebase করুন।

Git cherry-pick আসলে কী করে?

Cherry-pick একটি বিদ্যমান commit নিয়ে তার diff আপনার বর্তমান branch-এ নতুন commit হিসেবে প্রয়োগ করে। আসল commit জায়গামতোই থাকে; কপিটি পায় একদম নতুন SHA। Git আসলে কিছুই “সরায়” না — পরে অনেকে ভাবেন কেন commit-টি পুরনো branch-এ এখনও দেখা যাচ্ছে; এটাই তার ব্যাখ্যা।

এই copy-not-move মডেলই ঠিক করে কখন cherry-pick সঠিক হাতিয়ার:

  • feature branch-এর একটি ফিক্স এখনই main-এ দরকার, বাকিটা merge না করে।
  • ভুল branch-এ করা একটি hotfix সঠিক branch-এ পৌঁছাতে হবে।
  • এমন একটি release branch-এ patch আবার বসাতে হবে যা main থেকে কখনো merge করে না।

পরিপূরক দক্ষতা হলো ভুল প্রমাণিত একটি commit কীভাবে বাদ দেবেন — সেই প্রক্রিয়া git undo last commit: keep the changes-এ ব্যাখ্যা করা হয়েছে।

অন্য branch থেকে commit কীভাবে cherry-pick করবেন?

SHA খুঁজুন, টার্গেট branch-এ যান, pick করুন:

# ১. সোর্স branch-এ commit-টি খুঁজুন
git log feature/payment-fix --oneline -5

# ২. যে branch এটি পাবে সেখানে যান
git switch main

# ৩. কপি করে আনুন
git cherry-pick 1a2b3c4

জেনে রাখার মতো দুটি সুবিধা:

  • git cherry-pick <branch> ওই branch-এর tip commit-টি pick করে — কাজের, কিন্তু “tip” আসলে কোনটা তার পুরনো ধারণা নিয়ে ভুলে চাপা খুব সহজ।
  • Pick-এর পর git log -1 --stat কী এসেছে তা নিশ্চিত করে। পড়তে এক সেকেন্ড, বাঁচায় এক revert।

Commit-গুলো feature/payment-fix-এই থাকে; ওই branch যখন খুশি মুছে দিন — main-এর কপিটির নিজস্ব SHA আছে, পুরনোটির ওপর কোনো নির্ভরতা নেই।

একাধিক commit কীভাবে cherry-pick করবেন?

তিনটি রূপ, কোনটি কত ঘন ঘন লাগে সেই ক্রমে:

# ১. সরাসরি তালিকা — লেখার ক্রমেই pick হয়
git cherry-pick 1a2b3c4 5d6e7f8

# ২. Range — A-এর পর থেকে B পর্যন্ত (B সহ)
git cherry-pick A..B

# ৩. A সহ range
git cherry-pick A^..B

A..B বনাম A^..B পার্থক্যটিই চিরচেনা ধাঁধা: A..B A-কে বাদ দেয়git log দেখে চোখে range আঁকতে আঁকতে oldest..newest pick করলে পুরনোতম commit-টি নীরবে বাদ পড়ে যায়। লক্ষ্য যখন “পুরনো কয়েকটি commit, ক্রম ঠিক রেখে”, লিখুন oldest^..newest — off-by-one চলে যাবে।

তিনটির বদলে একাধিক pick এক commit-এ ভাঁজ করতে -n / --no-commit দিয়ে commit না করে stage করুন, তারপর একবার commit করুন:

git cherry-pick -n 1a2b3c4 5d6e7f8
git commit -m "Backport: payment retry fixes"

Git cherry-pick কেন কাজ করছে না?

চারটি আসল কারণ, ঘনত্বের ক্রমে:

১. Conflict-এ pick থেমে গেছে। Git patch প্রয়োগ করতে করতে এমন একটি লাইনে পড়ে যা দুই branch-এই বদলেছে, আর মাঝপথে থেমে যায়:

# ফাইলগুলো সমাধান করুন, তারপর:
git add <resolved-files>
git cherry-pick --continue   # অথবা আগের অবস্থায় ফিরতে --abort

--continue ঐচ্ছিক নয়, আর এটি নিজে থেকেও হয় না — না চালানো পর্যন্ত আপনি থেমে থাকা একটি cherry-pick sequence-এর ভেতরেই আছেন, আর git status বারবার সেটাই বলবে।

২. Pick-টি ফাঁকা (“The previous cherry-pick is now empty”)। পরিবর্তনটি এই branch-এ আগেই আছে — প্রায়ই আগের কোনো pick বা squashed merge-এর কারণে। বাদ দিতে git cherry-pick --skip, আর মার্কারটি সত্যিই দরকার হলে --allow-empty দিয়ে ফাঁকা commit জোর করে আনুন।

৩. Commit-টি একটি merge commit। Merge-এর দুই parent থাকে, তাই “এই diff প্রয়োগ করো” অস্পষ্ট — গুজব না দিয়ে git অস্বীকার করে। কোন parent-এর বিপরীতে diff হবে সেটি বলে দিন:

git cherry-pick -m 1 <merge-sha>   # parent 1 = যে branch-এ আপনি merge করেছিলেন

৪. ভুল working tree বা detached HEAD। Pick যেখানে HEAD নির্দেশ করে সেখানেই বসে। Pick-এর আগে git branch --show-current চালান; কিছু প্রিন্ট না করলে বুঝবেন detached HEAD-এ আছেন, আর branch বদলালে commit-টি orphan হয়ে যাবে।

Cherry-pick বনাম merge বনাম rebase: কখন কোনটি?

Commandটার্গেটে কী যায়Historyকখন ব্যবহার করবেন
git cherry-pick <sha>শুধু নাম ধরে বলা commit(গুলো)কপি, নতুন SHAএকটি নির্দিষ্ট ফিক্স এখনই সরাতে হবে
git merge <branch>Branch-এর সবকিছুMerge commit বা fast-forwardপুরো branch চান, divergence দৃশ্যমান থাকুক
git rebase <base>Branch-এর সব commit, আবার চালানোLinear, SHA পুনর্লিখিতBranch-টিকে পরিচ্ছন্ন linear ধারায় চান
git revert <sha>একটি commit-এর বিপরীতএকটি undo commit যোগ হয়Shared history-তে এসে পড়া commit বাতিল করতে হবে

এক লাইনের নিয়ম: cherry-pick সরায় নির্বাচিত অংশ; merge আর rebase সরায় সবকিছু। Branch-এর সঙ্গে “sync”-এর জন্য cherry-pick ধরা মানে আসলে merge চাইছেন — আর সেই branch যদি হয় আপনার fork-এর main বনাম upstream, পুরো প্রক্রিয়া আছে sync a fork with upstream, step by step-এ।

একটি অভ্যাস বাদ দিন: একই commit দীর্ঘমেয়াদে একাধিক branch-এ cherry-pick করা। সোর্স branch-এর প্রতিটি ভবিষ্যৎ ফিক্সের জন্য আরেকটি pick লাগবে, আর শেষে branch-গুলো আলাদা পথে সরে যাবে। Release branch-এ backport স্বাভাবিক প্যাটার্ন; স্থায়ী সমান্তরাল জগৎ নয়।

Cherry-pick workflow, সংক্ষেপে

git log <source-branch> --oneline -5   # SHA খুঁজুন
git switch <target-branch>             # সঠিক জায়গায় পৌঁছান
git cherry-pick A^..B                  # range, তালিকা, বা একক SHA
# conflict হলে: resolve → git add → git cherry-pick --continue
git log -1 --stat                      # কী এসেছে নিশ্চিত করুন

খুঁজুন, যান, pick করুন, যাচাই করুন। কমান্ডটির বিপজ্জনক খ্যাতি অন্যায্য — diff হয় প্রয়োগ হয়, নয়তো থেমে বলে দেয় কেন হয়নি। একমাত্র সত্যিকারের ক্ষতিকর ভুল হলো ভুল branch-এ pick করা, আর push-এর আগে git log -1 সেই ভুল চোখ এড়াতে দেয় না।

— mrsaynothing

— mrsaynothing

AI, Linux ও self-hosting নিয়ে ফিল্ড নোটস।

পোস্টটি নিয়ে dev.to-তে আলোচনা করুন dev.to ↗

পরের হাউ-টু ইমেইলে পান

প্রতি পোস্টে একটি ইমেইল। সমাধান করুন, এগিয়ে যান।

self-hosted · কোনো তৃতীয় পক্ষ নেই · এক ক্লিকে আনসাবস্ক্রাইব

এটা কী?

Cron vs systemd timer: কোনটি ব্যবহার করবেন?

লেখাগুলো ভালো লাগছে? এমন জিনিস বানানোই আমার পেশা। আমাকে নিন