TL;DR: รัน git fetch upstream && git merge upstream/main && git push origin main แล้ว fork ของคุณตามทัน นั่นคือเวิร์กโฟลว์ “git sync fork กับ upstream” ทั้งหมดในหนึ่งบรรทัด — ดึงการเปลี่ยนแปลงจากโปรเจกต์ที่คุณ fork มา แล้วพุชเข้าสำเนาของตัวเอง ถ้าชอบประวัติเป็นเส้นตรง ให้เปลี่ยน merge เป็น git rebase upstream/main แล้ว force-push และถ้าคุณยังไม่เคยต่อ remote ชื่อ upstream เลย ให้เริ่มที่ขั้นตอน 1 ด้านล่าง เพราะ remote ที่หายไปนี่คือสาเหตุอันดับหนึ่งของอาการ “fork ซิงก์ไม่ได้” ที่เหลือทั้งหมด — rebase ปุ่มซิงก์ของ GitHub และ branch ที่แยกกันจนพุชไม่ได้ — เป็นแค่รายละเอียดทับบนสามคำสั่งนี้
ซิงก์ fork กับ upstream หมายถึงอะไร?
fork คือสำเนาของ repository คนอื่นบน GitHub ของคุณ ต้นฉบับคือ upstream สำเนาของคุณคือ origin fork บน GitHub ไม่อัปเดตตัวเอง — เมื่อผู้ดูแล merge pull request สำเนาของคุณก็ยังค้างกับโค้ดเมื่อวาน การซิงก์ fork คือการดึง commit ใหม่จาก upstream เข้ามาใน fork เพื่อให้ branch ของคุณตรงกับสถานะปัจจุบันของโปรเจกต์หรืออย่างน้อยก็มีมันด้วย
เรื่องนี้สำคัญสองเหตุผล หนึ่ง คือการมีส่วนร่วม: ทุก pull request ที่เปิดจาก fork ที่ล้าสมัยจะแถบเสียงรบกวนมาด้วย และผู้ดูแลจะให้คุณอัปเดตก่อน merge สอง คือการ self-host หรือการศึกษา: ถ้าคุณรัน fork ใน production หรือแค่อ่านโค้ด fork ที่เก่าหนึ่งเดือนคือการแก้บั๊กหนึ่งเดือนที่คุณไม่มี
ซิงก์ fork กับ upstream จาก command line อย่างไร?
สามขั้นตอน: ประกาศ upstream ครั้งเดียว ดึงจากมัน แล้ว merge กับพุช การต่อสายนี้ถาวร — ครั้งหน้าคุณพิมพ์แค่ขั้น 2 กับ 3
ขั้นตอน 1 — เพิ่ม remote ชื่อ upstream (ครั้งเดียวต่อการ clone)
# ภายในสำเนา local ของ fork
git remote add upstream https://github.com/ORIGINAL_OWNER/REPO.git
git remote -v # ยืนยัน: origin -> fork ของคุณ, upstream -> ต้นฉบับ หา URL ที่ถูกต้องจากหน้า repository ต้นฉบับ: ปุ่ม Code สีเขียว ความผิดพลาดที่พบบ่อยคือชี้ remote ทั้งสองไปที่ fork ของตัวเอง — แล้ว “การซิงก์” จะเงียบ ๆ ไม่ทำอะไรเลย เพราะคุณดึงจากสำเนาที่เก่าเท่ากับของคุณพอดี
ขั้นตอน 2 — fetch แล้ว merge branch ของ upstream
git checkout main
git fetch upstream
git merge upstream/main
git push origin main นี่คือคำตอบมาตรฐานของ “git sync fork กับ upstream ด้วย command line” ผลลัพธ์ปกติคือ fast-forward — main ของ fork คุณไม่มีอะไรใหม่ มันจึงไหลไปเทียบ upstream/main โดยไม่เกิด merge commit
ขั้นตอน 3 — ทำซ้ำตามต้องการ ไม่มีอะไรต้องจำเกิน git fetch upstream && git merge upstream/main && git push origin main ถ้าอยากรู้ว่าตกหล่นมาก่อน merge แค่ไหน ให้รัน git rev-list --count main..upstream/main หลัง fetch
ควร rebase หรือ merge ตอนซิงก์ fork?
ทั้งคู่พาโค้ดชุดเดียวกันเข้า fork ต่างกันที่ประวัติที่ทิ้งไว้ เลือกนโยบายเดียวต่อหนึ่ง repo แล้วยึดมั่น:
| วิธี | คำสั่ง | ผลต่อประวัติ | เหมาะกับ |
|---|---|---|---|
| Merge | git merge upstream/main | เกิด merge commit เพิ่มเมื่อ branch แยกกัน | Feature branch ที่มี PR เปิดอยู่ — ไม่เขียนทับอะไรเลย |
| Rebase | git rebase upstream/main | Commit ของคุณถูกเล่นซ้ำไว้บนสุด ประวัติเป็นเส้นตรง | รักษา main ของ fork ให้สะอาด; fork ที่แยกกันจนอยากรีเซ็ต |
| หน้า GitHub | ปุ่ม Sync branch / merge PR | เหมือน merge | ตามทันอย่างเร็วโดยไม่ต้องเปิด clone |
รูปแบบ rebase ของการซิงก์:
git fetch upstream
git rebase upstream/main
git push --force-with-lease origin main ต้อง force push เพราะ rebase เขียน commit ID ใหม่ — branch ฝั่ง remote ของ fork ไม่ได้สืบเชื้อสายจากของ local อีกต่อไป ให้เลือก --force-with-lease ทุกครั้งแทน --force: มันจะปฏิเสธถ้ามีคน (หรืออีกเครื่องของคุณ) พุชแทรกมาก่อน ซึ่งทำให้คำสั่งอันตรายกลายเป็นปลอดภัยโดยดีฟอลต์
กฎที่สมควรสักไว้ที่ข้อมือ: อย่า rebase branch ที่มี pull request เปิดอยู่ นอกจากคุณรู้ว่ากำลังทำอะไร — rebase เปลี่ยน commit ID และอาจทำให้ PR ที่เปิดอยู่หลุดจาก commit ของมัน ซิงก์ main ด้วย merge (หรือ rebase ก่อนเริ่มงานใหม่) แล้วเก็บ branch ของ PR ไว้นอกเรื่องนี้
ทำไม fork ของผมถึงซิงก์กับ upstream ไม่ได้?
สี่ผู้ต้องสงสัยประจำ เรียงตามลำดับที่เจอในเทอร์มินัลจริง:
- ไม่มี remote ชื่อ
upstream—git remote -vโชว์แค่originอาการ:git fetch upstreamล้มด้วยข้อความ'upstream' does not appear to be a git repositoryวิธีแก้: ขั้นตอน 1 ด้านบน - fetch แล้วแต่ไม่ merge — fetch อัปเดต
upstream/mainใน repo local แต่ไม่แตะ branch ทำงานสักตัว อาการ:git logยังดูเก่าทั้งที่ fetch สำเร็จ วิธีแก้:git merge upstream/main - ประวัติแยกทาง — คุณ commit ลง
mainของ fork และ upstream ก็เดินไปข้างหน้าเหมือนกันgit pullจะบ่นเรื่องประวัติไม่เกี่ยวข้องหรือบังคับ merge วิธีแก้ ถ้าคุณอยากให้ upstream ชนะ:git reset --hard upstream/main(ทิ้ง commit ที่มีเฉพาะใน main ของคุณ — เช็กgit stash listหรือสำรองเป็น branch ก่อน; ถ้า reset พลาดไปแล้ว ทางกู้คืนเหมือนกับใน git undo last commit:git reflogยังจำยอดเก่าได้อยู่) - push ถูกปฏิเสธเพราะไม่ใช่ fast-forward หลัง rebase — คุณ rebase แล้วพุชแบบปกติ วิธีแก้:
git push --force-with-lease origin main
กรณีที่ห้าที่พบน้อย: repo ต้นทางถูกเปลี่ยนชื่อหรือลบไป ทำให้ URL จากขั้น 1 ตอบ 404 GitHub จะ redirect repo ที่เปลี่ยนชื่อ ความล้มเหลวถาวรมักแปลว่าถูกลบหรือปิดเป็น private — ไม่มีอะไรให้ซิงก์แล้ว
ซิงก์ fork จากเว็บ GitHub ได้ไหม?
ได้ ในหน้า fork ของคุณ รายการ branch จะมีปุ่ม Sync fork ทุกครั้งที่ branch ของคุณตกหล่น; กดหนึ่งที upstream ก็ไหลเข้ามา ด้านล่างของหน้า วิธีเดียวกันทำได้ผ่าน pull request: เปิด PR จาก upstream/main เข้า main ของ fork แล้ว merge
ข้อจำกัดของปุ่มอธิบายว่าเมื่อไรควรกลับไปใช้ CLI: มันทำได้แค่ fast-forward หรือ merge — rebase ไม่ได้ และปฏิเสธเด็ดขาดเมื่อ branch แยกกัน โดยบอกให้ทิ้ง commit หรือใช้ command line และมันซิงก์เฉพาะ branch ดีฟอลต์เท่านั้น ทุกอย่างที่เกินการตามทันง่าย ๆ สามคำสั่งด้านบนคือเครื่องมือ
ควรซิงก์ fork บ่อยแค่ไหน?
ก่อนเริ่มงานใหม่ทุกชิ้น คือคำตอบที่ซื่อสัตย์: แตก branch จาก main ที่สด แล้ว PR ที่คุณเปิดจะไม่เริ่มด้วยประโยค “อันนี้ทำจากเวอร์ชันสามสัปดาห์ก่อน” สำหรับ fork ที่คุณมีส่วนร่วมจริง การซิงก์ main รายวันหรือรายเซสชันใช้เวลาไม่กี่วินาที สำหรับ fork ที่แค่อ่านหรือ deploy ให้ซิงก์เมื่อ upstream ปล่อยของที่คุณอยากได้ — กดติดตาม release ของ repo ต้นฉบับแล้วซิงก์ตอนมีรุ่นใหม่ การซิงก์ถูกเพราะมันเป็นกิจวัตร; fork ที่ตกหล่นหกเดือนมักต้องผ่าตัด ไม่ใช่ merge นั่นแหละที่ทำให้ “ซิงก์ fork ให้หน่อย” กลายเป็นทั้งบ่าย
แผ่นสรุปคำสั่ง
# เซ็ตอัปครั้งเดียว
git remote add upstream https://github.com/ORIGINAL_OWNER/REPO.git
# ซิงก์ประจำ (นโยบาย merge)
git fetch upstream && git merge upstream/main && git push origin main
# ซิงก์ประจำ (นโยบาย rebase, ประวัติเป็นเส้นตรง)
git fetch upstream && git rebase upstream/main && git push --force-with-lease origin main
# ผมตกหล่นมาก่อนแค่ไหน?
git fetch upstream && git rev-list --count main..upstream/main
# แยกกันจนแก้ไม่ได้ — ทำให้ main เหมือน upstream เป๊ะ (ทำลายข้อมูล)
git fetch upstream && git reset --hard upstream/main && git push --force-with-lease origin main จำคำสั่งสองบรรทัดประจำวันไว้ในความจำกล้ามเนื้อ แล้ว fork ที่แยกทางจะเป็นเรื่องเล่าที่คุณได้อ่าน ไม่ใช่ปัญหาที่คุณต้องแก้ ถ้างานบ้าน Git ของคุณลุกลามไปถึงเซิร์ฟเวอร์ สรุปคำสั่ง journalctl ดูแลอีกครึ่งของการเก็บประวัติเครื่องให้อ่านรู้เรื่อง
— mrsaynothing
— mrsaynothing
บันทึกหน้างานเรื่อง AI, Linux และ self-hosted
คุยต่อโพสต์นี้บน dev.to dev.to ↗
รับวิธีแก้ฉบับถัดไปทางอีเมล
อีเมลหนึ่งฉบับต่อหนึ่งโพสต์ แก้เสร็จแล้วไปต่อ
นี่คืออะไร?ss vs netstat: คำสั่งดูพอร์ตบน Linux ควรใช้ตัวไหน
ถ้าอ่านแล้วชอบ — ผมสร้างงานแบบนี้เป็นอาชีพ จ้างผม