- Manyana là một nguyên mẫu quản lý phiên bản dựa trên CRDT do Bram Cohen phát triển, đưa ra một cách tiếp cận mới nhằm loại bỏ xung đột hợp nhất và bảo tồn lịch sử theo cấu trúc
- Bằng cách sử dụng CRDT (Conflict-Free Replicated Data Type), việc hợp nhất luôn thành công, và xung đột được xử lý như thông tin hiển thị để người dùng có thể nhận biết rõ các thay đổi
- Các điểm cốt lõi gồm tính bền vững của thứ tự dòng, hợp nhất không chặn, và lịch sử được nội tại hóa, đồng thời không phá hủy các bản ghi hiện có ngay cả trong quá trình rebase
- Đây là một bản triển khai ở mức demo được viết bằng khoảng 470 dòng mã Python, với toàn bộ mã nguồn và tài liệu thiết kế được công bố trên GitHub dưới dạng public domain
- Một ví dụ thử nghiệm đề xuất mô hình quản lý phiên bản thế hệ tiếp theo không có thất bại khi hợp nhất, vượt qua các giới hạn của Git
Manyana: Tầm nhìn nhất quán cho tương lai của quản lý phiên bản
- Manyana là một nguyên mẫu hệ thống quản lý phiên bản dựa trên CRDT do Bram Cohen công bố, nhằm giải quyết vấn đề xung đột hợp nhất trong các hệ thống hiện có
- CRDT bảo đảm việc hợp nhất luôn thành công, đồng thời xử lý xung đột như các chỉ dấu mang tính thông tin để người dùng có thể xác nhận rõ những thay đổi thực tế
- Cách tiếp cận này có ba đặc tính cốt lõi: tính bền vững của thứ tự dòng, xử lý xung đột không chặn, và lịch sử được nội tại hóa trong cấu trúc
- Ngay cả trong quá trình rebase, hệ thống vẫn giữ nguyên lịch sử hiện có và có thể xử lý ổn định cả các cấu trúc hợp nhất phức tạp không có một tổ tiên chung duy nhất
- Manyana là một bản triển khai demo được viết bằng khoảng 470 dòng mã Python, và tài liệu thiết kế cùng mã nguồn đã được công bố trên GitHub dưới dạng public domain
Cốt lõi của cách tiếp cận dựa trên CRDT
- CRDT cung cấp eventual consistency bảo đảm việc hợp nhất luôn thành công và cho ra cùng một kết quả bất kể thứ tự hợp nhất
- Dù nhiều người dùng làm việc độc lập trên các nhánh khác nhau và hợp nhất chúng theo bất kỳ thứ tự nào, kết quả vẫn được giữ nguyên như nhau
- Thông qua tính bền vững của thứ tự dòng, một khi thứ tự của đoạn mã được chèn vào cùng một vị trí đã được xác định, nó sẽ tiếp tục được giữ nguyên về sau
- Nhờ đó ngăn được vấn đề vùng xung đột được giải quyết khác nhau giữa các nhánh
- Xung đột chỉ được xử lý như chỉ dấu cung cấp thông tin và không chặn quá trình hợp nhất
- Kết quả hợp nhất luôn được tạo ra, và xung đột được đánh dấu là “những phần được sửa đồng thời ở vị trí gần nhau”
- Hệ thống theo dõi chủ thể và hành động của từng thay đổi để cung cấp chỉ dấu xung đột hữu ích
- Lịch sử được nội tại hóa trong cấu trúc
- Trạng thái được biểu diễn bằng cấu trúc ‘weave’ bao gồm mọi dòng của tệp, trong đó mỗi dòng mang metadata về thời điểm được thêm hoặc xóa
- Khi hợp nhất, chỉ cần đưa vào hai trạng thái là luôn tạo ra kết quả đúng mà không cần tìm tổ tiên chung hay duyệt DAG
Chỉ dấu xung đột được cải thiện
- Các hệ thống quản lý phiên bản truyền thống khi gặp xung đột thường chỉ hiển thị hai khối mã cạnh nhau, buộc người dùng phải tự suy luận sự khác biệt
- Manyana biểu thị mỗi vùng xung đột một cách rõ ràng như “đã bị xóa”, “đã được thêm”, đồng thời cho biết ai đã thực hiện thay đổi nào
- Ví dụ, nếu một người dùng xóa một hàm còn người khác thêm một dòng bên trong hàm đó, Manyana sẽ hiển thị rõ ràng cấu trúc của từng thay đổi
- Nhờ vậy, thay vì phải so sánh hai khối mã, người dùng có thể nắm ngay ý nghĩa và ngữ cảnh của thay đổi
Định nghĩa lại rebase
- Trong hệ thống dựa trên CRDT, rebase không phá hủy lịch sử
- Rebase truyền thống xếp lại các commit lên trên một base mới và tạo ra một lịch sử hư cấu
- Với Manyana, vẫn đạt được hiệu quả tương tự nhưng giữ lại toàn bộ lịch sử gốc
- Để làm điều này, chỉ cần thêm chú thích “primary ancestor” vào DAG
- Cách làm này hoạt động ổn định ngay cả trong cấu trúc hợp nhất không có tổ tiên chung, và có thể tránh được thất bại của kiểu hợp nhất 3 chiều truyền thống
Trạng thái hiện tại của dự án
- Manyana là bản triển khai demo chứ chưa phải một hệ thống quản lý phiên bản hoàn chỉnh, và hoạt động ở mức tệp đơn lẻ
- Gồm khoảng 470 dòng mã Python
- Các tính năng cherry-pick và local undo vẫn chưa được triển khai, nhưng README đã nêu định hướng thực hiện sau này
- Dự án này chứng minh rằng quản lý phiên bản dựa trên CRDT có thể giải quyết các vấn đề UX, đồng thời mang lại kết quả tốt hơn các công cụ hiện có
- Toàn bộ mã nguồn được phát hành dưới dạng public domain, và toàn bộ tài liệu thiết kế được đưa vào README trên GitHub
Tóm tắt phản ứng từ cộng đồng
- Một người dùng cho rằng Git đã được dùng hơn 10 năm, nhưng cần một mô hình quản lý phiên bản mới, và nhắc đến nỗ lực của Manyana theo hướng tích cực
- Người này chỉ ra rằng khái niệm việc hợp nhất luôn thành công không hẳn là trực quan, và yêu cầu thêm ví dụ và giải thích
- Họ bày tỏ sự quan tâm tới ý tưởng cải thiện rebase, đồng thời nói rằng trong dự án cá nhân họ đang dùng cách quản lý hợp nhất qua các nhánh trung gian
- Họ cũng chỉ ra các giới hạn của Git như xử lý tệp nhị phân, sự nhầm lẫn trong phân biệt nhánh trái/phải, và thiếu khả năng tóm tắt các thay đổi mã nguồn quy mô lớn
- Họ đề xuất rằng quản lý phiên bản trong tương lai nên hỗ trợ khả năng nhận biết theo token (token-aware) hoặc plugin theo ngôn ngữ/định dạng tệp
- Một người dùng khác hỏi liệu Manyana có nền tảng tương tự Pijul hoặc Darcs hay không, đồng thời yêu cầu so sánh vấn đề hiệu năng của Darcs với tình trạng hiện tại của Pijul
Kết luận
- Manyana là một bản demo thực tiễn áp dụng CRDT vào quản lý phiên bản, tái thiết kế một cách căn bản vấn đề xử lý xung đột và rebase
- Cấu trúc không có thất bại khi hợp nhất, việc biến xung đột thành thông tin, và sự nội tại hóa lịch sử trong cấu trúc đều cho thấy một hướng thiết kế vượt qua giới hạn của mô hình Git hiện tại
- Dù chưa phải một hệ thống hoàn chỉnh, đây vẫn là một điểm khởi đầu có ý nghĩa như bản thiết kế cho hệ thống quản lý phiên bản thế hệ tiếp theo
1 bình luận
Ý kiến Hacker News
Tôi nghĩ cách hiển thị merge là một vấn đề tách biệt với cách biểu diễn lịch sử
Tôi cũng ghét UI merge mặc định của Git nên dùng p4merge. Đây là công cụ hiển thị bốn panel (trái, phải, base chung, kết quả), nên có thể nhìn một phát là hiểu nguyên nhân xung đột và cách xử lý
Tôi không thấy cần phải thay cả VCS chỉ vì chuyện đó
merge.conflictStylecủa Git sang"diff3"hoặc"zdiff3"thì sẽ hiển thị cả phiên bản baseLàm vậy thì chỉ cần nhìn conflict marker cũng có thể suy ra bên nào đã thêm mã mới
Trước đây tôi từng nghe một podcast có khách mời làm VCS mới nhưng lại hiểu sai cách Git lưu diff, và thấy khá sốc. Làm dự án nhiều năm mà còn chưa tìm hiểu cả khái niệm cơ bản, đủ thấy tinh thần NIH (tự phát minh lại bánh xe) vẫn còn sống khỏe
Tuy vậy, xử lý ở cấp SCM có lợi thế là có thể ghi nhớ lịch sử merge của người dùng. Git có vài edge case ở chỗ này
Tôi không chắc việc merge tuyệt đối không bao giờ thất bại có thực sự là điều tốt hay không
Merge thất bại thường không chỉ là xung đột vị trí đơn thuần, mà còn là tín hiệu cho thấy có xung đột ngữ nghĩa. Những trường hợp đó phải xử lý thủ công
Tôi nghĩ CRDT không phù hợp cho quản lý phiên bản
Xung đột là bản chất của quản lý phiên bản. Khi hai lập trình viên sửa mã theo hai hướng khác nhau, cuối cùng vẫn cần một lựa chọn về ngữ nghĩa. CRDT rất dễ tạo ra đoạn mã kỳ quặc trong những tình huống như vậy
Hiện đã có rất nhiều công cụ cung cấp UX merge tốt hơn trên nền Git, và việc cherry-pick hay revert dễ dàng cũng là một ưu điểm của Git
Ví dụ, ở một nhánh thì xóa hằng số, còn ở nhánh khác lại dùng hằng số đó, thì mã sẽ hỏng
Phần lớn xung đột của Git là vấn đề cú pháp, nên cách tiếp cận semantic merge thông minh hơn hoặc CRDT có thể vẫn hữu ích
Ví dụ, khi theo dõi tên file, thuộc tính, hash v.v. thì có thể dùng OR-set(https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type).
Tuy nhiên, việc giải quyết xung đột vẫn phải được xử lý ở giao diện bên ngoài
Tôi không hiểu vì sao lại tập trung vào CRDT đến vậy
Vấn đề ngữ nghĩa của xung đột vẫn còn nguyên. Thậm chí thay đổi còn có thể trông như bị đan xen (interleave) vào nhau nên càng rối hơn
Tôi là người theo chủ nghĩa rebase trước hết. Nên tránh merge commit, và mọi commit đều phải là đơn vị độc lập. Tôi xem Gitflow là một anti-pattern
Jujutsu hay Gerrit xử lý rất tốt vấn đề thật sự của Git là “quản lý chuỗi commit dựa trên phản hồi review”
Git áp dụng lại snapshot nên cùng một công việc về bản chất xuất hiện hai lần. Trong khi đó, Pijul hoạt động theo đơn vị patch, nên cho ra cùng một kết quả bất kể thứ tự. Tôi nghĩ đó mới là đơn vị công việc độc lập thật sự
Ngay cả khi đang có xung đột, vẫn có thể hoàn tác (undo) chỉ một commit cụ thể. Nó có thể có cấu trúc linh hoạt hơn Git
Trên thực tế, nhiều khi chỉ kết quả cuối cùng mới quan trọng. Kết hợp squash merge hợp lý sẽ thực tế hơn
Nhưng có những vấn đề về bản chất vẫn cần xung đột. Ví dụ như hiện tượng ký tự bị trộn lẫn trong trình soạn thảo đồng thời, thậm chí còn có thể cho ra kết quả tệ hơn
Dự án này có vẻ là phần mở rộng của ý tưởng từ Codeville mà Bram từng làm trước đây
Codeville xuất hiện vào thời kỳ bùng nổ DVCS đầu những năm 2000, và dùng lưu trữ và merge dựa trên weave. Đây là ý tưởng đi trước CRDT khoảng 10 năm, nhưng là một hướng phát triển rất tự nhiên
Thật vui khi thấy Bram vẫn bám theo bài toán này và tiếp tục thử nghiệm cái mới
arxiv:2002.09511
Tôi không đồng ý với nhận định “VCS dựa trên CRDT vẫn chưa tồn tại”
Pijul đã tồn tại rồi, và đó là một dự án mà các chuyên gia đã đổ vào hàng nghìn giờ công
Dự án đã thử nghiệm 6 năm rồi, tôi còn tự đăng issue từ 4 năm trước mà đến nay vẫn chưa được phản ánh
Pijul là một VCS được phát triển bằng chính nó, nên không dùng GitHub
pijul pull -athì bị conflict nên toàn clone lại. Không biết có kiểu pull nào để cập nhật theo dõi khôngmanana.py là đoạn mã Python không phụ thuộc gì dài 473 dòng
Phần triển khai thực tế chỉ khoảng 240 dòng, còn lại là test. Đơn giản nhưng rất ấn tượng
Nhìn lại sự cố left-pad của hệ sinh thái JS, tôi nghĩ Python cũng nên có nhiều gói nhỏ nhưng có trách nhiệm như thế hơn
Những hệ thống như thế này nên được thiết kế dựa trên việc phân tích mẫu hình merge conflict theo quy mô đội ngũ
Cần xem đội 1 người, 10 người, 100 người, 1000 người gặp những vấn đề gì, và phát triển dựa trên agent sẽ làm thay đổi điều đó ra sao
Theo kinh nghiệm của tôi, ở quy mô 1~100 người thì thường chia subtree mã theo từng nhóm nên gần như không có xung đột.
Khi agent tăng lên thì 100 người có thể thành 1000 người, nhưng hiện tại vẫn có cảm giác là giải pháp xuất hiện trước cả vấn đề thực tế
Dạo này cứ giao merge conflict cho Codex là xong, nên lý do để dùng VCS mới lại càng ít đi
Git được thiết kế cho đội ngũ lớn, và trong thời đại agent thì chỉ cần tự động hóa quy trình là đủ để thích nghi
Vấn đề thật ra lại nảy sinh ở nút thắt thư viện dùng chung hoặc chính sách hạn chế truy cập
Vấn đề lớn hơn xung đột là khả năng mở rộng (scalability) của Git
Kích thước kho và tốc độ thay đổi đang chạm đến giới hạn. Cần thiết kế lại toàn bộ server, client và giao thức
Cá nhân tôi không rõ hệ thống này giải quyết vấn đề gì
Xét ở mức trừu tượng thì khá thú vị, nhưng trong thực tế thì jj hữu dụng hơn Git rất nhiều
Tôi nghĩ bước tiếp theo là hệ thống quản lý phiên bản không ở cấp file mà ở mức AST.
Đã có những thử nghiệm như LightTable hay Dark; sẽ hay nếu thử nghiệm những VCS dựa trên cây như vậy