ทำงานร่วมกัน 2 คนบน Branch เดียวกัน: ปัญหาที่พบบ่อยและวิธีแก้

เมื่อสองคน (หรือมากกว่า) ทำงานบน branch เดียวกันใน Git ระบบจะเกิดความท้าทายและปัญหาต่างๆ ที่อาจทำให้งานสูญหาย การรู้วิธีจัดการปัญหาเหล่านี้เป็นสิ่งสำคัญสำหรับการทำงานเป็นทีม บทความนี้จะอธิบายปัญหาทั่วไป วิธีแก้ไข และ best practices ในการทำงานร่วมกันอย่างมีประสิทธิภาพ

ปัญหาทั่วไปเมื่อทำงานร่วมกันบน Branch เดียว

เมื่อสองคนทำงานบน branch เดียวกัน จะเกิดปัญหาต่างๆ ที่อาจทำให้งานเสียหายหรือสูญเสีย ต่อไปนี้คือปัญหาที่พบบ่อยที่สุดและวิธีการจัดการ

ปัญหา #1: Push Rejection (Non-Fast-Forward Error)

สถานการณ์ที่เกิดขึ้นบ่อยครั้ง:

  • คนที่ 1 ทำการ commit และ push ขึ้นไป
  • คนที่ 2 ยังไม่ทำการ pull จากเซิร์ฟเวอร์
  • คนที่ 2 พยายาม push โดยคนที่ 1 ได้ push ไปแล้ว
  • Git ปฏิเสธการ push เพราะ branch บนเซิร์ฟเวอร์มี commit ใหม่ที่ไม่มีใน local repository ของคนที่ 2

Error message ที่จะเห็น:

! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to 'origin'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g. 'git pull')
hint: before pushing again.

วิธีแก้: ต้อง pull ข้อมูลล่าสุดก่อนเสมอ

git pull origin branch-name
git push origin branch-name

คำสั่ง pull จะดึง commits ที่ใหม่ที่สุดจากเซิร์ฟเวอร์มา และ merge เข้าไปใน local branch ของคุณ หากไม่มี conflict จะ merge โดยอัตโนมัติ

ปัญหา #2: Merge Conflict

นี่คือปัญหาที่ซับซ้อนกว่า เกิดขึ้นเมื่อทั้งสองคนแก้ไขบรรทัดเดียวกันในไฟล์เดียวกัน Git ไม่สามารถ merge อัตโนมัติได้เพราะไม่รู้ว่าเวอร์ชันไหนถูกต้อง

ตัวอย่างสถานการณ์:

  • คนที่ 1 แก้ไขบรรทัด 5 ในไฟล์ config.js เป็น const API_URL = “https://api1.example.com”
  • คนที่ 2 แก้ไขบรรทัด 5 เดียวกันเป็น const API_URL = “https://api2.example.com”
  • เมื่อคนที่ 2 ทำการ pull หลังจากคนที่ 1 push ไปแล้ว Git จะพบ conflict
$ git pull origin main
AUTO_MERGING src/config.js
CONFLICT (content): Merge conflict in src/config.js
Automatic merge failed; fix conflicts and then commit the result.

เมื่อเปิดไฟล์ config.js จะเห็นเนื้อหา conflict marker:

<<<<<<< HEAD
const API_URL = "https://api1.example.com";
=======
const API_URL = "https://api2.example.com";
>>>>>>> origin/main

วิธีแก้ Merge Conflict:

  • เปิดไฟล์ที่มี conflict ด้วย text editor
  • แก้ไขส่วนที่ conflict โดยเลือกเวอร์ชันที่ถูกต้อง หรือรวมทั้งสองเวอร์ชัน
  • ลบ conflict markers (<<<<<<< HEAD, =======, >>>>>>> origin/main)
  • บันทึกไฟล์
  • Stage และ commit การแก้ไข
# หลังจากแก้ไขไฟล์แล้ว
git add src/config.js
git commit -m "Resolve merge conflict in config.js: use api1.example.com after discussion with team"

หมายเหตุ: บางครั้งสามารถใช้ merge tools เช่น VS Code, Sublime Text, หรือ GitKraken เพื่อแก้ไข conflict ได้ง่ายกว่า

ปัญหา #3: Lost Work / Overwriting Changes

นี่คือปัญหาที่เลวร้ายที่สุด เมื่อคนที่ 2 ลืม pull ข้อมูลล่าสุด และทำการ force push โดยใช้ flag -f หรือ –force work ของคนที่ 1 อาจสูญหาย

สถานการณ์ที่เสี่ยง:

  • คนที่ 1 push commit abc123 ที่ลบ function oldAPI() และเพิ่ม function newAPI()
  • คนที่ 2 ยังทำงานกับ local copy เก่าที่มี function oldAPI() อยู่
  • คนที่ 2 ทำการ force push โดยไม่ pull ก่อน
  • commit abc123 ของคนที่ 1 จะถูก overwrite และ newAPI() function จะหายไป

วิธีป้องกัน: ห้ามใช้ force push บนทั่วไป โดยเฉพาะถ้าเป็น shared branch ที่มีคนอื่นทำงานด้วย

# AVOID - ห้ามใช้บน shared branches
git push -f origin main
git push --force origin main

# SAFER - ใช้ --force-with-lease เพื่อให้ safe ขึ้น
git push --force-with-lease origin branch-name

flag –force-with-lease จะ reject push หากมี commit ใหม่บนเซิร์ฟเวอร์ที่คุณไม่รู้จัก ช่วยป้องกันการสูญหาย work ของคนอื่น

ปัญหา #4: Stale Branch Information

บางครั้งข้อมูล remote branch บน local machine ของคุณอาจเก่า ทำให้คิดว่า branch ยังไม่มี commits ใหม่ แต่จริงๆ แล้วมี commits ใหม่บนเซิร์ฟเวอร์

วิธีแก้: ใช้ fetch เพื่ออัปเดตข้อมูล remote tracking branches

# ดึงข้อมูล remote ล่าสุดโดยไม่ merge
git fetch origin

# ดู commits ล่าสุดบน remote branch
git log origin/main

# ดู status เทียบกับ remote
git status

1. Always Pull Before Push

นี่คือกฎสำคัญที่สุด ทุกครั้งก่อนทำการ push ต้อง pull ข้อมูลล่าสุดจากเซิร์ฟเวอร์ก่อนเสมอ

# Workflow ที่ถูกต้อง
git status                    # ตรวจสอบสถานะ
git add .                     # Stage changes
git commit -m "Description"   # Commit
git pull origin main          # Pull ข้อมูลล่าสุด
# หากมี conflict ให้แก้ไข
git push origin main          # Push ขึ้นไป

2. ใช้ Feature Branch แทน Shared Branches

best practice ที่สำคัญคือ ให้แต่ละคนสร้าง feature branch ของตนเอง ห้ามทำงานโดยตรงบน main หรือ master branch

# สำหรับคนที่ 1 - ทำ feature user authentication
git checkout -b feature/user-auth
# ทำงาน commit ต่างๆ
git push origin feature/user-auth

# สำหรับคนที่ 2 - ทำ feature payment integration
git checkout -b feature/payment
# ทำงาน commit ต่างๆ
git push origin feature/payment

ด้วยวิธีนี้ branch หลักจะปลอดภัย และปัญหา merge conflict จะลดลงมาก

3. Communicate และ Coordinate ระหว่างสมาชิกทีม

การสื่อสารที่ดีคือสิ่งสำคัญ บอกให้ทีมรู้:

  • คุณกำลังทำอะไรใน branch ไหน
  • ไฟล์ไหนที่คุณกำลังแก้ไข เพื่อไม่ให้คนอื่นแก้ไขไฟล์เดียวกัน
  • ประมาณเวลาที่จะ commit และ push
  • หากใกล้จะ merge branch ลงมา main บอกให้ทีมรู้ก่อน

ใช้ tools เช่น Slack, Discord, หรือ project management tools เพื่อประสานงานกับทีม

4. ใช้ Pull Request (PR) และ Code Review

นี่คือ best practice ที่นิยมใช้ในทีมมืออาชีพ PR ช่วยให้:

  • สมาชิกอื่นสามารถรีวิว code ของคุณก่อน merge
  • ลดความเสี่ยงของ bug หรือ broken code ใน main branch
  • สร้าง discussion เกี่ยวกับการออกแบบ implementation
  • เพิ่มเติม documentation และ context ของการเปลี่ยนแปลง
# Workflow ด้วย PR
1. สร้าง feature branch
   git checkout -b feature/new-api

2. ทำงาน commit
   git add .
   git commit -m "Implement new API endpoint"

3. Push ขึ้นไป
   git push origin feature/new-api

4. สร้าง PR จาก GitHub/GitLab web interface
   - Add description ที่ชัดเจน
   - Request reviewers

5. รอการ approve จากอย่างน้อย 1 reviewer

6. Merge PR (โดยทั่วไปใช้ Squash or Rebase merge)

5. ทำ Rebase หรือ Squash Commits ก่อน Merge

เมื่อก่อน merge feature branch ลงมา main ให้ clean up commit history ทำให้สามารถเข้าใจการเปลี่ยนแปลงได้ง่ายขึ้น

# Squash commits เป็น 1 commit เดียว
git rebase -i HEAD~3  # Interactive rebase 3 commits ล่าสุด

# หรือ squash ขณะ merge PR
# สำหรับ GitHub: เลือก "Squash and merge" ในปุ่ม merge

Recommended Complete Workflow

นี่คือ workflow ที่ recommended สำหรับทีมที่ทำงานกับ ผู้ให้บริการโฮสติ้ง Cloud VPS หรือ server อื่นๆ

# 1. สร้าง feature branch จาก main ล่าสุด
git checkout main
git pull origin main
git checkout -b feature/my-feature

# 2. ทำงาน และ commit เพียงสองสามครั้ง
git add src/myfile.js
git commit -m "Add user validation logic"

# 3. ตรวจสอบว่า main มี commits ใหม่ไหม
git fetch origin
git log --oneline main..origin/main

# 4. หากมี commits ใหม่ ให้ rebase feature branch
git rebase origin/main

# 5. Push feature branch ขึ้นไป
git push origin feature/my-feature

# 6. สร้าง Pull Request บน GitHub/GitLab
# เพิ่มรายละเอียด description ที่ชัดเจน

# 7. รอการ approve จากทีม

# 8. Squash and merge PR

# 9. ลบ feature branch เก่า
git branch -d feature/my-feature
git push origin --delete feature/my-feature

ใช้ Git Hooks สำหรับ Automation

บน ผู้ให้บริการโฮสติ้ง VPS สามารถตั้งค่า git hooks เช่น pre-commit เพื่อรัน tests โดยอัตโนมัติ ก่อน commit

# ตัวอย่าง .git/hooks/pre-commit
#!/bin/bash
echo "Running tests..."
npm test
if [ $? -ne 0 ]; then
  echo "Tests failed. Commit aborted."
  exit 1
fi

Stash Changes ชั่วคราว

หากคุณอยากเปลี่ยน branch แต่ยังไม่พร้อมจะ commit ใช้ git stash

# บันทึกการเปลี่ยนแปลงชั่วคราว
git stash

# เปลี่ยน branch
git checkout main

# หลังจาก pull ข้อมูลใหม่ กลับไป feature branch
git checkout feature/my-feature

# คืนการเปลี่ยนแปลง
git stash pop

ตั้งค่า .gitignore ให้เหมาะสม

โปรแกรมที่ generate files อัตโนมัติ (node_modules, .env, build files) ไม่ควร commit ให้เพิ่มลงใน .gitignore

# .gitignore
node_modules/
.env
.env.local
dist/
build/
*.log
.DS_Store

สรุป

การทำงานร่วมกันบน branch เดียวกันต้องการ discipline, communication, และ best practices ที่ดี หากทำตามขั้นตอนดังกล่าว ปัญหาส่วนใหญ่สามารถป้องกันได้ เมื่อเกิด conflict ให้แก้ไขอย่างรอบคอบ และสื่อสารกับสมาชิกทีมเสมอ