So Sánh Văn Bản & Hợp Nhất
Dán hai phiên bản văn bản và so sánh chúng từng dòng với các khác biệt được tô màu.
Kết quả so sánh
Cách hoạt động
- Dán hai văn bản: nhập văn bản gốc vào ô bên trái và văn bản đã chỉnh sửa vào ô bên phải.
- Xem các khác biệt: các dòng đã thay đổi được làm nổi bật, xanh lá cho thêm vào, đỏ cho xóa và vàng cho sửa đổi.
- Duyệt diff: cuộn qua các thay đổi được tô màu và sao chép hoặc chụp ảnh các phần bạn cần.
Lịch sử ngắn của Diff
Diffing văn bản hiện đại bắt đầu tại Bell Labs. Douglas McIlroy (cùng McIlroy đã phát minh ra pipe Unix) và James W. Hunt đã viết Unix diff nguyên bản vào đầu những năm 1970; nó được giao như một phần của Phiên bản thứ 5 của Unix vào năm 1974. Thuật toán được ghi lại trong Bell Laboratories Computing Science Technical Report #41 (tháng 6 năm 1976), một báo cáo nội bộ có tiêu đề "An Algorithm for Differential File Comparison". Thuật toán Hunt-McIlroy được xây dựng trên bài toán subsequence chung dài nhất (LCS), tìm chuỗi dài nhất các dòng xuất hiện, theo thứ tự, trong cả hai đầu vào, và mọi thứ không nằm trong chuỗi đó hoặc là xóa hoặc là chèn. Một thập kỷ sau, Eugene W. Myers đã xuất bản "An O(ND) Difference Algorithm and Its Variations" trong Algorithmica, Tập 1 Số 2 (1986). Myers đã định khung lại bài toán như tìm đường đi ngắn nhất trên một "edit graph" và cho thấy nó có thể được giải trong thời gian và không gian O(ND), trong đó N là kích thước đầu vào và D là kích thước của script chỉnh sửa tối thiểu. Đối với đầu vào điển hình, các tệp chỉ khác nhau ở một vài nơi, D nhỏ, vì vậy thuật toán nhanh trong thực tế. Bài báo của Myers trở thành cơ sở cho một triển khai Unix diff nhanh hơn chạy nhanh gấp hai đến bốn lần so với người tiền nhiệm và tạo ra đầu ra chất lượng cao hơn. Patience diff (Bram Cohen, 2008) là một sự tinh chỉnh LCS ưu tiên các dòng neo duy nhất, tạo ra các diff dễ đọc hơn xung quanh các khối đã di chuyển. Mặc định hiện tại trong git diff là thuật toán histogram trong LibXDiff, thường được coi là nhanh hơn Myers vanilla và tạo ra các diff dễ đọc hơn khi có các khối được di chuyển (nó trở thành mặc định của Git trong 2.11, phát hành 29 tháng 11 năm 2016). Các nền tảng toán học còn đi sâu hơn: khoảng cách Levenshtein (Vladimir Levenshtein, 1965) là người anh em họ cấp ký tự của bài toán LCS, và giải pháp lập trình động Wagner-Fischer (1974) là những gì mọi thư viện "fuzzy match" vẫn triển khai bên trong.
Cách một Diff được render
Có bốn quy ước trực quan phổ biến để hiển thị một diff. Cạnh nhau, hai cột, bản gốc bên trái, đã sửa đổi bên phải, với các dòng tương ứng được căn chỉnh. Tốt cho so sánh thoáng qua; hoạt động tốt ở chiều rộng máy tính để bàn nhưng trở nên khó đọc trên viewport di động hẹp. Diff thống nhất nội tuyến, một cột duy nhất hiển thị các dòng đã xóa (thường có tiền tố - và được tô màu đỏ), các dòng được thêm vào (+, xanh lá), và các dòng ngữ cảnh không thay đổi (không có tiền tố, văn bản thuần). Layout mà git diff sử dụng theo mặc định. Quy mô tốt cho di động nhưng mất tính song song không gian của cạnh nhau. Diff cấp từ, chỉ nổi bật những từ đã thay đổi trong các dòng đã thay đổi. Hữu ích cho so sánh prose nơi hầu hết văn bản không thay đổi nhưng các cụm từ cụ thể đã được chỉnh sửa. Diff cấp ký tự, nổi bật mọi ký tự đã thay đổi riêng lẻ. Hữu ích cho những thay đổi rất nhỏ (sửa lỗi đánh máy, chỉnh sửa một chữ số) nơi cấp từ sẽ nổi bật toàn bộ từ. Quy ước màu sắc nhất quán đáng chú ý trên toàn hệ sinh thái: xanh lá cho bổ sung, đỏ cho xóa bỏ, vàng hoặc hổ phách cho giá trị đã thay đổi, xám trung tính hoặc không có kiểu cho không thay đổi. Công cụ này sử dụng kiểu thống nhất nội tuyến với nổi bật cấp ký tự bên trong các dòng đã thay đổi, một hybrid quy mô tốt cho di động trong khi bảo toàn độ chính xác của so sánh cấp ký tự cho chỉnh sửa prose.
Merge ba chiều, khi hai diff cần kết hợp
Một diff hai chiều (công cụ này) cho bạn biết điều gì đã thay đổi giữa phiên bản A và phiên bản B. Merge ba chiều trả lời một câu hỏi khó hơn: cho một tổ tiên chung và hai bản sửa đổi khác nhau, kết quả kết hợp nào kết hợp cả hai bộ thay đổi? Đây là hoạt động cốt lõi của mọi hệ thống kiểm soát phiên bản, khi hai developer chỉnh sửa cùng một tệp một cách độc lập và một người cố gắng merge công việc của họ, hệ thống cần áp dụng cả hai diff cho bản gốc. Thuật toán diff3 được chính thức hóa bởi Khanna, Kunal và Pierce (2007) là cơ sở. Quy ước đánh dấu xung đột bảy ký tự, <<<<<<<, =======, >>>>>>>, mà Git chèn vào các tệp khi merge tự động thất bại, đến trực tiếp từ dòng dõi này. Các công cụ merge trực quan hiện đại (trình chỉnh sửa merge ba ngăn của VS Code, mặc định bật từ 1.69 vào tháng 6 năm 2022; Beyond Compare từ Scooter Software, từ 1996; Meld; Kaleidoscope bởi Black Pixel cho macOS) xử lý các merge ba chiều với rendering cạnh nhau của cả ba phiên bản cộng với ngăn thứ tư cho kết quả merge được đề xuất. Công cụ này tập trung vào so sánh hai chiều, merge ba chiều thuộc về quy trình kiểm soát phiên bản thực sự.
Các trường hợp sử dụng phổ biến
- Code review. Dán hai phiên bản của một hàm hoặc module để phát hiện thay đổi nhanh chóng, đặc biệt khi làm việc bên ngoài quy trình Git (một đoạn từ email của đồng nghiệp, một câu trả lời Stack Overflow vs mã hiện tại của bạn).
- So sánh hợp đồng pháp lý. Luật sư và đàm phán hợp đồng thường so sánh hai phiên bản của một hợp đồng để xem bên kia đã thay đổi những gì. Thuật ngữ legal-tech là so sánh "blackline" hoặc "redline"; các sản phẩm như Draftable chuyên về điều này.
- Chỉnh sửa prose. So sánh bản nháp của một nhà văn với bản sửa đổi của một biên tập viên, hoặc hai phiên bản của một bài viết. Track Changes của Microsoft Word làm điều này trong sản phẩm; cho các bản nháp văn bản thuần hoặc Markdown, một công cụ diff là tương đương.
- Drift cấu hình. So sánh tệp cấu hình trong production với phiên bản trong kiểm soát nguồn, khoảng cách là drift. Quy trình tương tự cho các cấu hình theo môi trường cụ thể (dev vs staging vs production).
- So sánh log. Diffing hai tệp log từ các lần chạy khác nhau của cùng một quy trình để tìm điểm phân kỳ.
- Đánh giá bản địa hóa. Người dịch thường xuyên diff một nguồn tiếng Anh mới so với phiên bản trước để xác định chính xác những gì là mới và cần dịch.
Hệ sinh thái Diff vào năm 2026
Ngoài git diff và Unix diff, một số công cụ diff chuyên biệt đáng được đề cập. Beyond Compare (Scooter Software, 1996) là công cụ so sánh thư mục và tệp thương mại lâu đời, phổ biến với các developer và chuyên gia CNTT cho diffing giữa các máy. Meld (mã nguồn mở, dựa trên GTK) là mặc định của GNOME. Kaleidoscope (Black Pixel, macOS) tích hợp với kiểm soát phiên bản và là lựa chọn de facto cho nhiều developer Mac. Trình chỉnh sửa diff tích hợp của VS Code xử lý so sánh hai chiều và ba chiều một cách bản địa; trình chỉnh sửa merge ba ngăn trở thành mặc định bật trong 1.69 (tháng 6 năm 2022). Mergely (Wayne Stidolph, 2013, giấy phép MIT) là trình chỉnh sửa merge hai chiều dựa trên trình duyệt kinh điển được xây dựng trên CodeMirror. jsdiff (Kevin Decker, khoảng 2010) là thư viện diff JavaScript thống trị, được sử dụng bởi mọi công cụ diff dựa trên trình duyệt mà bạn từng dán vào. diff-match-patch (Neil Fraser tại Google, 2006) là thư viện thay thế xử lý diffing, fuzzy matching và tạo patch trong một API duy nhất; được sử dụng trong lịch sử sửa đổi Google Docs. Diffchecker là dịch vụ diff trực tuyến freemium thống trị, đầy đủ tính năng nhưng với quyền riêng tư trả phí (tầng miễn phí gửi văn bản đến máy chủ của họ). text-compare.com là trang web diff văn bản thuần chạy lâu nhất, UI cũ kỹ nhưng chức năng.
Quyền riêng tư: Tại sao chỉ-trình duyệt quan trọng đặc biệt ở đây
Mọi diff đều tiết lộ chính xác những gì đã thay đổi giữa hai phiên bản, và những gì đã thay đổi thường nhạy cảm hơn so với một trong hai phiên bản đơn lẻ. Ba kịch bản cụ thể nơi điều này quan trọng sâu sắc. Bản vá bảo mật: diffing phiên bản dễ bị tổn thương của một hàm với phiên bản đã được vá tiết lộ vị trí chính xác và bản chất của một lỗi bảo mật, kẻ tấn công tìm thấy bản vá có thể tạo ra một khai thác cho phiên bản chưa được vá (cuộc tấn công "patch gap" được ghi lại bởi Tian et al. tại USENIX Security 2017). Dán một bản vá bảo mật vào công cụ diff phía máy chủ về cơ bản là xuất bản lỗ hổng. Đàm phán hợp đồng: diffing hai phiên bản của một hợp đồng tiết lộ chính xác các điều khoản mà mỗi bên quan tâm, đó chính xác là thông tin bạn không muốn bên kia (hoặc bất cứ ai theo dõi mạng) có trong khi đàm phán. Các quyết định biên tập trước khi xuất bản: diffing một bản thảo trước và sau khi chỉnh sửa tiết lộ những gì tác giả và biên tập viên đã quyết định cắt hoặc thay đổi, thường tiết lộ hơn phiên bản xuất bản cuối cùng. Các công cụ diff phía máy chủ tải lên cả hai phiên bản cho bên thứ ba, nơi chúng nằm trong logs. Công cụ này chạy hoàn toàn trong trình duyệt của bạn qua JavaScript, xác minh trong tab Network của DevTools khi bạn nhấp Compare, hoặc đưa trang offline (chế độ máy bay) sau khi tải và công cụ vẫn hoạt động.
Câu hỏi thường gặp
Tôi có thể so sánh các tệp mã không?
Có. Dán bất kỳ văn bản nào, bao gồm mã, JSON, HTML, Markdown hoặc văn bản thuần. Diff hoàn toàn dựa trên văn bản, vì vậy nó hoạt động cho mọi định dạng.
Nó có bỏ qua sự khác biệt về khoảng trắng không?
Bật tùy chọn « Bỏ qua khoảng trắng » để bỏ qua các khác biệt chỉ là khoảng trắng hoặc kết thúc dòng. Hữu ích để so sánh mã được định dạng lại nhưng không thay đổi về cơ bản.
Công cụ này sử dụng thuật toán nào?
Thuật toán O(ND) của Myers (Eugene Myers, Algorithmica Tập 1 Số 2, 1986), cùng thuật toán mà GNU diff đã sử dụng theo mặc định trong nhiều thập kỷ và là cơ sở cho hầu hết các triển khai text-diff. Myers đã định khung lại bài toán subsequence chung dài nhất như tìm đường đi ngắn nhất trên một đồ thị chỉnh sửa, làm cho nó nhanh trong thực tế đối với các đầu vào chỉ khác nhau ở một vài nơi. Thuật toán histogram mới hơn (mặc định hiện tại của Git từ v2.11, tháng 11 năm 2016) xử lý các khối đã di chuyển tốt hơn một chút nhưng quá mức cần thiết cho trường hợp sử dụng hai-lần-dán điển hình mà công cụ này xử lý.
Có giới hạn kích thước không?
Không có giới hạn cứng, nhưng so sánh chạy trong trình duyệt của bạn qua JavaScript nên trần thực tế là bộ nhớ khả dụng của thiết bị của bạn. Hàng chục ngàn dòng hoạt động thoải mái. Các đầu vào rất lớn (tệp log nhiều megabyte, tiểu thuyết đầy đủ) sẽ chạy nhưng có thể mất vài giây đáng chú ý để render. Đối với các đầu vào thực sự khổng lồ hãy sử dụng diff của Git trên dòng lệnh, nó stream đầu ra và xử lý các tệp có kích thước tùy ý mà không có áp lực bộ nhớ.
Có thể thực hiện merge ba chiều hoặc áp dụng patch không?
Hiện tại không, công cụ này tập trung vào so sánh hai chiều (A vs B). Merge ba chiều (thuật toán diff3 với các đánh dấu xung đột <<<<<<< / ======= / >>>>>>>) là hoạt động mà Git sử dụng khi merge các nhánh; nó yêu cầu một tổ tiên chung cộng với hai phiên bản khác nhau. Đối với merge ba chiều, hãy sử dụng một hệ thống kiểm soát phiên bản thực sự hoặc một công cụ chuyên dụng như trình chỉnh sửa merge ba ngăn của VS Code (mặc định bật từ 1.69 vào tháng 6 năm 2022).
Văn bản của tôi có được tải lên không?
Không. So sánh chạy hoàn toàn trong trình duyệt của bạn qua JavaScript. Văn bản bạn dán không bao giờ băng qua mạng, xác minh trong tab Network của DevTools khi bạn nhấp Compare, hoặc đưa trang offline (chế độ máy bay) sau khi tải và công cụ vẫn hoạt động. Đặc biệt an toàn cho diffing các bản vá bảo mật (nơi chính diff tiết lộ lỗ hổng), sửa đổi hợp đồng (nơi diff tiết lộ vị trí đàm phán), hoặc các bản nháp biên tập trước khi xuất bản.