jj v0.45.0 เพิ่มคำสั่ง jj converge เพื่อรวม commit ของ divergent change ให้เหลือตัวเดียว
ถ้าแก้ change เดียวกันจากสองที่ jj จะขึ้นสถานะ divergent เพราะมี commit หลายตัว v0.45.0 เพิ่ม jj converge มารวมให้เหลือตัวเดียว และถามผู้ใช้เมื่อไม่แน่ชัด

ใน jj (Jujutsu) ระบบจัดการเวอร์ชันที่ทำงานร่วมกับ Git ได้ เวลาเปิด jj log ดูประวัติการทำงาน แล้วเห็นสถานะแตกสายอย่าง divergent บน change ที่เพิ่งแก้ไข สาเหตุมักเกิดจาก change เดียวกันถูกแก้แยกกันสองทาง เช่น เราแก้ในเครื่องตัวเองไปพร้อมกับฝั่ง remote ซึ่งเป็นเซิร์ฟเวอร์ส่วนกลาง ทำให้ change นั้นมีประวัติ commit ซ้อนกันมากกว่าหนึ่งเวอร์ชัน
ใครที่ยังไม่เคยใช้ jj มาก่อน อ่านคำอธิบายเบื้องต้นได้จากบทความ jj ทำงานยังไง
ล่าสุดในอัปเดต v0.45.0 ทีมพัฒนา Jujutsu ชูไฮไลต์หลักเพียงข้อเดียวในบันทึกการอัปเดต นั่นคือคำสั่ง jj converge ซึ่งช่วยยุบ commit ที่แตกสายหรือ divergent ให้กลับมารวมเหลือเพียง commit เดียว โดยระบบจะใช้ชุดกฎช่วยวิเคราะห์ผลลัพธ์ที่น่าจะถูกต้องให้อัตโนมัติ และจะหยุดถามผู้ใช้เฉพาะเมื่อตัดสินใจเองไม่ได้เท่านั้น
divergent ไม่ใช่ conflict ในไฟล์
ก่อนอื่น ต้องแยก commit ออกจาก change ใน jj ให้ได้:
- commit คือสถานะของโค้ดที่บันทึกไว้ ณ เวลาใดเวลาหนึ่ง (คล้ายกับ commit ใน Git)
- change คือตัวแทนของชิ้นงานนั้น ซึ่งจะคงอยู่ต่อเนื่องแม้โค้ดจะถูกแก้ไขหรือบันทึกทับใหม่หลายรอบ
ในสภาวะปกติ แต่ละ change จะมี visible commit เพียงตัวเดียวเท่านั้น ซึ่งก็คือ commit ที่แสดงผลในคำสั่ง jj log -r 'all()' เมื่อเราแก้ไขงานใหม่ commit เก่าจะถูกแทนที่และซ่อนไป ทำให้ change นั้นเหลือเวอร์ชันล่าสุดเพียงตัวเดียว
สถานะ divergent เกิดขึ้นเมื่อ change เดียวกันมี visible commit พร้อมกันมากกว่าหนึ่งตัว มักเกิดขึ้นเมื่อมีการแก้ change เดียวกันจากสองที่ เช่น ทั้งในเครื่องเราและบน remote
จุดที่ชวนสับสนคือ divergent เป็นคนละเรื่องกับ conflict ที่เนื้อหาในไฟล์ชนกัน ซึ่งเวลาเกิด conflict ตัว jj จะแสดงสถานะสีแดงให้เห็นชัดเจนใน jj status และ jj log ส่วน divergent ไม่ได้ตัดสินกันที่เนื้อหาชนกัน แต่คือ change เดียวที่มี commit ซ้อนกันอยู่มากกว่าหนึ่งตัว สำหรับผู้ที่ย้ายมาจาก Git และอยากเห็นภาพรวมความแตกต่างของทั้งสองระบบ สามารถอ่านเพิ่มเติมได้ที่ jj ต่างจาก Git ตรงไหน
เมื่อ change มีหลาย commit ต้องเติมเลข offset เพื่อระบุให้ชัด

ผลกระทบที่ตามมาเมื่อเกิด divergent คือเรื่องการระบุ change ID ซึ่งเป็นรหัสประจำชิ้นงาน 12 ตัวอักษรหน้าบรรทัดใน log แต่บางครั้งรหัสชุดนี้ก็ชี้ commit ได้ไม่ชัดเจน เช่น ตอนที่ commit ถูกซ่อนไป หรือตอนที่ change กลายเป็น divergent จนรหัสเดิมชี้ไปยัง commit ได้หลายตัว การระบุแค่ change ID จึงไม่เพียงพออีกต่อไป
ตามที่ คู่มือของ Jujutsu ระบุไว้ ทางแก้คือต้องเติมเลข offset ต่อท้ายรหัส change ID โดยเลข 0 คือ commit ตัวล่าสุด และเลข 1 คือตัวก่อนหน้า ไล่เรียงกันไป เช่น ถ้า change ID คือ xyz ตัวล่าสุดจะเรียกว่า xyz/0 ส่วนตัวก่อนหน้าจะเรียกว่า xyz/1 เพื่อให้เราระบุได้ชัดเจนว่าจะจัดการกับ commit ตัวไหน
ทำไม divergent ถึงต้องมีคนมาตัดสิน
สถานะ divergent ดูจากจำนวน visible commit ของ change นั้นโดยตรง ถ้ามีมากกว่าหนึ่งตัวก็เข้าข่ายแล้ว ส่วนคำถามที่ตามมาคือ "สรุปแล้ว commit ไหนคือเวอร์ชันจริง หรือควรนำข้อมูลมารวมกันอย่างไร"
สิ่งที่ชี้ว่าคำถามนี้ยังต้องอาศัยคนตอบ เห็นได้จากตัวคำสั่งใหม่อย่าง jj converge ในเวอร์ชัน 0.45.0 เอง เพราะคำสั่งนี้ไม่ได้ออกแบบมาให้ทำงานเงียบๆ จนจบได้เองทุกกรณี
jj converge ช่วยรวม commit ให้เหลือตัวเดียว

jj converge ทำงานโดยสร้าง commit ใหม่ขึ้นมาหนึ่งตัว เพื่อนำไปใช้แทนที่ชุด commit ที่แตกสายทั้งหมด ส่งผลให้ change นั้นกลับมามี commit ที่ถูกต้องเพียงตัวเดียวเหมือนเดิม
เบื้องหลังการทำงาน ระบบจะใช้ heuristics ซึ่งเป็นชุดกฎช่วยประเมิน มาช่วยวิเคราะห์และคาดเดาผลลัพธ์ที่น่าจะถูกต้องให้ก่อน ทำให้เราไม่ต้องคอยเลือกคำตอบเองทุกครั้ง
แต่ heuristics ก็ไม่ได้ตัดสินใจแทนได้ทุกกรณี ถ้าระบบไม่แน่ใจ คำสั่งจะหยุดถามผู้ใช้ทันทีแทนที่จะเดาสุ่มแล้วทำต่อ นั่นหมายความว่า jj converge ช่วยลดภาระที่เราต้องลงมือเอง แต่ไม่ได้แปลว่าจะทำงานอัตโนมัติได้ทุกครั้ง
นอกจากนี้ jj converge ยังมีโหมดทำงานแบบไม่ถามตอบ (non-interactive mode) โดยถ้าทำงานมาถึงจุดที่ตัดสินใจเองไม่ได้ คำสั่งจะยกเลิกการทำงานทันทีแทนที่จะหยุดรอคำตอบ
โหมดที่ไม่ถามนี้เหมาะกับการนำไปใส่ในสคริปต์หรืองานอัตโนมัติ เพราะช่วยป้องกันไม่ให้คำสั่งค้างรอคนมากดตอบ และแจ้งข้อผิดพลาดออกมาให้เรากลับมาตรวจสอบเองในภายหลัง ส่วนการใช้งานทั่วไปในเทอร์มินัล การปล่อยให้ระบบถามตอบจะสะดวกกว่า เพราะเราตอบตรงนั้นได้เลย ไม่ต้องปล่อยให้คำสั่งยกเลิกทิ้งแล้วค่อยกลับมาเริ่มใหม่
การเปลี่ยนแปลงสำคัญ 3 เรื่องใน v0.45.0 ที่ควรรู้ก่อนอัปเดต
นอกจากคำสั่ง jj converge แล้ว ใน v0.45.0 ยังมีการปรับปรุงอีก 3 เรื่องที่ส่งผลต่อการใช้งาน:
เรื่องแรกคือ การจัดการไฟล์ config: คำสั่ง jj config edit, jj config set และ jj config unset รองรับแฟล็ก --file เพื่อระบุตำแหน่งของไฟล์ config ที่ต้องการจัดการได้โดยตรง ซึ่งมีประโยชน์มากสำหรับผู้ที่แยกไฟล์ config ไว้หลายไฟล์ ส่วนแฟล็ก --user ก็ปรับการทำงานใหม่ โดยระบบจะเลือกแก้ไขไฟล์ config ระดับ user ตัวแรกที่โหลดขึ้นมาทันที แทนที่จะขึ้นเมนูมาให้เลือกเหมือนแต่ก่อน ถ้าใครต้องการเจาะจงไฟล์ ให้เปลี่ยนมาใช้แฟล็ก --file แทน
เรื่องที่สองคือ repo ที่ไม่ใช่แบบ colocated หรือ repo ที่โฟลเดอร์ .git ไม่ได้อยู่คู่กับ .jj: คำสั่ง jj git import จะไม่ดึง commit จากสถานะ detached Git HEAD ที่ไม่ได้อยู่บน branch ใดเข้ามาใน jj อีกต่อไป
เรื่องที่สามคือ การเตรียมพร้อมสำหรับ Git worktree: ตัว jj เริ่มปรับโครงสร้างภายในให้จัดเก็บสถานะ Git HEAD แยกตามแต่ละ worktree แล้ว เพื่อเตรียมรองรับการใช้งาน Git worktree หลายชุดพร้อมกันบน repo แบบ colocated ในอนาคต ส่วน repo เดิมที่มีอยู่แล้ว jj จะจัดการย้ายข้อมูลให้อัตโนมัติโดยที่เราไม่ต้องทำอะไรเพิ่ม
บั๊กที่แก้แล้วและข้อควรระวังสำหรับ repo เดิม
เรื่องแรกคือ บั๊กใน repo แบบ colocated: ก่อนหน้านี้ ถ้ารันคำสั่งของ jj แล้วสลับไปสั่ง git add จากภายนอก โครงสร้าง tree ของ Git อาจมีรายการไฟล์ซ้ำ จนทำให้คำสั่ง git fsck รายงานข้อผิดพลาด duplicateEntries สาเหตุเกิดจาก jj ทิ้งข้อมูล cache-tree เก่าค้างไว้ใน .git/index ซึ่งทีมพัฒนาแก้ปัญหานี้แล้วใน v0.45.0
เรื่องที่สองคือ Pager เริ่มต้น: โปรแกรมสำหรับเปิดอ่านผลลัพธ์ยาวๆ ในเทอร์มินัลอย่าง less ได้เพิ่มแฟล็ก -K เข้ามา ทำให้เมื่อกด Ctrl+C เพื่อออกจาก less ตัวโปรแกรมจะปิดได้อย่างเรียบร้อย ไม่ทิ้งหน้าจอเทอร์มินัลให้แสดงผลผิดเพี้ยน
เรื่องที่สามคือ การจัดการ Carriage Return ใน conflict: ก่อนหน้านี้ ถ้าเนื้อหาฝั่งที่มี conflict ลงท้ายด้วยอักขระ carriage return หรือ \r ไบต์ดังกล่าวอาจหายไปเวลา jj อ่านไฟล์กลับเข้ามา ซึ่งในเวอร์ชันนี้แก้ให้เก็บค่า carriage return ไว้ครบถ้วนแล้ว
สิ่งที่ 0.45.0 หยิบออกไปจากหัวคนใช้
ประโยชน์ที่แท้จริงของ jj converge ไม่ใช่แค่ช่วยลดขั้นตอนการพิมพ์คำสั่ง แต่คือช่วยลดภาระที่ผู้พัฒนาต้องคอยจดจำรายละเอียดต่างๆ เพราะเดิมทีเราต้องมาคอยเช็กว่า change นี้มี commit แตกออกมากี่ตัว ตัวไหนใหม่กว่ากัน หรือต้องอ้างอิงด้วย offset เลขอะไร ทั้งที่ข้อมูลทั้งหมดนี้อยู่ในระบบอยู่แล้ว การให้เครื่องมือช่วยรวม commit ให้อัตโนมัติจึงช่วยประหยัดเวลาและแรงไปได้มาก
แต่ก็อย่าลืมว่าเลขเวอร์ชันของ jj ยังคงเป็น 0.x (v0.45.0) และคำสั่ง jj converge เพิ่งเปิดตัวในเวอร์ชันนี้ จึงควรทดลองใช้กับโปรเจกต์ทั่วไปหรือในสภาพแวดล้อมทดสอบก่อนนำไปใช้กับงานสำคัญ สำหรับใครที่สนใจและยังไม่ได้ติดตั้ง สามารถดูขั้นตอนเริ่มต้นได้ที่ หน้าติดตั้งของ Jujutsu
เครื่องมือรุ่นนี้ไม่ได้วัดกันที่ทำงานแทนคนได้มากแค่ไหน แต่วัดกันที่เหลือสถานะให้คนต้องจำเองน้อยลงเท่าไร
ที่มา:
- Release v0.45.0 · jj-vcs/jj จาก jj (Jujutsu)
- Glossary - Jujutsu docs จาก Jujutsu docs
ชอบเรื่องแนวนี้ มีอีบุ๊คฟรีให้อ่านต่อ
ChatGPT Work ฉบับเข้าใจง่าย มอบงานให้ AI ทำจนจบ ตั้งแต่งานแรกจนถึงงานอัตโนมัติ พร้อม workflow ใช้ได้จริง 8 แบบ
กดสมัครแล้วเราจะส่งเทคนิค AI และของแจกใหม่ๆ ให้ทางอีเมล เลิกรับได้ตลอด
Claude Cowork · The Business Playbook

ฉบับภาษาไทย 15 บท เรียนรู้ผ่านโปรเจกต์จำลองต่อเนื่องทั้งเล่ม ตั้งแต่ตั้งค่า Workspace จัดการไฟล์ เชื่อมแอป ตั้งระบบอัตโนมัติ จนถึงสร้าง Plugin


