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

လေ့ကျင့်ခန်း — Git ပြဿနာကို Diagnose လုပ်ခြင်း

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

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

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

Git က မင်းတောင်းဆိုတဲ့အရာကို ငြင်းပယ်တဲ့အခါ, fix တစ်ခုကို ခန့်မှန်းပြီး ထပ်စမ်းချင်စိတ် ဖြစ်တတ်ပါတယ်။ ဒီအလေ့အထကြောင့် ပြဿနာသေးလေးက ပြဿနာကြီးဖြစ်လာတတ်ပါတယ်။ Git troubleshooting ရဲ့ တကယ့် skill က diagnosis ပါ — တခြားဘာမှ မထိခင် Git က ဘာပြောနေလဲ အတိအကျ ဖတ်ရမှာပါ။

  • `git status` — working directory နဲ့ staging area လက်ရှိ ဘယ်လိုပုံစံလဲ။
  • `git log --oneline --graph --all` — သိထားတဲ့ branch နဲ့ remote-tracking branch အားလုံးရဲ့ history တကယ့်ပုံစံ။

Git ရဲ့ error နဲ့ status message တွေက အံ့ဩစရာလောက် literal ဖြစ်ပါတယ် — rejected push, merge conflict marker, "detached HEAD" warning တစ်ခုစီက repository ရဲ့ တကယ့် state ကို ညွှန်ပြနေတာပါ၊ မရေရာတဲ့ ညည်းညူချက် မဟုတ်ပါဘူး။ အထက်က command နှစ်ခုက ဘာမှမလုပ်ခင် လိုအပ်တဲ့ မေးခွန်းနှစ်ခုကို ဖြေပေးပါတယ် — ငါဘယ်နေရာမှာရှိလဲ, history က ဘယ်လို ဒီနေရာရောက်လာခဲ့လဲ။

ဒီသင်ခန်းစာက concrete case တစ်ခုကို လေ့လာပါမယ် — local clone မှာ တစ်ခါမှ မမြင်ဖူးတဲ့ commit တွေ remote မှာ ရှိနေလို့ Git က ငြင်းပယ်တဲ့ `git push` — branch တစ်ခုတည်းပေါ်မှာ sync မလုပ်ဘဲ လူနှစ်ယောက် အလုပ်လုပ်နေတဲ့ classic symptom ပါ။ GitHub ရဲ့ ကိုယ်စား local bare repository တစ်ခုနဲ့ rejection ကို အစစ်အမှန် ပြန်ဖန်တီးရပါမယ်။

Hint line တွေကို ဖတ်ပါ

Rejected push နောက်ပိုင်း Git ရဲ့ `hint:` line တွေက ဖြည့်စွက်စာမဟုတ်ပါဘူး — တကယ့်အကြောင်းရင်းနဲ့ ရှေ့ဆက်ရမယ့်လမ်းကို ရှင်းပြထားတာပါ။ Error ကို Google မရှာခင် ဒါတွေကို ဖတ်ရင် အချိန်တကယ်သက်သာပါတယ်။

Diverge လုပ်နေတဲ့ branch, detached HEAD, (သို့) မှားနေတဲ့ staged file တစ်ခုစီအတွက် ဖြေရှင်းတဲ့ command တွေက အမှန်တကယ် ကွဲပြားပါတယ်။ Diagnostic အလေ့အထ — message ဖတ်ပါ, status စစ်ပါ, history စစ်ပါ, ပြီးမှ လုပ်ဆောင်ပါ — ဆိုတာချည်းက Git ပြဿနာတိုင်းကို ကူညီပေးနိုင်တဲ့ တစ်ခုတည်းသော skill ပါ။

text
PUSH REJECTED: LOCAL MAIN VS ORIGIN/MAIN
----------------------------------------
origin/main (bare repo)          your local "you" clone
------------------------         ------------------------
24e9b92 Initial commit           24e9b92 Initial commit
3e8f241 Add Contributing         44aff82 Add Installation
  ^ teammate pushed this           ^ you committed this,
    -- you don't have it            origin doesn't have it
       locally yet

                git push origin main
                        |
                        v
        ! [rejected]   main -> main (fetch first)
   "remote contains work that you do not have locally"

AFTER: git fetch reveals the divergence, then merge + push
  origin/main == local main == one new merge commit

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

ဒါကို အစစ်အမှန်ဖြစ်အောင်, GitHub remote ရဲ့ ကိုယ်စား local bare repository တစ်ခုတည်းသုံးပြီး လူနှစ်ယောက်ပါတဲ့ team ကလေးတစ်ခု တည်ဆောက်ပါမယ်။ Bare repo (`git init --bare`) မှာ working directory မရှိပါဘူး — GitHub ပေါ်ကရော `origin` လိုပဲ push/pull လုပ်ဖို့ရည်ရွယ်ချက်နဲ့ရှိတာပါ။

ကိုယ်တိုင်ကို ကိုယ်ဆောင်ရွက်ပါ

Bare repo ကို clone လုပ်ပြီး README commit ပထမဆုံးကို push လုပ်ပါ။

Teammate ကို ကိုယ်ဆောင်ရွက်ပါ

GIT_AUTHOR_NAME ကွဲပြားစွာသုံးပြီး ထပ်တူ bare repo ကို ထပ်ကာ clone လုပ်ပြီး ဒုတိယ commit ကို တိုက်ရိုက် push လုပ်ပါ။

ကိုယ့် clone ကို ပြန်လာပြီး, fetch မလုပ်ဘဲ ကိုယ့် change ကို commit လုပ်ပြီး `git push` run ပါ။ Git က ငြင်းပယ်ပါလိမ့်မယ် — bug မဟုတ်ပါဘူး, Git က shared history ကို တိတ်တဆိတ် overwrite မဖြစ်အောင် ကာကွယ်နေတာပါ။

ပြသထားတဲ့ rejection text အတိအကျကို ဖတ်ပြီး, `git status` နဲ့ `git fetch` ကို သုံးကာ ကိုယ့် branch နဲ့ `origin/main` ဘယ်လိုကွဲထွက်နေလဲ ဆုံးဖြတ်ခင် တိတိကျကျ ကြည့်ပါ။ အဆုံးမှာ တကယ့် push rejection တစ်ခု ဖြစ်ပျက်တာကို ကြည့်ရမယ်, team အစစ်မှာလုပ်သလိုပဲ ဖြေရှင်းပေးရပါမယ်။

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

bash
# One-time setup
git config --global init.defaultBranch main

# Create a bare repo to stand in for a GitHub remote
git init --bare team-repo.git

# --- You: clone it and push the first commit ---
git clone team-repo.git you
cd you
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"
export GIT_AUTHOR_DATE="2026-01-01T09:00:00"
export GIT_COMMITTER_DATE="2026-01-01T09:00:00"
echo "# Team Project" > README.md
echo "Initial setup." >> README.md
git add README.md
git commit -m "Initial commit: add README"
git push origin main
cd ..

# --- Teammate: clone the SAME bare repo, push a second commit ---
git clone team-repo.git teammate
cd teammate
export GIT_AUTHOR_NAME="Maung Maung"
export GIT_AUTHOR_EMAIL="maungmaung@example.com"
export GIT_COMMITTER_NAME="Maung Maung"
export GIT_COMMITTER_EMAIL="maungmaung@example.com"
export GIT_AUTHOR_DATE="2026-01-01T10:15:00"
export GIT_COMMITTER_DATE="2026-01-01T10:15:00"
echo "" >> README.md
echo "## Contributing" >> README.md
echo "See CONTRIBUTING.md for guidelines." >> README.md
git add README.md
git commit -m "Add Contributing section to README"
git push origin main
cd ..

# --- You again: commit locally WITHOUT fetching first, then push ---
cd you
export GIT_AUTHOR_DATE="2026-01-01T11:00:00"
export GIT_COMMITTER_DATE="2026-01-01T11:00:00"
echo "" >> README.md
echo "## Installation" >> README.md
echo "Run npm install to get started." >> README.md
git add README.md
git commit -m "Add Installation section to README"
git push origin main

# --- Diagnose: what does Git actually tell us? ---
git status
git log --oneline
git fetch origin
git log --oneline --graph --all
git status
You should see
နောက်ဆုံး push ကို ငြင်းပယ်ခံရပါတယ် —

To .../team-repo.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to '.../team-repo.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.

Fetch မလုပ်ခင်, `git status` က —

On branch main
Your branch is ahead of 'origin/main' by 1 commit.

ဒါက technically မှန်ပေမယ့် လှည့်ဖြားတတ်ပါတယ် — အခုလက်ရှိ remote ကို မဟုတ်ဘဲ နောက်ဆုံး fetch ကို ရေရာနေတာပါ။ `git fetch origin` ပြီးနောက်, `git log --oneline --graph --all` က "Initial commit" ancestor တူတူကနေ ခွဲထွက်သွားတဲ့ branch နှစ်ခုကို ပြပြီး, `git status` က တကယ့်ပုံစံကို ယခု ပြောပါတယ် —

On branch main
Your branch and 'origin/main' have diverged,
and have 1 and 1 different commits each, respectively.

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

Teammate က သူ့ change ကို ပထမဆုံး merge လုပ်ခဲ့ပါတယ်။ မင်းက ကိုယ့် edit ကို ပြီးအောင်လုပ်, commit လုပ်ပြီး `git push origin main` run လိုက်ပါတယ် — ပုံမှန် `main -> main` success line အစား, Git က "! [rejected] main -> main (fetch first)" ကို ပြသပြီး "the remote contains work that you do not have locally" ဆိုတဲ့ hint ကို ဆက်ပြပါတယ်။ ဒီအတောအတွင်း `git status` က "Your branch is ahead of 'origin/main' by 1 commit" လို့ ဆက်ပြောနေပါတယ် — အားလုံးကောင်းနေသလို ကြားရပေမယ့်, စကားလုံးအပြည့်အစုံကို မပြောပါဘူး။ `git status` တစ်ခုတည်းက ပြမပြနိုင်တာကို ဘယ် command က ပြပေးမလဲ, branch နဲ့ remote ကို ပြန်ချိန်ညှိဖို့ ဆုံးဖြတ်ခင် history ရဲ့ ပုံသဏ္ဌာန်ကို ဘာကြည့်သင့်လဲ?

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

Rejection ကို ဖျောက်ဖို့ `git push --force` ကို ချက်ချင်းသုံးလိုက်ရင် teammate ရဲ့ commit တွေကို တိတ်တဆိတ် overwrite ဖြစ်စေနိုင်ပါတယ်။

Push ငြင်းပယ်ခံရပြီးနောက် `git status` တစ်ခုတည်းကို ယုံကြည်တာ လှည့်ဖြားတတ်ပါတယ် — နောက်ဆုံး fetch ကိုသာ ရေရာပြီး remote ရဲ့ လက်ရှိ state ကို မဟုတ်ပါဘူး။

Pro Git -- Working with RemotesGit & GitHub

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

  • Rejection ကို ဖျောက်ဖို့ `git push --force` ကို ချက်ချင်းသုံးလိုက်ရင် teammate ရဲ့ commit တွေကို တိတ်တဆိတ် overwrite ဖြစ်စေနိုင်ပါတယ်။
  • Push ငြင်းပယ်ခံရပြီးနောက် `git status` တစ်ခုတည်းကို ယုံကြည်တာ လှည့်ဖြားတတ်ပါတယ် — နောက်ဆုံး fetch ကိုသာ ရေရာပြီး remote ရဲ့ လက်ရှိ state ကို မဟုတ်ပါဘူး။
  • Destructive (သို့) history ပြောင်းလဲနိုင်တဲ့ command တိုင်းကို run မခင် git status နဲ့ လက်ရှိအခြေအနေကို အမြဲစစ်ပါ။

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

Teammate က သူ့ change ကို ပထမဆုံး merge လုပ်ခဲ့ပါတယ်။ မင်းက ကိုယ့် edit ကို ပြီးအောင်လုပ်, commit လုပ်ပြီး `git push origin main` run လိုက်ပါတယ် — ပုံမှန် `main -> main` success line အစား, Git က "! [rejected] main -> main (fetch first)" ကို ပြသပြီး "the remote contains work that you do not have locally" ဆိုတဲ့ hint ကို ဆက်ပြပါတယ်။ ဒီအတောအတွင်း `git status` က "Your branch is ahead of 'origin/main' by 1 commit" လို့ ဆက်ပြောနေပါတယ် — အားလုံးကောင်းနေသလို ကြားရပေမယ့်, စကားလုံးအပြည့်အစုံကို မပြောပါဘူး။ `git status` တစ်ခုတည်းက ပြမပြနိုင်တာကို ဘယ် command က ပြပေးမလဲ, branch နဲ့ remote ကို ပြန်ချိန်ညှိဖို့ ဆုံးဖြတ်ခင် history ရဲ့ ပုံသဏ္ဌာန်ကို ဘာကြည့်သင့်လဲ?

You'll know it worked when: နောက်ဆုံး push ကို ငြင်းပယ်ခံရပါတယ် — To .../team-repo.git ! [rejected] main -> main (fetch first) error: failed to push some refs to '.../team-repo.git' hint: Updates were rejected because the remote contains work that you do not hint: have locally. This is usually caused by another repository pushing to hint: the same ref. If you want to integrate the remote changes, use hint: 'git pull' before pushing again. Fetch မလုပ်ခင်, `git status` က — On branch main Your branch is ahead of 'origin/main' by 1 commit. ဒါက technically မှန်ပေမယ့် လှည့်ဖြားတတ်ပါတယ် — အခုလက်ရှိ remote ကို မဟုတ်ဘဲ နောက်ဆုံး fetch ကို ရေရာနေတာပါ။ `git fetch origin` ပြီးနောက်, `git log --oneline --graph --all` က "Initial commit" ancestor တူတူကနေ ခွဲထွက်သွားတဲ့ branch နှစ်ခုကို ပြပြီး, `git status` က တကယ့်ပုံစံကို ယခု ပြောပါတယ် — On branch main Your branch and 'origin/main' have diverged, and have 1 and 1 different commits each, respectively.

လေ့ကျင့်ခန်း — Git ပြဿနာကို Diagnose လုပ်ခြင်း | Thuta Learning