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

ပရောဂျက် — Developer နှစ်ယောက်၊ File တစ်ခု — Collaboration နဲ့ Conflict

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

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

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

ဒီ project က branching, remote, push, pull, conflict resolution အားလုံးကို developer နှစ်ယောက် file တစ်ခုတည်းကို တစ်ချိန်တည်းပြင်နေတဲ့ လက်တွေ့ scene တစ်ခုထဲမှာ ပေါင်းစည်းထားပြီး ဘာမှ ရိုးရှင်းအောင် ချန်ထားခြင်း မရှိပါဘူး။

  • developer နှစ်ယောက်စလုံး shared repository တစ်ခုတည်းကို clone လုပ်ပြီး history အတူတူကနေ စကြတယ်
  • Developer A က အရင်ဆုံး commit + push လုပ်လိုက်တာကို Git က fast-forward အဖြစ် လက်ခံတယ်
  • Developer B ရဲ့ push ကို remote က သူမသိဘဲ ရွေ့သွားလို့ ပယ်ချခံရတယ်
  • git pull က shared line ပေါ်မှာ real merge conflict တစ်ခုကို ဖြစ်ပေါ်စေတယ်
  • ဖြေရှင်းတာက Git အလိုအလျောက်လုပ်လို့မရဘဲ လူကိုယ်တိုင် ဆုံးဖြတ်ရမယ့် အလုပ်ပါ

ဒီ rejection ဟာ bug မဟုတ်ပါဘူး။ Git က teammate ရဲ့ push ပြီးသား အလုပ်ကို တိတ်တဆိတ် overwrite မဖြစ်အောင် team ကို ကာကွယ်ပေးပြီး နောက်ထပ် push မအောင်မြင်ခင် pull လုပ်ခိုင်းနေတာပါ။

ပယ်ချခံရတဲ့ push ဟာ bug မဟုတ်ပါ

ဒါက remote မှာ local မှာမရှိသေးတဲ့ commit ရှိနေတယ်လို့ ဆိုလိုတာပါ။ ဖြေရှင်းနည်းက အမြဲတမ်း အတူတူပါပဲ — pull (fetch + merge/rebase) လုပ်ပါ၊ conflict ရှိရင် ဖြေရှင်းပါ၊ ပြီးမှ ထပ်ပြီး push ပါ။

အခြေအနေGit ဘာလုပ်လဲ
Clean pushlocal history က remote ထက် ရှေ့ရောက်ပြီး divergence မရှိ — fast-forward၊ conflict မရှိ
Rejected pushremote မှာ local branch မရှိသေးတဲ့ commit ရှိနေ — pull မလုပ်ခင် push ငြင်းပယ်ခံရ
Merge conflictနှစ်ဖက်စလုံးက line တူတူကို ပြောင်းထား — Git ရပ်ပြီး လူကို ဆုံးဖြတ်ခိုင်း
text
TWO DEVELOPERS, ONE FILE: PUSH, REJECT, CONFLICT, RESOLVE
---------------------------------------------------------
            TEAM REPO (bare repo, stands in for GitHub)
                 ^                            ^
                 | clone                      | clone
                 |                            |
           DEV A CLONE                  DEV B CLONE
     edit config.py, line X       edit SAME config.py, line X
     commit (author: Aye)         commit (author: Banyar)
                 |                            |
     push main -> OK (fast-forward)           |
                 |                            |
     TEAM REPO now ahead ------------> push main -> REJECTED
                                       "fetch first" (remote moved)
                                               |
                                        git pull (fetch + merge)
                                               v
                                   CONFLICT in config.py:
                                   <<<<<<< HEAD (Banyar's line)
                                   =======
                                   >>>>>>> commit-hash (Aye's line)
                                               |
                                   edit file by hand, remove markers
                                   git add config.py
                                   git commit  (merge commit)
                                               |
                                        push main -> OK
                                               v
             TEAM REPO now holds both developers' changes

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

shared team repo ကို ဖန်တီးပါ

GitHub ကိုယ်စား bare repository တစ်ခုကို git init --bare နဲ့ ဖန်တီးပြီး folder နှစ်ခုကို clone နှစ်ကြိမ် လုပ်ပါ — developer တစ်ယောက်စီအတွက်တစ်ခု။

Developer A ပြင်ပြီး push လုပ်ပါ

shared file ရဲ့ line တစ်ကြောင်းကို ပြင်ပြီး A ရဲ့ pinned identity နဲ့ commit လုပ်ပြီး push ပါ။ A ရဲ့ history က remote နဲ့ ကိုက်ညီနေသေးလို့ ဒီ push က fast-forward အဖြစ် အောင်မြင်ပါတယ်။

Developer B က line တူတူကို မသိဘဲ ပြင်ပါ

A ရဲ့ push ကို မမြင်ရသေးတဲ့ clone ကနေ line တူတူကို မတူညီစွာ ပြင်ပြီး B ရဲ့ ကိုယ်ပိုင် pinned identity နဲ့ commit လုပ်ပါ။

Developer B ရဲ့ push ပယ်ချခံရတယ်

push ကြိုးစားလိုက်ရင် Git က ငြင်းပယ်ပြီး remote မှာ local မှာမရှိသေးတဲ့ အလုပ်ရှိတယ်လို့ ပြောပါတယ် — fetch first ဆိုပြီး။

Pull လုပ်ပြီး real conflict ကို ကြုံပါ

git pull က A ရဲ့ commit ကို fetch လုပ်ပြီး automatic merge ကြိုးစားပါတယ်။ edit နှစ်ခုစလုံးက line တူတူကို ထိနေလို့ မအောင်မြင်ဘဲ file ကို conflict marker အစစ်တွေနဲ့ merge ကြားထားခဲ့ပါတယ်။

လက်နဲ့ ဖြေရှင်းပါ

file ကိုဖွင့်ပြီး <<<<<<<, =======, >>>>>>> ကြားက ဗားရှင်းနှစ်ခုစလုံးကို ဖတ်ပါ၊ line က ဘာဆိုသင့်လဲ ဆုံးဖြတ်ပြီး marker အားလုံးကို ဖျက်ပါ။

Stage, commit ပြီး merge ကို push ပါ

ဖြေရှင်းပြီးသား file ကို git add လုပ်ပြီး merge ပြီးအောင် commit လုပ်ပါ၊ ပြီးရင် push ပါ — ဒီတစ်ကြိမ်တော့ developer နှစ်ယောက်စလုံးရဲ့ အလုပ်ကို အတူတူ ယူဆောင်ပြီး အောင်မြင်ပါလိမ့်မယ်။

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

bash
git init --bare /tmp/team-repo.git
git clone /tmp/team-repo.git /tmp/seed
cd /tmp/seed
export GIT_AUTHOR_NAME="Team Lead"
export GIT_AUTHOR_EMAIL="lead@example.com"
export GIT_COMMITTER_NAME="Team Lead"
export GIT_COMMITTER_EMAIL="lead@example.com"
export GIT_AUTHOR_DATE="2026-02-01T09:00:00"
export GIT_COMMITTER_DATE="2026-02-01T09:00:00"
cat > config.py <<'EOF'
# Application configuration

APP_NAME = "Thuta Widgets"
VERSION = "1.0.0"
DEBUG = False
EOF
git add config.py
git commit -m "Initial commit: add config.py"
git push origin main
cd ..

# Two developers each clone the same team repo
git clone /tmp/team-repo.git /tmp/dev-a
git clone /tmp/team-repo.git /tmp/dev-b

# --- Developer A ---
cd /tmp/dev-a
export GIT_AUTHOR_NAME="Developer Aye"
export GIT_AUTHOR_EMAIL="aye@example.com"
export GIT_COMMITTER_NAME="Developer Aye"
export GIT_COMMITTER_EMAIL="aye@example.com"
export GIT_AUTHOR_DATE="2026-02-01T10:00:00"
export GIT_COMMITTER_DATE="2026-02-01T10:00:00"
sed -i 's/DEBUG = False/DEBUG = True  # enabled for local testing/' config.py
git add config.py
git commit -m "Enable DEBUG mode for local testing"
git push origin main   # succeeds: fast-forward

# --- Developer B (has not seen A's push yet) ---
cd /tmp/dev-b
export GIT_AUTHOR_NAME="Developer Banyar"
export GIT_AUTHOR_EMAIL="banyar@example.com"
export GIT_COMMITTER_NAME="Developer Banyar"
export GIT_COMMITTER_EMAIL="banyar@example.com"
export GIT_AUTHOR_DATE="2026-02-01T10:30:00"
export GIT_COMMITTER_DATE="2026-02-01T10:30:00"
sed -i 's/DEBUG = False/DEBUG = os.environ.get("DEBUG", "false") == "true"/' config.py
git add config.py
git commit -m "Read DEBUG flag from environment variable"
git push origin main   # REJECTED -- remote has A's commit

git pull origin main   # fetch + merge -> real CONFLICT
cat config.py           # shows <<<<<<< / ======= / >>>>>>> markers

# Resolve by hand: pick the final version, remove every marker
cat > config.py <<'EOF'
# Application configuration

APP_NAME = "Thuta Widgets"
VERSION = "1.0.0"
DEBUG = os.environ.get("DEBUG", "true") == "true"  # defaults on for local dev
EOF
git add config.py
git commit -m "Merge branch 'main' of team-repo, resolve DEBUG conflict"
git push origin main   # succeeds now
You should see
Developer A ရဲ့ push က ရှင်းရှင်းလင်းလင်း အောင်မြင်ပါတယ်:

   4a5335c..75007aa  main -> main

Developer B ရဲ့ push ကတော့ လုံးဝ ပယ်ချခံရပါတယ်:

 ! [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
 hint: not have locally...

Developer B အနေနဲ့ git pull run လိုက်ရင် A ရဲ့ commit ကို fetch လုပ်ပြီး automatic merge ကြိုးစားပေမယ့် line တူတူပေါ်မှာ မအောင်မြင်ပါဘူး:

Auto-merging config.py
CONFLICT (content): Merge conflict in config.py
Automatic merge failed; fix conflicts and then commit the result.

git status ကလည်း အတည်ပြုပါတယ်:

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   config.py

config.py ကိုဖွင့်လိုက်ရင် Git ရဲ့ real conflict marker၊ ဗားရှင်းနှစ်ခုကို ယှဉ်ပြထားတာ တွေ့ရပါတယ်:

<<<<<<< HEAD
DEBUG = os.environ.get("DEBUG", "false") == "true"
=======
DEBUG = True  # enabled for local testing
>>>>>>> 75007aa66326065e94a973a8f81a152cd9144142

ဗားရှင်းနှစ်ခုစလုံးကို ပေါင်းစပ်အောင် file ကို လက်နဲ့ ပြင်၊ stage လုပ်၊ merge ကို commit လုပ်ပြီးတဲ့နောက် နောက်ဆုံး push ကတော့ အောင်မြင်ပါတယ်:

   75007aa..83b66b7  main -> main

git log --graph ကို run လိုက်ရင် developer နှစ်ယောက်ရဲ့ commit နှစ်ခုစလုံးကို merge commit တစ်ခုအောက်မှာ ထိန်းသိမ်းထားတာ တွေ့ရပါလိမ့်မယ်။

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

scene တူတူကို ထပ်လုပ်ကြည့်ပါ၊ ဒါပေမယ့် ဒီတစ်ကြိမ် developer နှစ်ယောက်စလုံးကို main ပေါ်တိုက်ရိုက် commit မလုပ်စေဘဲ သီးခြား feature branch တွေ (dev-a/fix-debug နဲ့ dev-b/fix-debug) ပေါ်မှာ edit လုပ်ခိုင်းပါ၊ Developer A ရဲ့ branch ကို main ဆီ အရင် merge လုပ်ပြီးမှ Developer B ရဲ့ branch ကို merge ကြည့်ပါ — conflict က push အချိန်မှာ မဟုတ်ဘဲ merge အချိန်မှာသာ ဖြစ်လာမလားဆိုတာ ကြည့်ပါ။

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

branch တစ်ခုမှာ မဟုတ်ဘဲ main ပေါ်တိုက်ရိုက် commit လုပ်တာကြောင့် conflict တစ်ခုက pull request တစ်ခုတည်းမှာ ကန့်သတ်မနေဘဲ team တစ်ခုလုံးရဲ့ shared history ကို ပိတ်ဆို့နေခြင်း။

ပယ်ချခံရတဲ့ push ကို 'ဖြတ်ကျော်' ဖို့ pull ပြီး conflict ဖြေရှင်းမည့်အစား git push --force သုံးခြင်း — ဒါက teammate ရဲ့ push ပြီးသား commit ကို တိတ်တဆိတ် ဖျက်ပစ်နိုင်ပါတယ်။

GitHub Docs: Resolving a merge conflict using the command lineGit & GitHub

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

  • branch တစ်ခုမှာ မဟုတ်ဘဲ main ပေါ်တိုက်ရိုက် commit လုပ်တာကြောင့် conflict တစ်ခုက pull request တစ်ခုတည်းမှာ ကန့်သတ်မနေဘဲ team တစ်ခုလုံးရဲ့ shared history ကို ပိတ်ဆို့နေခြင်း။
  • ပယ်ချခံရတဲ့ push ကို 'ဖြတ်ကျော်' ဖို့ pull ပြီး conflict ဖြေရှင်းမည့်အစား git push --force သုံးခြင်း — ဒါက teammate ရဲ့ push ပြီးသား commit ကို တိတ်တဆိတ် ဖျက်ပစ်နိုင်ပါတယ်။
  • Destructive (သို့) history ပြောင်းလဲနိုင်တဲ့ command တိုင်းကို run မခင် git status နဲ့ လက်ရှိအခြေအနေကို အမြဲစစ်ပါ။

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

scene တူတူကို ထပ်လုပ်ကြည့်ပါ၊ ဒါပေမယ့် ဒီတစ်ကြိမ် developer နှစ်ယောက်စလုံးကို main ပေါ်တိုက်ရိုက် commit မလုပ်စေဘဲ သီးခြား feature branch တွေ (dev-a/fix-debug နဲ့ dev-b/fix-debug) ပေါ်မှာ edit လုပ်ခိုင်းပါ၊ Developer A ရဲ့ branch ကို main ဆီ အရင် merge လုပ်ပြီးမှ Developer B ရဲ့ branch ကို merge ကြည့်ပါ — conflict က push အချိန်မှာ မဟုတ်ဘဲ merge အချိန်မှာသာ ဖြစ်လာမလားဆိုတာ ကြည့်ပါ။

You'll know it worked when: Developer A ရဲ့ push က ရှင်းရှင်းလင်းလင်း အောင်မြင်ပါတယ်: 4a5335c..75007aa main -> main Developer B ရဲ့ push ကတော့ လုံးဝ ပယ်ချခံရပါတယ်: ! [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 hint: not have locally... Developer B အနေနဲ့ git pull run လိုက်ရင် A ရဲ့ commit ကို fetch လုပ်ပြီး automatic merge ကြိုးစားပေမယ့် line တူတူပေါ်မှာ မအောင်မြင်ပါဘူး: Auto-merging config.py CONFLICT (content): Merge conflict in config.py Automatic merge failed; fix conflicts and then commit the result. git status ကလည်း အတည်ပြုပါတယ်: Unmerged paths: (use "git add <file>..." to mark resolution) both modified: config.py config.py ကိုဖွင့်လိုက်ရင် Git ရဲ့ real conflict marker၊ ဗားရှင်းနှစ်ခုကို ယှဉ်ပြထားတာ တွေ့ရပါတယ်: <<<<<<< HEAD DEBUG = os.environ.get("DEBUG", "false") == "true" ======= DEBUG = True # enabled for local testing >>>>>>> 75007aa66326065e94a973a8f81a152cd9144142 ဗားရှင်းနှစ်ခုစလုံးကို ပေါင်းစပ်အောင် file ကို လက်နဲ့ ပြင်၊ stage လုပ်၊ merge ကို commit လုပ်ပြီးတဲ့နောက် နောက်ဆုံး push ကတော့ အောင်မြင်ပါတယ်: 75007aa..83b66b7 main -> main git log --graph ကို run လိုက်ရင် developer နှစ်ယောက်ရဲ့ commit နှစ်ခုစလုံးကို merge commit တစ်ခုအောက်မှာ ထိန်းသိမ်းထားတာ တွေ့ရပါလိမ့်မယ်။

ပရောဂျက် — Developer နှစ်ယောက်၊ File တစ်ခု — Collaboration နဲ့ Conflict | Thuta Learning