- เวอร์ชันพอร์ตสำหรับ 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_FIXED
git 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 แบบพอหอมปากหอมคออยู่บ้าง แต่ก็แอบรู้สึกหมดไฟนิด ๆ เหมือนกันว่า หรือมีแค่ผมคนเดียวที่ไปใส่ใจกับเรื่องนี้...