git absorb - `git commit --fixup` แบบอัตโนมัติ
(github.com/tummychow)- เวอร์ชันพอร์ตสำหรับ git ของ
hg absorbที่ Facebook สร้างขึ้นhg absorbอาจเรียกได้ว่าเป็นหนึ่งในการปรับปรุงเวิร์กโฟลว์ที่เจ๋งที่สุดของระบบควบคุมเวอร์ชันในช่วงหลายปีที่ผ่านมา- เมื่อมีการเปลี่ยนแปลงที่ยังไม่ได้ commit อยู่บน draft changeset, การรัน
hg absorbจะดูดซับการแก้ไขที่ยังไม่ได้ commit ไปยัง draft ancestor changeset ที่เหมาะสมโดยอัตโนมัติ - สามารถทำงานแบบ
hg histedit+ "roll" ได้โดยไม่ต้องสร้าง commit หรือกำหนดกฎการแก้ประวัติด้วยตนเอง - คำสั่งจะดูบรรทัดที่ถูกแก้ไข, หา changeset ที่แก้บรรทัดนั้น, แล้วแก้ changeset นั้นให้รวมการเปลี่ยนแปลงที่ยังไม่ได้ commit เข้าไป
- หากไม่สามารถสร้างการเปลี่ยนแปลงได้โดยไม่มี conflict ก็จะคงอยู่ในสถานะยังไม่ได้ commit
- เวิร์กโฟลว์นี้มีประโยชน์มากกับงานอย่างการนำ feedback จากการรีวิวมาใช้ เพียงแก้ไฟล์แล้วรัน
hg absorbการจับคู่ระหว่างการเปลี่ยนแปลงกับ commit จะถูกจัดระเบียบโดยอัตโนมัติ เป็นฟีเจอร์ที่เหมือนเวทมนตร์
สถานการณ์การใช้งาน git absorb
- มี feature branch ที่ประกอบด้วยหลาย commit
- เพื่อนร่วมทีมรีวิว branch แล้วชี้บั๊กบางอย่าง
- มีการแก้บั๊กแล้ว แต่เพราะเชื่อในแนวคิด atomic commit จึงไม่อยากรวมทุกอย่างไว้ใน commit คลุมเครือชื่อ fixes
- แทนที่จะต้องหา commit SHA สำหรับ
git commit --fixupด้วยตนเอง หรือรัน interactive rebase เอง ให้ทำดังนี้:git add $FILES_YOU_FIXEDgit absorb --and-rebase
git absorbจะระบุโดยอัตโนมัติว่า commit ใดสามารถแก้ได้อย่างปลอดภัย และ staged change ใดควรอยู่กับ commit ใด- จากนั้นจะสร้าง commit แบบ
fixup!สำหรับการเปลี่ยนแปลงเหล่านั้น - หากใช้แฟล็ก
--and-rebaseก็จะรวม fixup commit เหล่านี้กลับเข้า commit ที่เกี่ยวข้องโดยอัตโนมัติ - หากยังไม่มั่นใจ สามารถตรวจสอบผลลัพธ์ด้วยตนเองก่อน แล้วใช้ความสามารถ
autosquashที่มีใน git เพื่อรวม fixup เข้ากับ feature branch ได้
การติดตั้ง
- ดาวน์โหลดอาร์ติแฟกต์จากแท็กรุ่นล่าสุดเพื่อติดตั้งได้
- มีอาร์ติแฟกต์สำหรับ Windows, MacOS, Linux
วิธีใช้
- เพิ่มการเปลี่ยนแปลงที่จะดูดซับด้วย
git add - รัน
git absorb - หากพอใจกับผลลัพธ์ ให้รัน
git rebase -i --autosquash - หากไม่พอใจ ให้ย้อนกลับไปสถานะก่อนหน้าด้วย
git reset --soft
How it works (roughly)
git absorbจะตรวจสอบว่า patch สองตัว P1 และ P2 สามารถสลับลำดับกันได้หรือไม่- โดยค่าเริ่มต้นจะพิจารณา 10 commit ล่าสุด
- สำหรับแต่ละ hunk ใน index จะตรวจสอบว่า hunk นั้นสลับกับ commit ล่าสุดได้หรือไม่
- เมื่อพบ commit ที่สลับไม่ได้ ก็จะแปลง hunk นั้นเป็น fixup commit
Configuration
Stack size
- โดยค่าเริ่มต้นจะพิจารณา 10 commit ล่าสุด
- หากต้องการให้พิจารณา commit มากกว่านี้ ให้ตั้งค่า
maxStackใน.gitconfig
One fixup per fixable commit
- โดยค่าเริ่มต้นจะสร้าง fixup commit แยกสำหรับแต่ละ hunk ที่ดูดซับได้
- สามารถใช้แฟล็ก
-Fเพื่อสร้าง fixup commit เพียงอันเดียวสำหรับทุก hunk ที่จะถูกดูดซับเข้า commit เดียวกัน
Auto-stage all changes if nothing staged
- โดยค่าเริ่มต้นจะพิจารณาเฉพาะไฟล์ที่ staged แล้ว
- หากไม่มี staged change และต้องการ stage ทุกการเปลี่ยนแปลงโดยอัตโนมัติ ให้ตั้งค่า
autoStageIfNothingStaged
Fixup target always SHA
- โดยค่าเริ่มต้นข้อความของ fixup commit จะอ้างถึงสรุปของ commit เป้าหมาย
- สามารถตั้งค่าให้ชี้ไปที่ SHA ของเป้าหมายเสมอได้
TODO
- เพิ่มการรองรับ force flag
- เพิ่มการตรวจสอบ remote default branch
- เพิ่ม force flag ขนาดเล็กสำหรับปิดการตรวจสอบความปลอดภัยเป็นรายจุด
- ทำให้แน่ใจว่าข้อความ error ทั้งหมดมีประโยชน์ต่อผู้ใช้
- แสดง log ให้มากขึ้นเมื่อสำเร็จ
- เพิ่มการทดสอบให้มากขึ้น
- จัดทำเอกสารรายละเอียดของ stack และการสลับลำดับ
- เพิ่มกรณีการสลับลำดับให้มากขึ้น
- ปรับให้ไม่ต้องโหลดทุก hunk เข้า memory พร้อมกัน
- เพิ่ม index lock เพื่อป้องกันการแก้ไขพร้อมกัน
สรุปของ GN⁺
git absorbเป็นเครื่องมือที่พอร์ตมาจากhg absorbของ Facebook โดยช่วยปรับปรุงเวิร์กโฟลว์การพัฒนาด้วยการแก้ commit โดยอัตโนมัติ- มีประโยชน์มากเมื่อต้องนำ feedback จากการรีวิวมาใช้ เพราะช่วยจัดการให้แบบอัตโนมัติโดยไม่ต้องหา commit หรือแก้ไขเอง
- เครื่องมืออื่นที่มีความสามารถคล้ายกันคือ git-autofixup ซึ่งช่วยสร้าง fixup commit อัตโนมัติตามข้อความ commit
- ข้อดีคือทำให้รับ feedback จาก code review ได้ง่ายขึ้น และทำให้ประวัติ commit สะอาดขึ้น ส่วนข้อเสียคือหากพึ่งพาระบบอัตโนมัติมากเกินไป อาจเกิดผลลัพธ์ที่ไม่คาดคิดได้
2 ความคิดเห็น
ความคิดเห็นจาก Hacker News
คนที่ใช้
git absorbมองว่าเครื่องมือนี้มีประโยชน์มากgit absorbจะช่วยหาได้อัตโนมัติว่าควรแก้กับคอมมิตไหนพอใจกับการใช้ alias สำหรับ
git commit --fixupเคยลองใช้
git absorbแต่พบว่ามันเลือก parent commit ผิดบ่อยเกินไปยังไม่เคยใช้
git --fixupและgit rebase --autosquashแต่ก็ดูน่าจะมีประโยชน์git-absorbดูเหมือนจะไปได้ไกลกว่าอีกขั้นมีความสงสัยกับการแก้ไขคอมมิตและประวัติ
ใช้
magitเพื่อสร้างคอมมิต fixup ได้อย่างง่ายดายได้รู้จัก
git commit --fixupและgit rebase --autosquashgit rebase -iตอบโจทย์ความต้องการได้หลากหลายไม่เข้าใจการยึดติดกับประวัติคอมมิตที่สะอาดหมดจดมาก ๆ
ไม่ค่อยเข้าใจแนวคิดการเลือกคอมมิตที่แก้ไขได้โดยไม่มี conflict จาก 10 คอมมิตล่าสุด
คอมเมนต์นี้แทงใจเลยนะครับ ผมก็แค่ลอง fixup / autosquash แบบพอหอมปากหอมคออยู่บ้าง แต่ก็แอบรู้สึกหมดไฟนิด ๆ เหมือนกันว่า หรือมีแค่ผมคนเดียวที่ไปใส่ใจกับเรื่องนี้...