Rebase คือการดำเนินการใน Git ที่ย้าย commits จากแขนงหนึ่งไปยังยอดของอีกแขนงหนึ่ง สร้างประวัติเชิงเส้นโดยไม่มี merge commits ที่ไม่จำเป็น แตกต่างจากการรวม rebase เขียนประวัติใหม่: แต่ละ commit ที่ถูกย้ายจะได้รับ hash ใหม่เนื่องจากพาเรนต์ของมันเปลี่ยนไป ตามเอกสาร Git (2026) rebase ถูกใช้เพื่อซิงโครไนซ์ feature แขนงกับสถานะล่าสุดของ main ก่อนสร้าง pull request คำสั่ง git rebase เป็นหนึ่งในเครื่องมือหลักสำหรับการรักษาประวัติที่สะอาดในโครงการที่ใช้ Git Flow
ประเด็นสำคัญ
Rebase คือคำสั่ง Git ที่วางฐานแขนงปัจจุบันใหม่บนแขนงที่ระบุ: มันนำ commits ทั้งหมดจากแขนงปัจจุบัน บันทึกไว้ชั่วคราว ย้ายตัวชี้แขนงไปยัง commit เป้าหมาย และนำ commits ที่บันทึกไว้ไปใช้ทีละลำดับบนมัน ผลลัพธ์ — ประวัติดูเหมือนว่านักพัฒนาได้ทำงานโดยตรงจาก commit ล่าสุดของแขนงเป้าหมาย
ไวยากรณ์พื้นฐาน: git rebase main — ขณะอยู่ใน feature แขนง คำสั่งนี้ย้าย feature commits ทั้งหมดไปยังยอดของ main Git ใช้กลยุทธ์การรวมแบบสามทางสำหรับแต่ละ commit แยกต่างหาก ถ้า commit A มีอยู่ในแขนงเป้าหมายแล้ว (กำหนดโดย hash) Git จะข้ามมันโดยอัตโนมัติ หลีกเลี่ยงการเปลี่ยนแปลงที่ซ้ำกัน
Rebase ยังรองรับ โหมด onto สำหรับการย้ายชุดย่อยของ commits: git rebase --onto target start end — รูปแบบนี้ช่วยให้สามารถดึงช่วงของ commits จากแขนงหนึ่งและนำไปใช้บนอีกแขนงหนึ่ง ตัวอย่างเช่น git rebase --onto main feature~3 feature ย้ายสาม commits ล่าสุดของแขนง feature ไปวางบน main
# Switch to feature branch
git checkout feature
# Rebase feature onto main
git rebase main
# After successful rebase — history is linear
git log --oneline --graph
# Move last 3 commits to main
git rebase --onto main HEAD~3 HEAD
Rebase และ merge แก้ไขงานเดียวกัน — การรวมการเปลี่ยนแปลงจากแขนงต่างๆ — แต่ทำในวิธีที่แตกต่างกันโดยพื้นฐาน Merge รักษาประวัติการรวมที่สมบูรณ์โดยการสร้าง merge commit ที่มีสองพาเรนต์ Rebase เขียนประวัติใหม่ ทำให้มันเป็นเชิงเส้น การเลือกระหว่างทั้งสองขึ้นอยู่กับขั้นตอนการทำงานของทีมและกฎการจัดการคลัง
ข้อแตกต่างหลักคือ วิธีการบันทึกข้อเท็จจริงของการรวม Merge บันทึก: "ณ จุดนี้เรารวม feature เข้ากับ main" — ข้อมูลนี้มีประโยชน์สำหรับประวัติโครงการแต่ทำให้บันทึกรกเมื่อมีการรวมบ่อยๆ Rebase แสดง: "commits feature ถูกสร้างขึ้นตามลำดับจากสถานะล่าสุดของ main" — สะอาดแต่ซ่อนความจริงที่ว่าการพัฒนาทำแบบขนาน
ข้อแตกต่างที่สองคือ การจัดการข้อขัดแย้ง ด้วย merge ข้อขัดแย้งจะถูกแก้ไขครั้งเดียวและคำตอบถูกบันทึกใน merge commit ด้วย rebase ข้อขัดแย้งสามารถเกิดขึ้นสำหรับแต่ละ commit ที่ถูกย้าย แต่ละอันต้องการการแก้ไขแยกต่างหาก วิธีนี้ต้องใช้แรงงานมากกว่าแต่ช่วยให้ควบคุมได้แม่นยำกว่าว่าการเปลี่ยนแปลงใดจะไปอยู่ในเวอร์ชันสุดท้าย
| เกณฑ์ | Rebase | Merge |
|---|---|---|
| ประวัติ | เชิงเส้น ไม่มี merge commit | ไม่เชิงเส้น มี merge commit |
| Hash ของ commit | เขียนใหม่ (ใหม่) | เดิมถูกรักษา |
| ข้อขัดแย้ง | แต่ละ commit แยกต่างหาก | ครั้งเดียวใน merge commit |
| แขนงสาธารณะ | ห้าม | อนุญาต |
| คำสั่งเพิกเรียก | git rebase --abort | git merge --abort |
Rebase แบบโต้ตอบ (git rebase -i) คือโหมดที่ Git เปิดโปรแกรมแก้ไขพร้อมรายชื่อ commits และการกระทำที่ใช้ได้สำหรับแต่ละอัน นักพัฒนาสามารถเขียนประวัติใหม่ก่อนส่งไปยังคลังระยะไกล นี่คือเครื่องมือหลักสำหรับการรักษา commits ที่สะอาดใน feature แขนง
คำสั่งที่ใช้ได้ในโหมดโต้ตอบ: pick (เก็บ commit ไว้เหมือนเดิม), reword (เปลี่ยนข้อความของ commit), edit (หยุดเพื่อแก้ไข), squash (รวมกับ commit ก่อนหน้า เก็บข้อความทั้งสอง), fixup (รวม ทิ้งข้อความ), drop (ลบ commit) แต่ละคำสั่งจะถูกวางไว้ก่อน hash ของ commit ในโปรแกรมแก้ไขที่เปิดขึ้น
Squash และ fixup เป็นคำสั่งที่ใช้บ่อยที่สุดสำหรับการรวม commits ถ้านักพัฒนาทำ commits แก้ไขเล็กๆ 5 รายการระหว่างทำงาน squash จะรวมมันเข้าด้วยกันเป็น commit เดียวที่มีเหตุผลพร้อมข้อความที่มีความหมาย Fixup มีประโยชน์สำหรับการแก้ไขคำผิด: การเปลี่ยนแปลงจะไปอยู่ใน commit ก่อนหน้าโดยไม่ต้องเก็บข้อความของตัวเอง
# Open editor for last 4 commits
git rebase -i HEAD~4
# Editor will show:
pick a1b2c3d Add authentication
pick e4f5g6h Fix typo in login
squash i6j7k8l Additional login fixes
pick m9n0o1p Add auth tests
# After saving — Git performs rebase
# and opens editor for squashed commit message
# Auto-squash without opening editor
git rebase -i HEAD~4 --autosquash
แฟลก --autosquash จัดเรียง fixup/squash โดยอัตโนมัติสำหรับ commits ที่มีข้อความขึ้นต้นด้วย fixup! หรือ squash! ซึ่งเร่งการทำงานถ้านักพัฒนาทำเครื่องหมาย commits ไว้ล่วงหน้าสำหรับการรวมภายหลัง แฟลก --committer-date-is-author-date จะรักษาวันที่ของ commit ต้นฉบับเมื่อทำ rebase — มีประโยชน์สำหรับการรักษาลำดับเวลาในประวัติ
ข้อขัดแย้งระหว่าง rebase เกิดขึ้นเมื่อ Git ไม่สามารถใช้ commit ที่ถูกย้ายโดยอัตโนมัติเนื่องจากขัดแย้งกับการเปลี่ยนแปลงในแขนงเป้าหมาย แตกต่างจาก merge ที่ข้อขัดแย้งถูกแก้ไขครั้งเดียว ด้วย rebase แต่ละ commit สามารถทำให้เกิดข้อขัดแย้ง และต้องแก้ไขตามลำดับสำหรับแต่ละ commit จากเก่าที่สุดไปหาใหม่ที่สุด
เมื่อเกิดข้อขัดแย้ง Git จะ หยุด rebase ไว้ชั่วคราว และรายงานว่า commit ไหนที่ทำให้เกิดปัญหา นักพัฒนาเปิดไฟล์ที่ขัดแย้ง (Git ทำเครื่องหมายบริเวณที่ขัดแย้งด้วย <<<<<<<, =======, >>>>>>>) แก้ไข เพิ่มไปยังดัชนี (git add) และดำเนินการ rebase ต่อด้วยคำสั่ง git rebase --continue หากไม่พบคำตอบ — git rebase --abort จะยกเลิก rebase โดยสมบูรณ์
คำแนะนำ: เมื่อมีข้อขัดแย้งหลายจุด การใช้ git mergetool ซึ่งเปิดโปรแกรมแก้ไขแบบเสมือนจริงสำหรับแก้ไขข้อขัดแย้งจะมีประสิทธิภาพมากกว่า นอกจากนี้ยังสามารถข้าม commit ที่มีปัญหาไปได้ (git rebase --skip) แต่จะลบการเปลี่ยนแปลงของมันออกจากประวัติสุดท้าย ซึ่งไม่ค่อยเป็นการตัดสินใจที่ถูกต้อง
# Start rebase with conflict
git rebase main
# Auto-merging file.txt
# CONFLICT (content): Merge conflict in file.txt
# Check status
git status
# both modified: file.txt
# Edit conflicted sections → git add → continue
git add file.txt
git rebase --continue
# If uncertain — abort
git rebase --abort
กฎทองของ rebase: อย่า rebase commits ที่ถูกส่งไปยังคลังระยะไกลแล้วและพร้อมให้กับนักพัฒนาคนอื่น เนื่องจาก rebase เขียน hash ของ commit ใหม่ เพื่อนร่วมงานจะพบข้อขัดแย้งเมื่อพยายามซิงโครไนซ์ — ประวัติท้องถิ่นของพวกเขาจะแตกต่างจากประวัติระยะทางที่ถูกเขียนใหม่
สถานการณ์ที่ rebase ถูก ห้าม โดยเด็ดขาด: ถ้ามีคนสร้างแขนงโดยอาศัย commits ของคุณแล้ว (ตัวอย่างเช่น เพื่อนร่วมงานสร้างแขนงจาก feature ของคุณ) การเขียนประวัติใหม่จะทำให้งานของเขาเสียหาย ในกรณีเช่นนี้ ให้ใช้ merge ไม่ควรทำ rebase ก่อนกำหนดส่ง เนื่องจากข้อผิดพลาดในการแก้ไขข้อขัดแย้งอาจใช้เวลามากกว่าที่คาดและบล็อกการเผยแพร่
ข้อยกเว้น: ถ้าแขนงใช้โดยนักพัฒนาเพียงคนเดียว (แขนง feature ส่วนบุคคล ยังไม่ได้เผยแพร่หรือเผยแพร่ในโหมดร่าง) rebase ก่อน push เป็น แนวปฏิบัติมาตรฐาน หลังจากเผยแพร่และเริ่มทำงานร่วมกัน — ใช้เฉพาะ merge GitHub และ GitLab เสนอ squash merge เป็นตัวเลือกประนีประนอม: มันรวม commits เข้าด้วยกันเป็นอันเดียวแต่ไม่ได้เขียนประวัติของแขนงเป้าหมายใหม่
ทีมสมัยใหม่มักใช้งาน ขั้นตอนการทำงานที่เน้น rebase ร่วมกับ GitHub Flow กระบวนการเป็นดังนี้: นักพัฒนาสร้างแขนง feature จาก main ทำงานในมัน ซิงโครไนซ์เป็นประจำผ่าน git rebase main และก่อนสร้าง pull request ทำ rebase แบบโต้ตอบเพื่อทำความสะอาดประวัติ
หลังจากสร้าง PR (ถ้าจำเป็นต้องดึงการเปลี่ยนแปลงใหม่จาก main) ใช้ git pull --rebase main แทน git pull ทั่วไป วิธีนี้ดึงการเปลี่ยนแปลงโดยไม่ต้องสร้าง merge commit ที่ไม่จำเป็น git pull ด้วยแฟลก --rebase เท่ากับ git fetch + git rebase — Git ดาวน์โหลด commits ใหม่ก่อน แล้ว rebase การเปลี่ยนแปลงท้องถิ่นบนพวกมัน
Git อนุญาตให้กำหนด rebase เป็นพฤติกรรมเริ่มต้นสำหรับ pull: git config --global pull.rebase true หลังจากตั้งค่านี้ git pull จะทำ rebase แทน merge เสมอ ถ้าต้องการ pull ทั่วไป — ใช้ git pull --no-rebase หลายทีมยังเปิดใช้ autostash: git config --global rebase.autoStash true — ซึ่งจะซ่อนการเปลี่ยนแปลงที่ยังไม่ได้ commit โดยอัตโนมัติก่อน rebase และคืนสภาพหลังจากนั้น
คำถามที่พบบ่อย
การ rebase หมายถึงการดำเนินการ git rebase: ย้าย commits จากแขนงปัจจุบันไปยังยอดของอีกแขนงหนึ่ง ผลลัพธ์คือประวัติกลายเป็นเชิงเส้น แต่ละ commit ได้รับ hash ใหม่ และไม่มีการสร้าง merge commit คำสั่งนี้ใช้สำหรับซิงโครไนซ์แขนงโดยไม่ต้องมีจุดรวมที่ไม่จำเป็นในบันทึก
Merge สร้าง merge commit ที่มีสองพาเรนต์ รักษาประวัติขนานและ hash ดั้งเดิม Rebase เขียนประวัติใหม่ — commits ได้รับ hash ใหม่และประวัติกลายเป็นเชิงเส้น Merge ปลอดภัยกว่าสำหรับแขนงสาธารณะ rebase ให้บันทึกที่สะอาดกว่า
คำสั่ง git rebase -i HEAD~N เปิดโปรแกรมแก้ไขที่มี N commits ล่าสุด สำหรับแต่ละ commit สามารถเลือกการกระทำ: pick (เก็บไว้), reword (เปลี่ยนชื่อ), edit (แก้ไข), squash (รวมกับอันก่อนหน้า), fixup (รวมโดยไม่มีข้อความ), drop (ลบ) หลังจากบันทึก Git จะใช้การเปลี่ยนแปลงที่เลือก
Rebase เขียน hash ของ commit ใหม่ ทำให้ประวัติไม่สามารถทำงานร่วมกับสำเนาของ commits เดียวกันบนเครื่องของนักพัฒนาคนอื่น ถ้าเพื่อนร่วมงานได้รับ commits ของคุณผ่าน git pull แล้ว และคุณเขียน rebase มัน git push ของเขาจะถูกปฏิเสธ และ git pull จะสร้าง commits ซ้ำและข้อขัดแย้ง
ก่อนเสร็จสิ้น — git rebase --abort ยกเลิกโดยสมบูรณ์ หลังจากเสร็จสิ้น สามารถคืนสภาพก่อนหน้าได้ผ่าน git reflog — ค้นหา hash ของ commit ก่อน rebase และดำเนินการ git reset --hard ไปที่มัน Reflog จัดเก็บประวัติการเคลื่อนไหวของ HEAD เป็นเวลา 30 วันโดยค่าฐาน
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ