2 điểm bởi GN⁺ 9 ngày trước | 1 bình luận | Chia sẻ qua WhatsApp
  • jj, giao diện dòng lệnh của Jujutsu, là một công cụ dựa trên hệ thống quản lý phiên bản phân tán (DVCS)
  • Cung cấp các tính năng đơn giản, trực quan hơn git nhưng vẫn mạnh mẽ hơn
  • Kết hợp ưu điểm của git và Mercurial để giảm số lượng công cụ cốt lõi và tăng cường sự liên kết hữu cơ giữa chúng
  • Sử dụng backend tương thích git để có thể thử nghiệm độc lập mà vẫn giữ nguyên môi trường cộng tác hiện có
  • Với người dùng nâng cao, điểm quan trọng là có thể tận dụng các tính năng quản lý phiên bản bổ sung vốn khó thực hiện bằng git

Giới thiệu và đặc điểm của jj

  • jj là CLI (giao diện dòng lệnh) của Jujutsu, và Jujutsu là hệ thống quản lý phiên bản phân tán (DVCS)

    • Người dùng có thể đã quen với các DVCS khác như git, và hướng dẫn này được viết với giả định từ góc nhìn của người dùng git
    • jj được thiết kế là công cụ đơn giản, dễ dùng hơn git nhưng vẫn mạnh mẽ
    • Thông thường, “mạnh mẽ” và “phức tạp” là hai yếu tố đối nghịch, nhưng jj đưa ra một cách cân bằng mới
    • jj kết hợp ưu điểm của git và Mercurial(hg) để tạo nên một dạng DVCS mới
    • Giảm số lượng công cụ cốt lõi và cung cấp môi trường làm việc hiệu quả thông qua sự liên kết hữu cơ giữa từng công cụ
    • Người dùng nâng cao có thể tận dụng các tính năng quản lý phiên bản bổ sung vốn khó thực hiện với git
    • jj sử dụng backend tương thích git để có thể thử nghiệm độc lập mà không cần thay đổi môi trường cộng tác
    • Vẫn duy trì khả năng tương thích với kho lưu trữ git hiện có, và khi cần cũng có thể dễ dàng quay lại git
    • Hướng dẫn này báo trước quá trình trực tiếp cho thấy vì sao jj là một công cụ đáng chú ý thông qua những đặc tính đó

1 bình luận

 
Ý kiến Hacker News
  • Nhiều thảo luận tập trung vào sự khác biệt giữa git và jj, nhưng tôi nghĩ tốt hơn là cứ quên git đi và tập trung vào workflow cơ bản của jj
    Khi ở một repository sạch, chỉ cần chạy jj là có thể kiểm tra trạng thái, sau đó sửa đổi xong thì commit bằng jj commit -m "made changes"
    Nếu lỡ làm sai, sửa lại rồi dùng jj squash để gộp vào commit cuối cùng
    Chỉ khi muốn làm việc từ một revision cụ thể như tạo branch mới thì mới cần dùng jj new -r lmnop
    Có thể xem lịch sử git bằng git log, còn cơ chế hoạt động nội bộ của jj thì không hiện ra

    • Tôi cũng muốn thứ gì đó tương tự nên đã tạo git alias như alias.save="!git add -A; git commit -m" và dùng kiểu $ git save "made changes"
  • Tôi có cảm giác JJ bắt tôi phải nghĩ ngược lại
    Trong git, bạn sửa xong rồi mới viết message commit, còn jj thì giống như tạo commit mới trước rồi mới gắn mô tả
    Tôi quen với việc ở trong một trạng thái lộn xộn có nhiều tính năng trộn lẫn rồi chọn ra đúng phần thay đổi cần thiết để commit, nhưng chỉ xem tutorial của jj thì tôi chưa chắc điều đó có làm được không

    • jj new là một khái niệm giống vùng staging trống của git
      Trong jj luôn có một commit tồn tại, và commit đó có changeid ổn định là giá trị được tính từ nội dung thư mục
      Nếu muốn tách nhiều thay đổi thành các commit riêng thì dùng jj split
    • Tôi thường tạo commit tạm bằng jj new và để trống message
      Khi đã sẵn sàng, tôi squash nhiều commit lại thành một và thêm message sau
      Cách này hoạt động như một loại lịch sử undo, nên việc thử nghiệm thoải mái hơn nhiều
    • Thực ra jj new chỉ đơn giản là “tạo một commit mới ở phía trên”, nên không cần phải viết mô tả ngay
      Ban đầu tôi cũng cố tạo thói quen đó, nhưng hóa ra lại kém hiệu quả hơn
    • Trong JJ thì cách làm này là chuẩn mực
      Git cũng đã khuyến nghị workflow tương tự từ lâu, và nếu xem Squash Workflow thì có thể tạo ra luồng làm việc gần giống index của Git
    • Tôi cũng hay gặp tình huống đang làm nhiều thay đổi thì các tính năng khác nhau bị trộn vào nhau
      Vì thế tôi dùng nhiều workspace và thường xuyên dùng tính năng shelve (IntelliJ)
      Đôi khi tôi còn tạm lưu diff bằng git patch
      Tôi cố giấu quy trình hỗn loạn này với đồng nghiệp để trông chuyên nghiệp hơn một chút
  • Điều tôi không thích khi dùng jj là việc sửa file sẽ tự động được commit
    Nếu checkout để duyệt một commit cũ rồi sửa file, commit đó sẽ bị thay đổi và toàn bộ lịch sử phía sau sẽ được rebase lại
    Vì thế tôi phải phòng thủ bằng cách tạo một commit rỗng mới
    Với git thì repository không thay đổi cho đến khi tôi commit một cách tường minh, nên thấy thoải mái hơn

    • Trước đây tôi cũng nghĩ vậy, nhưng sau khi biết jj evolog thì suy nghĩ đã thay đổi
      jj đã có sẵn một lời giải tốt hơn staging
      Việc quá quen với git CLI lại trở thành rào cản khi học jj
      Điều thú vị là dùng jj lại giúp hiểu rõ hơn về cấu trúc storage engine của git
    • Dùng edit thay vì jj new thì có thể theo dõi thay đổi gọn gàng hơn
      Tôi thấy còn tốt hơn nhiều so với việc phải juggling với stash của git
    • jj editcái bẫy lớn nhất của jj
      Thay vào đó hãy dùng jj new, và nếu lỡ sai thì có thể khôi phục bằng jj undo
      jj coi commit là các snapshot rẻ, nên hợp lý hơn khi tập trung vào “thay đổi” thay vì commit
      Việc auto rebase sẽ được cố định bất biến sau khi push nên vẫn an toàn
    • Việc sửa file được auto commit là tính năng cốt lõi của jj
      Chỉ cần kết hợp jj newjj squash để quản lý như branch head của git
      jj khiến việc làm việc trong trạng thái detached head trở nên dễ dàng
    • Có lẽ bạn đã checkout commit cũ bằng jj edit
      Nếu đổi sang jj new thì vấn đề sẽ được giải quyết
  • Đoạn cuối của jj mới là điểm mấu chốt
    Nó dùng backend tương thích hoàn toàn với git, nên bạn có thể tự dùng thử mà không cần cả nhóm cùng chuyển đổi
    Nếu không thích thì lúc nào cũng có thể quay về git

    • Tuy vậy, sẽ có ngoại lệ ở các tổ chức dùng LFS, submodule hoặc hook
    • Không phải tương thích hoàn toàn. Có thể tương tác với nhau, nhưng không hoàn toàn trơn tru
      Các thao tác git sẽ không được ghi vào log của jj nên phải import thủ công
      Trong một dự án, tốt nhất chỉ nên dùng một interface
    • Trước đây tôi cũng từng dùng git theo kiểu đó cùng với CVS và Subversion
    • Nhưng nếu dùng git và jj đồng thời trong cùng một thư mục thì có thể làm hỏng mọi thứ
  • Tính năng tôi thích nhất là jj absorb
    Nó tự động chuyển các thay đổi của revision hiện tại sang những commit trước đó có liên quan
    Rất hữu ích khi quên sửa file config hoặc .gitignore
    Chỉ cần jj new, sửa đổi rồi chạy jj absorb
    Tuyệt nhất là không phải xử lý merge conflict

    • Nếu jj absorb áp dụng sai thì có thể hoàn tác bằng jj undo
      Nhờ tính năng này mà cả rebase phức tạp cũng không còn đáng sợ
    • Nhân tiện, git cũng có git absorb
  • Tôi đã không cập nhật tutorial trong một thời gian dài, nhưng vẫn dùng jj hằng ngày
    Tôi bận ở startup ersc.io nên chưa thể làm việc upstream
    Nếu có câu hỏi thì lúc nào cũng hoan nghênh

    • Điểm cốt lõi là sự khác biệt về tính bất biến của DAG giữa git và jj
      jj dùng stable change ID, còn git dùng immutable commit ID
      Vì thế trong jj, undo hay rebase có cảm giác linh hoạt hơn nhiều
    • jj tự động ẩn các thay đổi “không thú vị”
      Đôi khi tôi muốn xem nhiều thay đổi hơn, không biết có tùy chọn nào để hiện tất cả một lần không
  • jj khác git đủ nhiều để đáng thử
    Chỉ riêng việc trải nghiệm một cách tiếp cận khác cũng đã giúp mở rộng góc nhìn kỹ thuật
    Không cần phải thử mọi thứ, nhưng hiểu được trade-off của các workflow khác nhau là điều quan trọng

    • Tất nhiên, trong 99% trường hợp thì những thử nghiệm lợi ích ít ỏi có thể chỉ là lãng phí thời gian
  • Mối quan hệ giữa git và jj khiến tôi liên tưởng đến quan hệ giữa C và Python
    git giống như truy vết pháp chứng, còn jj giống như các chương của một câu chuyện
    Đôi khi phải viết lại chương đầu thì phần sau mới trở nên tự nhiên hơn

    • Những gì jj làm thì git cũng làm được, nhưng cách tư duy theo thói quen của git lại cản trở
      jj được thiết kế theo triết lý “working tree tự thân là commit” và “xung đột cũng có thể được commit”
  • Tôi cảm thấy tuyên bố “mạnh hơn và dễ hơn” cần có ví dụ cụ thể

    • Nếu phải kể vài ưu điểm của jj thì là:
      • Không cần giải quyết ngay rebase/merge conflict
      • Việc thao tác commit rất dễ (đặc biệt khi dùng jjui)
      • jj có operation log để theo dõi các thay đổi trạng thái của git
      • Các branch không tên giúp thoải mái làm việc mang tính thử nghiệm
      • Tương thích hoàn toàn với git nên có thể dùng lẫn trong nhóm
    • Khi chúng tôi chuyển từ SVN sang git, đó là một cải tiến lớn, nhưng hiện tại workflow git không còn gây khó chịu lớn nào
    • Có thể làm nhiều PR cùng lúc trong một repository và push từng cái theo cách phù hợp
      Nếu không có nhu cầu này thì có thể bạn sẽ không cảm thấy giá trị của jj
    • Sức hấp dẫn của jj không nằm ở câu lệnh mà ở workflow trực quan
      Phải tự dùng thì mới hiểu được
    • Chỉ riêng jj undo thôi cũng đã đủ đáng giá
      Trong git rất dễ rơi vào trạng thái không thể khôi phục, còn trong jj thì chỉ cần undo vài lần là giải quyết được
  • Nhờ jj mà tôi tự tin hơn khi tận dụng DAG phi tuyến tính
    Tôi thoải mái xử lý các thay đổi có nhiều parent hoặc child
    Trước đây tôi thường ép thứ tự một cách không cần thiết, nhưng giờ có thể biểu đạt quan hệ phụ thuộc rõ ràng
    Quá trình review và submit cũng hiệu quả hơn nhiều

    • Tôi tò mò không biết trên những thay đổi phân nhánh như vậy, mọi người có dùng workflow mega-merge + absorb hay không