Thuta Learning
Git & GitHub: Collaboration and Professional Workflows
AdvancedDevOps & Toolsintermediate

Cherry-pick နှင့် Bisect

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Cherry-pick နှင့် Bisect concept ကို နားလည်ရှင်းပြနိုင်ရန်
  • Diagram ကို ဖတ်ပြီး Git/GitHub workflow ထဲမှာ state (သို့) data ဘယ်လိုစီးဆင်းသလဲ ခြေရာခံနိုင်ရန်
  • ကိုယ့် project/team အတွက် ဘယ်လို အသုံးချသင့်သလဲ ဆုံးဖြတ်နိုင်ရန်

နားလည်ထားရမယ့် အချက်

Cherry-pick နဲ့ bisect ဟာ surgical tool နှစ်ခုပါ — branch တစ်ခုလုံးအပေါ် အလုပ်လုပ်မယ့်အစား commit တစ်ခုတည်းကို ရည်ရွယ်ချက်ကွဲပြားစွာနဲ့ ပစ်မှတ်ထားနိုင်ပါတယ်။

Cherry-pick က repository ထဲက commit တစ်ခုကို ယူပြီး ၎င်းရဲ့ change ကိုသာ လက်ရှိ branch ပေါ် ပြန်သက်ရောက်စေကာ content တူတဲ့ hash အသစ်ရှိတဲ့ commit အသစ်တစ်ခု ဖန်တီးပေးပါတယ်။ classic use case ကတော့ hotfix ပါ — branch တစ်ခုပေါ် ပြင်းထန်တဲ့ bug ကို fix လုပ်ပြီးသားဖြစ်ပြီး branch တခြားတစ်ခုပေါ်မှာလည်း အဲ့ fix အတိအကျ ချက်ချင်းလိုချင်တဲ့အခါ၊ branch ကွဲထွက်ကတည်းက စုစည်းလာခဲ့တဲ့ တခြားအရာအားလုံးကို merge မလုပ်ဘဲ သုံးနိုင်ပါတယ်။

  • အသီးသန့် နဲ့ ရှင်းရှင်းလင်းလင်းနားလည်ထားတဲ့ fix တွေအတွက် ရံဖန်ရံခါသုံးရင် cherry-pick က တကယ်အသုံးဝင်ပါတယ်။
  • branch တစ်ခုလုံး merge/rebase လုပ်မယ့်အစား အလေ့အကျင့်လိုသုံးနေရင် change တူတဲ့ hash ကွဲပြားတဲ့ commit ထပ်တွေ တိတ်တဆိတ် ဖန်တီးလိုက်ပြီး history ကို ရှုပ်ထွေးစေပါတယ်။

Bisect ကတော့ ပြဿနာမျိုးစိတ်လုံးဝကွဲပြားပါတယ် — အခု ရှိနေတဲ့ bug တစ်ခုက အတိတ်က တစ်ချိန်ချိန်မှာ မရှိခဲ့ဘူးဆိုရင် ဘယ် commit က စပြီး ဖြစ်ပေါ်စေခဲ့သလဲ။ git bisect က binary search လုပ်ပေးပါတယ် — known-good commit တစ်ခုနဲ့ known-bad commit တစ်ခု (ပုံမှန်အားဖြင့် HEAD) ကို ပြောပြရင် Git က အလယ်လောက်က commit ကို checkout လုပ်ပေးပြီး စမ်းသပ်ခိုင်းပါတယ်။ good/bad လို့ ပြန်ဖြေပေးရင် range ကျဉ်းသွားပြီး candidate commit အရေအတွက်ရဲ့ log-base-2 လောက်အဆင့်ပဲ လိုအပ်ပါတယ်။

Cherry-pick
commit တစ်ခုတည်းရဲ့ ပြောင်းလဲမှုကို branch တခြားတစ်ခုပေါ် content တူပေမယ့် hash အသစ်ရှိတဲ့ commit အသစ်တစ်ခု ဖန်တီးပြီး သက်ရောက်စေခြင်း။
Bisect
known-good နဲ့ known-bad commit ကြားက commit တွေကို ထပ်ခါတလဲလဲ စမ်းသပ်ပြီး bug ဖြစ်ပေါ်စေတဲ့ commit အတိအကျကို ရှာပေးတဲ့ binary-search workflow (git bisect) တစ်ခု။
text
CHERRY-PICK (COPY ONE COMMIT) AND BISECT (BINARY SEARCH)
--------------------------------------------------------
CHERRY-PICK

hotfix:  base---FIX
                  |
                  | git cherry-pick FIX
                  v
main:    base---update---FIX'   (new hash, same change)

BISECT

good                                   bad (HEAD)
 |---------|---------|---------|---------|
 c1        c2        c3        c4        c5
           git bisect checks c3 first (halfway)
           mark good/bad, range shrinks each step
           until the first bad commit is found

လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်

Cherry-pick ဥပမာမှာ shared commit တစ်ခုကနေ branch နှစ်ခု တည်ဆောက်ထားပါတယ်။ hotfix branch ပေါ်မှာ fix commit (Fix null pointer crash) လုပ်ထားပြီး main ကတော့ မသက်ဆိုင်တဲ့ commit (Update readme) နဲ့ ရှေ့ဆက်သွားလို့ branch နှစ်ခု တကယ်ကွဲထွက်သွားပါတယ်။ main ပေါ်ရောက်နေတုန်း hotfix commit ရဲ့ hash နဲ့ git cherry-pick run လိုက်ရင် အဲ့ change တစ်ခုတည်းကို ပြန်သက်ရောက်စေပါတယ် — ပြီးရင် git log --oneline က fix ကို hash အသစ် (parent ကွဲသွားလို့) နဲ့ ပြပါတယ်။

အစွန်းတွေကို သတ်မှတ်ခြင်း

git bisect start နဲ့ ရှာဖွေမှုစတင်ပြီး git bisect bad က လက်ရှိ HEAD ပျက်နေကြောင်း၊ git bisect good က known-clean ဖြစ်တဲ့ ပထမ commit ကို သတ်မှတ်ပေးပါတယ်။

Git က အလယ်ဗဟို commit ကို checkout လုပ်ပေးခြင်း

good နဲ့ bad ကြားက အလယ်ဗဟိုလောက် commit ကို Git က checkout လုပ်ပေးပြီး စမ်းသပ်ခိုင်းပါတယ် — တွေ့တာအလိုက် git bisect good ဒါမှမဟုတ် git bisect bad လို့ ပြန်ဖြေပါတယ်။

Range ကျဉ်းလာခြင်း

ဒီဥပမာမှာ အဆင့်နှစ်ခုပဲ ကြာပြီး Git က ပထမဆုံး bad commit ကို hash နဲ့ message နဲ့ တိတိကျကျ ဖော်ပြပေးပါတယ်။

Reset

ပြီးရင် git bisect reset နဲ့ မူလ branch ကို ပြန်သွားနိုင်ပါတယ်။

အတူတူ စမ်းရေးကြည့်မယ်

bash
export GIT_AUTHOR_NAME="Thuta Learner"
export GIT_AUTHOR_EMAIL="learner@example.com"
export GIT_COMMITTER_NAME="Thuta Learner"
export GIT_COMMITTER_EMAIL="learner@example.com"

# --- cherry-pick ---
mkdir cherry-pick-demo && cd cherry-pick-demo
git init -q -b main
export GIT_AUTHOR_DATE="2026-01-01T09:00:00"
export GIT_COMMITTER_DATE="2026-01-01T09:00:00"
echo "v1" > app.js
git add app.js
git commit -m "Initial commit"

git checkout -b hotfix
export GIT_AUTHOR_DATE="2026-01-01T09:30:00"
export GIT_COMMITTER_DATE="2026-01-01T09:30:00"
echo "v1-fixed" > app.js
git add app.js
git commit -m "Fix null pointer crash"

HASH=$(git rev-parse HEAD)
git checkout main
export GIT_AUTHOR_DATE="2026-01-01T10:00:00"
export GIT_COMMITTER_DATE="2026-01-01T10:00:00"
echo "unrelated change" > readme.txt
git add readme.txt
git commit -m "Update readme"

export GIT_AUTHOR_DATE="2026-01-01T10:30:00"
export GIT_COMMITTER_DATE="2026-01-01T10:30:00"
git cherry-pick $HASH
git log --oneline
cd ..

# --- bisect (separate repo, 5 commits, bug introduced in commit 3) ---
mkdir bisect-demo && cd bisect-demo
git init -q -b main

# check.sh is the automated test: exit 0 = good, exit 1 = bad (bug present).
printf "#!/bin/sh
grep -q RESULT=8 calc.sh
" > check.sh
chmod +x check.sh

write_commit() {
  echo "echo RESULT=$1" > calc.sh
  echo "$3" >> history.txt
  git add calc.sh check.sh history.txt
  GIT_AUTHOR_DATE="2026-01-02T0$2:00:00" GIT_COMMITTER_DATE="2026-01-02T0$2:00:00"     git commit -m "$3"
}

write_commit 8 9 "Add calc"
write_commit 8 10 "Add subtract"
write_commit 5 11 "Add multiply (introduces bug)"
write_commit 5 12 "Add divide"
write_commit 5 13 "Add docs"

FIRST_GOOD=$(git rev-parse HEAD~4)
git bisect start
git bisect bad HEAD
git bisect good $FIRST_GOOD
git bisect run ./check.sh
git bisect reset
cd ..
You should see
Cherry-pick — cherry-pick ပြီးနောက် main ပေါ်က git log --oneline:

9fe14a1 Fix null pointer crash
5a74be8 Update readme
e4fa43b Initial commit

9fe14a1 ဟာ မူလ hotfix commit ရဲ့ hash (8c3ee50) နဲ့ မတူပါဘူး — parent ကွဲသွားလို့ပါ။

Bisect — check.sh ကို good behavior အတွက် exit 0၊ bug အတွက် exit 1 ပြန်အောင် script ရေးထားလို့  က search တစ်ခုလုံးကို လူမပါဘဲ အလိုအလျောက် run ပေးပါတယ်။ Git က midpoint commit တစ်ခုချင်းစီကို checkout လုပ်ပြီး check.sh ကို run ကာ exit code ကို good/bad အဖြေအဖြစ် အလိုအလျောက် သုံးပါတယ်:

Bisecting: 1 revision left to test after this (roughly 1 step)
[<hash>] Add multiply (introduces bug)
running './check.sh'
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[<hash>] Add subtract
running './check.sh'
<hash> is the first bad commit
commit <hash>
    Add multiply (introduces bug)

 calc.sh     | 2 +-
 history.txt | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)
bisect found first bad commit

Git က "Add multiply (introduces bug)" ကို first bad commit အဖြစ် မှန်ကန်စွာ ရှာတွေ့ပါတယ် — calc.sh ရဲ့ RESULT value ကို ပြောင်းလဲခဲ့တဲ့ commit အတိအကျပါပဲ။

၅ မိနစ် စမ်းကြည့်

ကိုယ်ပိုင် hotfix branch နဲ့ cherry-pick ဥပမာကို ပြန်လုပ်ပြီး cherry-pick လုပ်လိုက်တဲ့ commit ရဲ့ hash က မူလနဲ့ ကွဲသွားတာကို အတည်ပြုပါ။ ပြီးရင် bug ဘယ် commit က စတင်ခဲ့တယ်ဆိုတာ သေချာသိတဲ့ commit ခြောက်ခုခုနစ်ခုလောက် ဖန်တီးပြီး (ဥပမာ - value မှားနေတဲ့ function) git bisect start / bad / good သုံးပြီး ရှာကြည့်ပါ — Git ရဲ့ အဖြေက သင်သိထားတဲ့ commit နဲ့ ကိုက်ညီလား စစ်ပါ။

သတိလေးတစ်ချက်

merge မလုပ်ဘဲ cherry-pick ကို shortcut အဖြစ် အလွန်အကျွံသုံးရင် commit history ဟာ hash ကွဲပြားပြီး branch အနှံ့ ပျံ့နှံ့သွားကာ ဘယ်နေရာမှာ တကယ်သက်ရောက်ပြီးလဲဆိုတာ ခွဲခြားရခက်သွားပါတယ်။

git bisect reset run ဖို့ မေ့သွားရင် repository ဟာ မူလ branch အစား ရှာဖွေမှုအလယ်က detached-HEAD commit မှာ checkout ဖြစ်နေခဲ့ပါလိမ့်မယ်။

Git - git-bisect DocumentationGit & GitHub

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • merge မလုပ်ဘဲ cherry-pick ကို shortcut အဖြစ် အလွန်အကျွံသုံးရင် commit history ဟာ hash ကွဲပြားပြီး branch အနှံ့ ပျံ့နှံ့သွားကာ ဘယ်နေရာမှာ တကယ်သက်ရောက်ပြီးလဲဆိုတာ ခွဲခြားရခက်သွားပါတယ်။
  • git bisect reset run ဖို့ မေ့သွားရင် repository ဟာ မူလ branch အစား ရှာဖွေမှုအလယ်က detached-HEAD commit မှာ checkout ဖြစ်နေခဲ့ပါလိမ့်မယ်။
  • Destructive (သို့) history ပြောင်းလဲနိုင်တဲ့ command တိုင်းကို run မခင် git status နဲ့ လက်ရှိအခြေအနေကို အမြဲစစ်ပါ။

လေ့ကျင့်ခန်း

ကိုယ်ပိုင် hotfix branch နဲ့ cherry-pick ဥပမာကို ပြန်လုပ်ပြီး cherry-pick လုပ်လိုက်တဲ့ commit ရဲ့ hash က မူလနဲ့ ကွဲသွားတာကို အတည်ပြုပါ။ ပြီးရင် bug ဘယ် commit က စတင်ခဲ့တယ်ဆိုတာ သေချာသိတဲ့ commit ခြောက်ခုခုနစ်ခုလောက် ဖန်တီးပြီး (ဥပမာ - value မှားနေတဲ့ function) git bisect start / bad / good သုံးပြီး ရှာကြည့်ပါ — Git ရဲ့ အဖြေက သင်သိထားတဲ့ commit နဲ့ ကိုက်ညီလား စစ်ပါ။

You'll know it worked when: Cherry-pick — cherry-pick ပြီးနောက် main ပေါ်က git log --oneline: 9fe14a1 Fix null pointer crash 5a74be8 Update readme e4fa43b Initial commit 9fe14a1 ဟာ မူလ hotfix commit ရဲ့ hash (8c3ee50) နဲ့ မတူပါဘူး — parent ကွဲသွားလို့ပါ။ Bisect — check.sh ကို good behavior အတွက် exit 0၊ bug အတွက် exit 1 ပြန်အောင် script ရေးထားလို့ က search တစ်ခုလုံးကို လူမပါဘဲ အလိုအလျောက် run ပေးပါတယ်။ Git က midpoint commit တစ်ခုချင်းစီကို checkout လုပ်ပြီး check.sh ကို run ကာ exit code ကို good/bad အဖြေအဖြစ် အလိုအလျောက် သုံးပါတယ်: Bisecting: 1 revision left to test after this (roughly 1 step) [<hash>] Add multiply (introduces bug) running './check.sh' Bisecting: 0 revisions left to test after this (roughly 0 steps) [<hash>] Add subtract running './check.sh' <hash> is the first bad commit commit <hash> Add multiply (introduces bug) calc.sh | 2 +- history.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) bisect found first bad commit Git က "Add multiply (introduces bug)" ကို first bad commit အဖြစ် မှန်ကန်စွာ ရှာတွေ့ပါတယ် — calc.sh ရဲ့ RESULT value ကို ပြောင်းလဲခဲ့တဲ့ commit အတိအကျပါပဲ။

Cherry-pick နှင့် Bisect | Thuta Learning