2 คะแนน โดย GN⁺ 2025-07-23 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Jujutsu (jj) เป็นระบบควบคุมเวอร์ชัน ที่มีแนวคิดและคำสั่ง เรียบง่ายกว่า Git แต่ยังคงมีความสามารถทรงพลัง
  • เนื่องจากใช้ Git เป็นแบ็กเอนด์ จึงมีข้อดีคือ ใช้งานควบคู่กันได้หรือกลับไปใช้ Git ได้ง่าย
  • มีความสามารถอย่าง stacked diff, rebase ที่ทำได้ง่าย, และ revision ชั่วคราว ให้ใช้งานได้อย่างเป็นธรรมชาติ
  • ใช้แนวคิด Bookmarks แทน Branch ซึ่งเข้าใจได้ตรงกับเวิร์กโฟลว์การทำงานจริงมากกว่า
  • วิธีจัดการ conflict มีความยืดหยุ่น และช่วยให้งานจัดการเวอร์ชันในชีวิตประจำวันง่ายขึ้นมาก

Elevator Pitch

Jujutsu (jj) เป็นระบบควบคุมเวอร์ชันที่ให้ mental model และ command-line interface ที่เรียบง่ายกว่า Git มาก
โดยไม่ต้องแลกกับความสามารถที่ลดลง และในความเป็นจริงอาจมองได้ว่าทรงพลังกว่าด้วยซ้ำ
ความสามารถอย่าง stacked diff, rebase ที่ทำได้ง่าย, และ revision ชั่วคราว ทำงานได้อย่างเป็นธรรมชาติ
เพราะใช้ Git เป็นแบ็กเอนด์ จึงสามารถเริ่มใช้งานควบคู่กับ Git repository ได้ด้วยคำสั่งเพียงบรรทัดเดียว และกลับไปใช้ Git เมื่อไรก็ได้
ทั้งยังไม่ส่งผลกระทบต่อวิธีที่ผู้ใช้อื่นจัดการกับ repository นั้น

Getting Started

  • หลังติดตั้งเครื่องมือบรรทัดคำสั่ง jj แล้ว แนะนำให้ตั้งค่าข้อมูลผู้ใช้และ shell auto-completion
  • หากจะใช้กับ repository เดิม การ clone ใหม่หรือเริ่มใช้งานในสถานะที่ไม่มีการเปลี่ยนแปลงจะเหมาะกว่า
  • ใน repository เดิม สามารถใช้คำสั่ง jj git init --colocate . เพื่อสร้าง Git และ Jujutsu repository แบบใช้งานคู่กันได้
  • ข้อมูลของ jj repository จะถูกเก็บไว้ในโฟลเดอร์ .jj/ แยกจาก .git ของ Git
  • โดยทั่วไปการซิงก์ข้อมูลระหว่าง Git และ Jujutsu ทำงานได้โดยไม่มีปัญหา
  • แต่ต้องระวังว่า คำสั่ง git clean -fdx จะลบโฟลเดอร์ .jj/ ออกไป
  • การตั้งค่า remote branch tracking ก็สามารถทำได้พร้อมกันด้วยคำสั่งดังกล่าว

How To Use It

command-line interface ของ Jujutsu แคบกว่าและกระชับกว่า Git
แม้แนวคิดพื้นฐานจะเรียบง่าย แต่เวิร์กโฟลว์ก็ยังต้องใช้เวลาปรับตัวเล็กน้อย
ส่วนนี้จะอธิบายวิธีใช้งานหลักด้วยขั้นตอนสั้น ๆ และตัวอย่าง

Starting A New Revision

  • งานใหม่ใน Git มักเริ่มจากการสร้าง branch แต่ Jujutsu ใช้วิธีสร้าง revision ใหม่
  • อัปเดตสถานะล่าสุดจาก remote repository: jj git fetch
  • ตรวจสอบ history ของ repository: jj log
  • revision ใน history จะถูกแยกด้วย revision ID เฉพาะของ Jujutsu และ Git commit hash
  • เริ่มงานใหม่ด้วย jj new main เพื่อสร้าง revision ใหม่บน main ปัจจุบัน
  • revision ที่กำลังแก้ไขอยู่จะระบุด้วยสัญลักษณ์ @
  • หาก prefix เดียวกันหมดไป prefix แบบสั้นของ revision ID ก็จะเปลี่ยนตามไปด้วย

Making Changes

  • เมื่อแก้ไขไฟล์ การเปลี่ยนแปลงจะ ถูกรวมเข้า revision นั้นทันที (ไม่มี staging area แยกต่างหาก)
  • เมื่อแก้ไขเสร็จแล้ว ให้เพิ่มข้อความให้ revision ด้วย jj describe -m "ข้อความ"
  • เมื่อต้องการสร้าง revision ใหม่ ใช้ jj new (หรือระบุ revision ก่อนหน้า)
  • jj commit เป็นการทำงานแบบผสมระหว่าง jj describe + jj new

Navigating

  • revision ว่างที่สร้างด้วย jj new จะถูกทิ้งอัตโนมัติเมื่อย้ายออกจากมัน
  • ลบ revision แบบระบุชัดเจน: jj abandon <rev ID>
  • ย้อนการลบ: jj op undo
  • กลับไปยัง revision เดิม ใช้ jj edit <rev ID>
  • ขณะอ้างอิง revision ยังสามารถใช้ revset expressions ได้ด้วย:
    • @: revision ปัจจุบัน
    • x-: parent revision
    • y+: child revision
    • z::: ลูกหลานทั้งหมดของ z

Branches (Bookmarks)

  • Jujutsu ไม่มีสถานะแบบ “อยู่บน branch” เหมือน Git
  • แต่ Bookmarks เป็นเพียง pointer ที่ชี้ไปยัง revision ใด revision หนึ่ง
  • สร้าง bookmark ใหม่: jj bookmark create <ชื่อ> -r <revision>
  • แม้จะ commit แล้ว bookmark จะไม่เลื่อนตามอัตโนมัติ ดังนั้นหากต้องการต้องย้ายเองด้วย jj bookmark move <ชื่อ> --to <revision>
  • ตอน push หากต้องการยอมรับการสร้าง remote branch ใหม่ ให้ใช้แฟลก --allow-new
  • หาก bookmark ต่างจากฝั่ง remote จะมีเครื่องหมาย * แสดงไว้ และสามารถซิงก์ด้วย jj git push

Conflicts

  • วิธีจัดการ conflict ของ Jujutsu ยืดหยุ่นกว่า Git
  • เมื่อเกิด conflict จะมีเครื่องหมาย ‘conflicted’ แสดงบน revision นั้นและ revision ลูกหลาน
  • ไฟล์ที่ conflict จะมี conflict marker ถูกแทรกไว้ และสามารถแก้ไขได้ด้วยการลบ marker เหล่านั้นออก
  • จะเลือกแก้ไขโดยตรง หรือแก้ใน revision ใหม่แล้วค่อยรวมด้วย jj squash ก็ได้

บทสรุป

เท่านี้ก็เป็นแนวทางในการจัดการงาน 80% ที่พบบ่อยที่สุดใน Git ให้เรียบง่ายขึ้นด้วย Jujutsu
ต่อไปจะมีการจัดทำคู่มืออ้างอิงแบบ Quick Reference สำหรับการใช้งานทั่วไปและขั้นสูง
รองรับคำสั่ง jj status เช่นเดียวกับ Git
หากมีคำถามหรือข้อเสนอแนะสามารถติดต่อได้ทางอีเมลที่ระบุในบทความ

1 ความคิดเห็น

 
GN⁺ 2025-07-23
ความคิดเห็นจาก Hacker News
  • มีจุดหนึ่งที่อยากเน้นสำหรับคนที่กำลังชั่งใจว่า jj คุ้มค่ากับการเรียนรู้ไหม
    พอพูดถึง jj บน Hacker News คนจะถูกแบ่งเป็นสองกลุ่ม: คนที่ยังไม่เคยลอง กับคนที่เชียร์แบบสุดตัว
    แทบไม่เคยเห็นใครที่ลองใช้ jj อยู่หนึ่งสัปดาห์แล้วกลับไปใช้ git อีก
    คนที่ได้ลองใช้อย่างจริงจังเกือบทั้งหมดก็ตั้งหลักอยู่กับ jj กันไปเลย
    หวังว่าวันนี้จะเป็นจุดเริ่มต้นให้คุณได้ลองใช้ jj
    การย้ายไปใช้มันง่ายกว่าที่คิดมาก และผมก็ยังรักษาประสิทธิภาพการทำงานได้ตั้งแต่วันแรก โดยภายในหนึ่งสัปดาห์ไม่ต้องกลับไปใช้คำสั่ง git เลย
    ผมทำงานได้มีประสิทธิภาพขึ้นในเวลาไม่นาน และยังอดแปลกใจไม่ได้ว่าเมื่อก่อนใช้ git กันมาได้อย่างไร

    • สำหรับผม git ไม่ได้สร้างความลำบากด้านประสิทธิภาพการทำงานเลย
      ผมไม่ได้ใช้คำสั่ง git หนัก ๆ ทุกวัน และโดยมากมันก็ไม่ได้เป็นอุปสรรคต่อการทำงาน
      ถ้าคุณต้องจัดการ repo ด้วย git เยอะมาก jj อาจดีกว่า แต่กรณีของผมไม่ใช่แบบนั้น
      มันคล้ายกับการชวนให้ลองใช้ bim ที่เกือบเหมือน vim มากแต่มีฟีเจอร์เพิ่มเข้ามา
      แต่ผมไม่ได้สนใจว่าจะต้องกด "i" เพิ่มอีกไม่กี่ครั้ง และก็ไม่ต้องการระบบเติมโค้ดอัตโนมัติของ julia
      ถ้าใครคิดว่า jj ดีกว่าก็ขอให้ใช้อย่างมีความสุข

    • jj ถือว่าเป็นพัฒนาการของ UI สำหรับ VCS อย่างชัดเจน แต่ถ้าเป็นผู้ใช้ git ระดับสูงก็ยังมีข้อจำกัดบางอย่าง
      การไม่รองรับ gitattributes ทำให้ใช้งานลำบากหากต้องพึ่งฟิลเตอร์อย่าง git-crypt หรือ git-lfs
      ความเข้ากันได้บน Windows เช่นเรื่องการจัดการตัวจบบรรทัดก็อาจด้อยลง
      อีกทั้งเครื่องมือภายนอกอย่าง git-annex หรือ git-bug ก็ไม่ผสานกับ oplog และอาจทำให้ history ยุ่งเหยิงได้

    • ผมเองเคยลองใช้จริงเกินหนึ่งสัปดาห์แล้วก็กลับไปใช้ git
      โดยส่วนตัวผมชอบ workflow ของ staging area มากกว่า แม้ว่าคนส่วนใหญ่จะไม่ชอบ git staging แต่สำหรับผมข้อดีนั้นไม่ได้มากพอให้ทิ้งมันไปอยู่กับ jj
      ผมอาจเปลี่ยนนิสัยได้ แต่ตอนนี้ยังไม่จำเป็นต้องผูกตัวเองกับ jj
      แต่ก็ยังเปิดใจว่าจะกลับไปลองใหม่สักวัน

    • ผมใช้ jj อยู่หลายเดือนก่อนจะกลับไปหา git เพราะปัญหาเรื่องประสิทธิภาพ
      การทำงานต่าง ๆ ใน jj ใช้เวลาหลายวินาที ขณะที่ git ตอบสนองทันทีไม่ว่าโปรเจกต์จะใหญ่แค่ไหน
      อีกอย่างคือพอใช้ jj แล้วรู้สึกว่ามันเพิ่มภาระทางความคิดขึ้นนิดหน่อย พอกลับมาใช้ git ก็รู้สึกโล่งขึ้นมาก
      เรื่องนี้อาจเป็นเพราะประสบการณ์การใช้ git ระยะยาวของผมเองก็ได้

    • การพูดว่า “ยังไงก็มีแค่สองกลุ่ม” ฟังดูเป็นประโยคแบบที่พวกนักเผยแพร่ jj ชอบพูดกันมาก

  • สิ่งที่ผมไม่ชอบใน jj คือการที่การเปลี่ยนแปลงทุกอย่างถูก staging อัตโนมัติเสมอ
    ระบบแบบ SVN ก็เคยเป็นอย่างนั้น และผมรู้สึกว่า git ปรับปรุงเรื่องนี้ได้มากเพราะต้อง staging แบบชัดเจน
    ใน repo มักจะมีการเปลี่ยนแปลงมากกว่าสิ่งที่อยากใส่ใน commit ถัดไปอยู่เสมอ และใน git การเลือกเฉพาะสิ่งที่จะใส่จึงเป็นเรื่องปกติ
    แต่ใน jj (รวมถึง SVN) กลับต้องใช้วิธีจัดการด้วยมือที่ยุ่งยาก เช่น ย้ายการเปลี่ยนแปลงออกไปชั่วคราวก่อน commit

    • ประเด็นนี้สำหรับผมก็เป็น dilemma เหมือนกัน
      staging น่ารำคาญเสมอจนแม้แต่ตอนใช้ Mercurial ก็ยังลำบาก
      ถ้าเคสกว่า 90% ต้อง auto add มันกลับสะดวกกว่า แต่ปัญหาคือไฟล์ที่ใส่ใน .gitignore ไม่ได้
      จะปิด auto add ก็ลำบาก จะเปิดไว้ก็ก้ำกึ่ง
      ไม่มีทางไหนที่สะอาดหมดจดจริง ๆ

    • workflow ของ JJ ต่างออกไปนิดหน่อย เช่น คุณอาจสร้าง base commit ก่อน แล้วซ้อน anonymous commit ไว้ด้านบนเพื่อทำงาน
      พอพร้อมแล้วค่อยจัดระเบียบด้วย jj squash หรือ jj split

    • ผมใช้ jj commit -i, ตัวเลือก -i ของหลายคำสั่ง และตั้งค่า snapshot.auto-track="none()" ใน config
      ตอนใช้ Mercurial ผมก็ทำคล้ายกัน
      จริง ๆ แล้วถ้าใช้ฟีเจอร์ absorb บ่อย ๆ ไฟล์หรือ chunk ที่ไม่จำเป็นก็มักจะถูกมองข้ามให้อัตโนมัติ

    • คำสั่ง “jj new” ไม่น่าจะเหมาะกับ workflow ที่คุณต้องการหรือ?

    • jj ติดตาม branch ที่ไม่ใช่ head บน tree ได้อย่างถูกต้องด้วย จึงทำให้ rebase และ merge ทำงานได้ลื่นโดยไม่ต้อง stash

  • มันปรับตัวยากกับการที่มีการเพิ่มการเปลี่ยนแปลงอัตโนมัติ
    บางครั้งในเครื่อง local ผมแก้ไฟล์บางไฟล์ชั่วคราวระหว่างพัฒนา โดยไม่ได้ตั้งใจจะ commit มัน
    ใน git ถ้าไม่ staging มันก็ไม่มีทางถูก commit หรือ push จึงอุ่นใจได้
    แต่ใน jj มันให้ความรู้สึกว่าต้อง unstage อะไรบางอย่างหรือระวังเป็นพิเศษ
    อาจเป็นแค่เรื่องความเคยชิน แต่สำหรับผมการระบุให้ชัดว่าจะ commit อะไรบ้างสบายใจกว่า
    เลยสงสัยว่าผมเข้าใจ jj ผิดไปหรือเปล่า

    • ใน jj คุณสามารถใช้ jj split เพื่อแยกการเปลี่ยนแปลงได้
      สิ่งที่เลือกจะไปอยู่ใน revision แรก ส่วนที่เหลือจะไปอยู่ใน revision ที่สอง
      ถ้าคุณทำหลายอย่างพร้อมกันแล้วค่อยแบ่งเป็น revision คำเล็ก ๆ ภายหลัง มันง่ายกว่า git มาก
      คุณสามารถสร้าง revision ใหม่ (jj new) แบบเดียวกับ git แล้วค่อยแก้ จากนั้นใช้ jj squash -i เพื่อย้ายเฉพาะส่วนที่ต้องการได้พอดี
      ในเชิงแนวคิด “@” คือ revision ปัจจุบัน และ “@-” คือหนึ่งขั้นก่อนหน้า จึงคิดได้คล้าย working copy/stage ของ git

    • auto staging ของ jj ไม่ได้ดีเสมอไป
      อยากให้เอกสารทางการของ jj และคนที่สอนมือใหม่บอกให้ชัดกว่านี้ว่าค่าเริ่มต้นสามารถปิดได้ง่าย
      ใน ~/.jjconfig ให้เขียนว่า
      [snapshot]
      auto-track = "none()"
      เท่านี้ก็พอ

    • ปกติผมจะใช้ jj split หลังทำงานเสร็จเพื่อ review และจัดระเบียบว่าจะ commit อะไรบ้าง
      workflow นี้เคลื่อนไหวคล้าย add -p ของ git
      commit บนสุดมักใช้เสมือนเป็น working copy ที่ไม่ push
      และสลับ branch ได้โดยไม่ต้อง stash โดยเนื้อหาที่ทำค้างไว้ยังถูกเก็บไว้อย่างดี

    • ใช่เลย นิสัยแบบนั้นของผมก็เปลี่ยนยากเหมือนกัน
      เหตุผลที่พอฟังขึ้นสำหรับการเปลี่ยนมันคือ เราไม่ควรรันโค้ดในสถานะ untracked
      การเก็บเฉพาะการเปลี่ยนแปลงที่มีความหมายไว้ใน commit และไม่บันทึกที่เหลือจะปลอดภัยกว่า
      ปัญหาคือเวลาการตั้งค่าระดับทั้ง repo กับการตั้งค่าเฉพาะเครื่องแยกจากกันไม่ได้ ซึ่ง VSCode เป็นตัวอย่างชัดเจน
      ในกรณีแบบนี้จึงจำเป็นต้องมีการเปลี่ยนแปลงที่ไม่ควรถูก commit ตามสภาพแวดล้อม ทำให้ยิ่งซับซ้อนขึ้น

    • ถ้าคุณอยากได้ workflow แบบนี้ ให้คิด “@” ของ jj เป็นเหมือน git index แล้วตอน commit ค่อย squash ไปที่ “@-” ก็จะได้ผลใกล้เคียงกับ git add --patch

  • ผมพยายามเปลี่ยนทีมให้ใช้ jj แต่ยังไม่สำเร็จ
    คงจะดีถ้ามีหน้าที่แสดงให้เห็นแบบเร็ว ๆ ว่างานซับซ้อนใน git ทำใน jj ได้ง่ายแค่ไหน
    เหมือน elevator pitch แบบสั้น ๆ
    ผมเองก็คิดว่าคงต้องเดโมให้ดูด้วยตัวเอง

    • สำหรับงาน git ที่คนส่วนใหญ่ใช้กันบ่อย ๆ หลายอย่าง ดูเหมือนว่าจะไม่ได้ง่ายกว่าใน jujutsu
      แต่ jujutsu มี workflow ใหม่ ๆ ที่ใน git ทำไม่ได้หรือทำได้ยาก
      ซึ่งสิ่งนี้อาจไม่โดนใจนักพัฒนาที่คุ้นกับ git แบบเดิมอยู่แล้ว

    • ผมเองก็ไม่ได้ชอบ git เป็นพิเศษ
      เมื่อก่อนใช้แต่ mercurial แต่ตอนนี้ git ฝังอยู่ในหัวไปแล้ว
      ต่อให้ Jujutsu มีข้อดีชัดเจนบางอย่าง ผมก็ยังไม่รู้สึกว่ามันดึงดูดพอจะไปใส่ใจกับการตั้งค่าเริ่มต้นทั้งหมด เช่น ตั้งค่าสีที่ซับซ้อนหรือสคริปต์ที่คุ้นมือ

    • สำหรับผม การได้เห็นการเปรียบเทียบงานหนึ่งอย่างระหว่าง jj กับ git ช่วยให้เข้าใจมากขึ้นมาก
      https://lottia.net/notes/0013-git-jujutsu-miniature.html

    • ขอแนะนำลิงก์ที่มีประโยชน์อีกหลายอัน
      https://v5.chriskrycho.com/essays/jj-init/
      https://v5.chriskrycho.com/journal/jujutsu-megamerges-and-jj-absorb/
      https://ofcr.se/jujutsu-merge-workflow

    • เนื้อหาถัดไปที่ผมกำลังจะเพิ่มในโพสต์นี้น่าจะเป็นสิ่งที่คุณชอบ
      อีกไม่นานจะลงไว้ทั้งท้ายหน้าและแยกเป็นอีกโพสต์หนึ่งต่างหาก

  • ผมใช้ jj มาหลายสัปดาห์แล้ว ถึงขั้นทำสคริปต์ข้อความ commit อัตโนมัติขึ้นมา
    วันนี้ผมพยายามพอร์ตสคริปต์เดียวกันไปใช้กับ git repo เก่าตัวหนึ่ง แล้วก็เพิ่งตระหนักว่าใน git ต้องมีโค้ดไว้ตรวจจับอัตโนมัติว่านี่คือจังหวะ commit หรือ amend
    แต่ใน jj สคริปต์เรียบง่ายมากเพราะโครงสร้าง commit แบบ immutable
    สุดท้ายก็ clone repo ใหม่ด้วย jj ไปเลย
    หลุดพ้นจากความสับสนระหว่าง commit กับ amend ได้แทบจะทันที
    https://codeberg.org/jcdickinson/nix/src/branch/main/home/common/scripts/jj-auto.fish

    • ไม่จำเป็นต้อง re-clone ก็ได้ แค่เพิ่ม jj เข้าไปใช้กับ git repo เดิมควบคู่กันก็พอ
  • git ทำงานได้ดีเพียงพออยู่แล้ว
    มันมี learning curve อยู่บ้าง แต่พอเข้าใจแล้วทุกอย่างก็สมเหตุสมผล
    พูดตามตรง ใน 95% ของสถานการณ์ แค่รู้ pull, add, reset, branch, commit ก็เพียงพอแล้ว

    • ใน workflow ของผม stacked diff เป็นของจำเป็น
      มันช่วยให้ผมไม่ติดคอขวดระหว่างรอ review และยังซ้อนงานในอนาคตไว้ก่อนได้
      การตั้งค่าใน git ไม่ได้ยาก แต่ถ้าต้องเพิ่มการเปลี่ยนแปลงลงไปที่ชั้นล่างของสแตกแล้ว restack ทั้งหมด นั่นคือฝันร้ายจริง ๆ

    • ถ้าทำงานร่วมกับคนอื่น การเข้าใจ rebase/squash เป็นสิ่งจำเป็น
      ต่อให้ไม่อยากใช้ก็เลี่ยงไม่ได้จนกว่าจะโน้มน้าวให้ทั้งทีมเลิกใช้มัน
      โดยเฉพาะเวลาเร่งพัฒนากันหลายคนบน branch เดียว นิสัยแบบ git จะเริ่มกลายเป็นความอึดอัด
      โดยพื้นฐานมันใช้งานสะดวก แต่พอเจอสถานการณ์ซับซ้อนก็มีปัญหาเยอะ

    • แค่ได้เจอสถานการณ์แปลก ๆ ไม่กี่ครั้งก็จะเห็นจุดอ่อนของ git แล้ว

  • ผมใช้ jj มาได้ประมาณ 2 สัปดาห์ และเป็นครั้งแรกที่รู้สึกสบายใจกับการจัดการเวอร์ชันผ่าน command line ล้วน ๆ
    ตอนใช้ git ผมต้องพึ่ง GUI (Git Graph ใน VSCode) แล้วคลิกขวาเป็นหลักตลอด
    แต่กับ jj แค่อ่าน tutorial อย่างเดียวก็เข้าสู่ command line ที่มีความสอดคล้องได้ทันที
    อย่างไรก็ตาม ถ้าอยากเลิกคอย copy-paste id ใน log ของ jj คงต้องเรียนรู้ภาษา revset

    • ผมก็คล้ายกัน
      ใช้ git มานาน แต่เรื่องซับซ้อนมักจัดการผ่าน UI ตลอด
      เกือบหนึ่งเดือนมานี้ผมใช้แค่ jj CLI และค่อนข้างพอใจมาก
      แต่อย่างหนึ่งคือเอกสารทางการของ jj เขียนโดยสมมติว่าผู้อ่านมีพื้นฐานอยู่แล้ว ทำให้มือใหม่สับสนได้ง่าย
      หวังว่าจะมีบล็อกและ tutorial เพิ่มขึ้น
      ผมเองก็อยากเรียนรู้ภาษา revset กับ rebase ให้มากขึ้น
      ชอบทั้ง cli ที่กระชับ การแก้ conflict และ oplog

    • ผมก็เคยรำคาญเรื่องการคัดลอกวาง id เหมือนกัน แต่พอใช้ jjui(https://github.com/idursun/jjui) แล้วลื่นขึ้นมาก
      มันทำให้ทำงานได้เร็วเหมือนกำลังกวาดตาดู log อยู่

  • ผมคิดว่าฟีเจอร์ที่ดีที่สุดของ jj คือ undo
    ใน git การ undo ทำได้ยากเพราะขึ้นกับว่าคุณพลาดแบบไหนและต้องใช้คำสั่งต่างกัน
    แต่ jj แค่ jj undo ครั้งเดียวก็จบ
    และมันไม่ได้ผูกกับระบบ backend ใด ๆ จนทำให้ถึงคุณจะใช้ jj คนเดียวในเครื่อง local ก็ไม่กระทบเพื่อนร่วมทีม

  • ผมยังสับสนว่า jj คืออะไรกันแน่
    มันเป็น frontend สำหรับคนที่สับสนกับ git หรือเปล่า
    แม้จะบอกว่า abstract backend ได้ แต่ก็ได้รับอิทธิพลจาก git มากเกินไป จนผมนึกภาพไม่ออกว่ามันจะเข้ากับระบบที่บังคับให้ commit มีเลขลำดับต่อเนื่องอย่าง Perforce หรือ Piper ได้อย่างไร
    แนวคิด working copy = commit ดูเหมือนทำ quality control ไม่ได้
    ความหมายดั้งเดิมของ commit คือการใส่เฉพาะสิ่งที่ตั้งใจจริง ๆ แต่โครงสร้างแบบนี้กลับทำให้แยก “ขยะ commit” ได้ยากขึ้น
    ทั้ง git และ jj ดูจะอ่อนแอกับโปรเจกต์ขนาดใหญ่ และยังแก้ปัญหา commit กระจัดกระจายไม่ได้
    ผมเลยสงสัยว่า jj แก้ปัญหาอะไรอยู่กันแน่ หรือมันเป็นแค่ frontend ตามรสนิยมของผู้เขียน

    • backend ของ Piper กลับทำงานได้เป็นธรรมชาติกว่า backend ของ Git เสียอีก
      commit ของ jj ไม่ได้ตรงกับ commit ของ git แบบหนึ่งต่อหนึ่งสมบูรณ์ ดังนั้นไม่ต้องเข้าใจผิด
      จริง ๆ แล้วเวลาเรียก “commit” มันใกล้กับแนวคิด “diff ที่มีชื่อ” มากกว่า และก่อน push ก็สามารถรื้อและจัดระเบียบการเปลี่ยนแปลงใหม่ได้ง่ายเสมอ
      มันสะดวกกว่า rebase หรือการแก้ history ใน git มาก
      ผมมักสร้างหลาย commit ระหว่างทำงาน เช่น สำหรับการทดลองหรือเอกสารต่าง ๆ ซึ่งถ้าเป็น git ก็คงต้องยัดลง stash หรือ branch ชั่วคราวแบบฝืน ๆ

    • jj เป็นมากกว่า frontend ของ git
      มันคือระบบ version control และเป็น backend-agnostic
      backend หลักที่เด่นที่สุดคือ git จึงทำให้สลับไปใช้กับ repo เดิมได้ทันที
      ผมเป็นผู้ใช้ git มาตั้งแต่ก่อน GitHub จะออกด้วยซ้ำ แต่พอใช้ jj แล้วก็กลับไปหา git ไม่ได้อีก
      jj ทั้งเรียบง่ายกว่าและทรงพลังกว่า
      แนวคิด working copy = commit จริง ๆ ควรเข้าใจประมาณว่า “index ก็เป็น commit แบบหนึ่ง”
      เช่น เวลาจะเริ่มทำ feature x ก็ใช้ jj new -m "working on feature x" trunk เพื่อสร้าง commit ใหม่ แล้ววาง commit เปล่าอีกอันไว้ด้านบน
      งานที่กำลังทำจะอยู่ใน working copy (@) แล้วค่อย “ย้าย” (squash) ไปยัง commit ก่อนหน้า (@-) แทนที่จะใช้ตัวเลือกซับซ้อนของ git อย่าง add-p หรือ reset โดยให้ทุกอย่างถูกจัดการผ่าน diff ระหว่าง commit
      โครงสร้างนี้ทำให้การแยกและจัดระเบียบ commit ยืดหยุ่นและทรงพลังกว่า git index
      ส่วนปัญหา commit กระจัดกระจายนั้นใกล้เคียงกับวัฒนธรรม pull request มากกว่า ซึ่ง jj ก็ช่วยได้เพียงบางส่วนเท่านั้น

    • working copy ไม่ได้ถูก push ขึ้น GitHub แบบส่งเดช และสามารถค่อย ๆ review/จัดระเบียบตอนใส่คำอธิบาย commit ได้

  • ผมลองใช้ jj อยู่ไม่กี่วัน แต่ยังพอใจกับ lazygit เดิม รวมถึง workflow และชุดสคริปต์ที่ตั้งไว้แล้ว
    jj มีอะไรใหม่ ๆ ที่น่าสนใจและก็ใช้ได้ดี แต่ถ้าไม่ได้เพิ่งเริ่มต้นกับ version control ก็คงยังไม่มีแรงจูงใจมากพอให้เปลี่ยน

    • ถ้าใช้เครื่องมืออื่นอย่าง GitButler ความสำคัญของ frontend ก็อาจลดลง แต่เมื่อไม่กี่วันก่อนผมเริ่มใช้ Jujutsu แล้วถาม Claude เรื่องการใช้งานหลัก ๆ (commit, ย้าย branch, push/pull กับ GitHub) ก็ใช้เวลาแค่ 10 นาทีก็คล่องแล้ว
      ผมยังใช้ diff ของ Lazygit อยู่เหมือนเดิม แต่ถึงจะอยู่ในสถานะ detached HEAD ก็ไม่เป็นปัญหาเลย
      JJ เข้ากับ git ได้ดีมาก และช่วยให้จัดการทุกอย่างได้ง่ายกว่ามากโดยไม่ต้องท่องจำคำสั่งซับซ้อน
      การที่ไฟล์ที่ยังไม่ commit เคลื่อนตามไปด้วยอัตโนมัติเวลาสลับ branch คือฟีเจอร์ที่ดีที่สุด
      มันทำให้สลับไปมาระหว่างการพัฒนา แก้บั๊ก แก้ข้อความ ได้สะดวกมาก
      ถ้า AI agent เป็นคนแก้ไฟล์ ก็แค่แยก worktree ออกไปใช้
      และการที่ใส่คำอธิบายการเปลี่ยนแปลง (=commit message) ไว้ล่วงหน้าก่อนงานเสร็จแล้วเห็นได้เลยบน tree ก็ยอดเยี่ยมมาก
      โดยรวมแล้ว JJ ยอดเยี่ยมมากจริง ๆ