So sánh Diff

So sánh hai văn bản theo ký tự/từ/dòng. Tạo unified patch. Chỉ trong browser.

text-regex

Diff Checker

Original
Modified

Runs entirely in your browser. Your input never leaves your device.

What next?

How it works

Diff là gì

Diff là một mô tả tối giản về cách biến đổi văn bản này thành văn bản kia. Thay vì hiển thị toàn bộ hai tài liệu, diff chỉ làm nổi bật những gì thay đổi — các dòng thêm vào, dòng bị xóa, và các dòng context xung quanh chúng. Đây là khái niệm đứng sau git diff, lệnh patch(1), và mọi công cụ code review bạn từng dùng.

Thuật toán nền tảng trong hầu hết các diff tool hiện đại — bao gồm thư viện diff đang chạy trong tool này — là Longest Common Subsequence (LCS). LCS tìm chuỗi dài nhất các phần tử xuất hiện ở cả hai input theo cùng thứ tự, sau đó coi mọi thứ không thuộc chuỗi đó là đã được thêm vào hoặc xóa đi. Tính toán LCS có độ phức tạp O(n²) trong trường hợp xấu nhất, nhưng các implementation thực tế dùng thuật toán Myers — tối ưu hơn nhiều với input thông thường.

Line-level vs word-level diff

Có hai mức độ chi tiết bạn cần quan tâm:

Line-level diff chia mỗi văn bản thành các dòng, chạy LCS trên những dòng đó, và báo cáo toàn bộ dòng là được thêm, xóa, hoặc không thay đổi. Đây là mặc định của git diff. Phù hợp nhất cho source code vì dòng là đơn vị thay đổi tự nhiên — thêm một function nghĩa là thêm nhiều dòng, và line-level diff bắt chính xác điều đó.

Word-level diff (còn gọi là "intra-line diff") phân tích sâu hơn và tính LCS trên từng từ hoặc ký tự. Điều này tiết lộ những từ nào trong một dòng đã thay đổi. Cực kỳ hữu ích cho văn xuôi, hợp đồng, và JSON blob — nơi một dòng có thể dài 200 ký tự nhưng chỉ một giá trị thay đổi.

Dùng line-level khi review code hoặc config. Dùng word-level khi so sánh tài liệu, markdown, API response, hoặc bất kỳ văn bản nào cần độ chính xác dưới dòng.

Unified vs side-by-side format

Unified format là output kiểu diff -u truyền thống: các dòng context được đánh dấu bằng space, dòng xóa bằng -, dòng thêm bằng +. Header của một unified diff hunk trông như @@ -12,7 +12,9 @@, nghĩa là "bắt đầu từ dòng 12 trong file cũ, 7 dòng; bắt đầu từ dòng 12 trong file mới, 9 dòng." Format này gọn và thân thiện với grep — đây là thứ git diff tạo ra và patch tiêu thụ.

Side-by-side format hiển thị phiên bản cũ bên trái và phiên bản mới bên phải, với các dòng bị xóa được highlight ở cột trái và dòng được thêm ở cột phải. Side-by-side dễ đọc hơn cho người review diff lớn — bạn thấy trước và sau cùng lúc mà không cần chuyển ngữ cảnh. Hầu hết các web UI review code (GitHub, GitLab, Bitbucket) mặc định dùng side-by-side.

Khi nào nên dùng diff tool

Chuẩn bị code review. Trước khi mở pull request, paste hai phiên bản của một function quan trọng vào diff checker để xác minh delta chính xác như bạn muốn — không có thay đổi whitespace vô tình, không có console.log debug bỏ quên.

Content QA. So sánh hai bản nháp của bài blog hay trang tài liệu nhanh hơn nhiều với word-level diff so với đọc thủ công. Một câu thay đổi sẽ hiển thị ngay lập tức.

Hợp đồng và văn bản pháp lý. Ngay cả việc đổi "shall" thành "may" cũng có ý nghĩa pháp lý; word-level diff bắt được ngay.

Configuration drift. Khi config file của server khác với phiên bản trong source control, line-level diff chỉ ra chính xác dòng nào bị chỉnh sửa.

Thay đổi API response. Paste response của hôm qua cạnh response hôm nay để phát hiện schema drift — đặc biệt hữu ích khi nâng cấp third-party API.

Giới hạn cần biết

Textual, không phải semantic. Diff tool so sánh chuỗi ký tự, không hiểu ngữ nghĩa. Rename một function từ getUser thành fetchUser ở 500 dòng code trông như 50 thay đổi riêng biệt dù về logic chỉ là một refactor.

Nhạy cảm với whitespace. Mặc định, một khoảng trắng thừa hay tab-vs-space tính là thay đổi. Bật tùy chọn Ignore whitespace để lọc bỏ khác biệt whitespace không đáng kể.

Input lớn. Độ phức tạp của LCS tăng đáng kể với input rất lớn. Với file hàng chục nghìn dòng, diff command-line hoặc tool có streaming support sẽ hiệu quả hơn.

Không có merge logic. Diff chỉ cho thấy thay đổi. Nó không tự động merge hai phiên bản phân kỳ hay giải quyết conflict — đó là bài toán three-way merge mà git mergediff3 xử lý.

Quyền riêng tư

Toàn bộ quá trình tính diff diễn ra trong trình duyệt của bạn bằng thư viện open-source diff. Không có văn bản nào của bạn được gửi đến server. Mở tab Network trong DevTools trong khi chạy diff — bạn sẽ thấy không có request nào.

Công cụ liên quan

  • Regex Tester — kiểm tra và lặp lại với regular expression trước khi dùng trong workflow find-and-replace.
  • Text Case Converter — chuẩn hóa casing trước khi diff để giảm noise.

FAQ

Tool dùng thuật toán gì để tính diff?

Tool dùng thuật toán Longest Common Subsequence (LCS), cụ thể là thuật toán Myers được implement trong thư viện open-source diff. Thuật toán Myers tìm edit script tối giản giữa hai chuỗi trong thời gian O(ND), trong đó N là tổng độ dài input và D là kích thước diff. Với input thông thường, điều này nhanh hơn nhiều so với độ phức tạp O(n²) của LCS naive.

Sự khác biệt giữa line-level và word-level diff là gì?

Line-level diff coi mỗi dòng là một đơn vị nguyên tử — toàn bộ dòng được đánh dấu thêm, xóa, hoặc không thay đổi. Word-level diff (intra-line diff) chia nhỏ hơn thành từng token và highlight chính xác những từ nào thay đổi. Dùng line-level cho source code vì dòng là đơn vị tự nhiên; dùng word-level cho văn xuôi, hợp đồng, hay JSON nơi một giá trị quan trọng có thể thay đổi trong một dòng dài.

Header @@ trong unified diff output có nghĩa gì?

Header @@ -12,7 +12,9 @@ nghĩa là: trong file gốc, hunk bắt đầu ở dòng 12 và kéo dài 7 dòng; trong file mới nó bắt đầu ở dòng 12 và kéo dài 9 dòng. Dòng có tiền tố - bị xóa, dòng có + được thêm, và dòng có space là context không thay đổi. Đây là format chuẩn của diff -u và được patch tiêu thụ.

Tôi có thể dùng tool này để diff source code không?

Được — paste hai phiên bản file vào hai ô text và chạy diff. Đặc biệt hữu ích để chuẩn bị code review, giúp bắt các thay đổi vô tình (log debug bỏ sót, whitespace thay đổi không mong muốn) trước khi mở pull request. Để so sánh toàn bộ repository hoặc theo dõi lịch sử, dùng git diff vì nó có access vào toàn bộ commit graph.

Tại sao diff của tôi hiển thị những thay đổi tôi không thực hiện (whitespace noise)?

Editor thường khác nhau về trailing whitespace, kiểu end-of-line (CRLF vs LF), hay indentation (tabs vs spaces). Bật tùy chọn Ignore whitespace để loại bỏ các khác biệt whitespace không đáng kể trước khi chạy LCS. Với vấn đề dai dẳng, chuẩn hóa line ending trước bằng dos2unix hoặc tính năng "trim trailing whitespace" của editor.

Input của tôi có được gửi lên server không?

Không. Toàn bộ diff được tính trong trình duyệt của bạn bởi thư viện diff — một implementation pure JavaScript không có server call. Input của bạn không rời khỏi thiết bị, điều này an toàn khi dùng với hợp đồng bảo mật, source code riêng tư, hay bất kỳ văn bản nào bạn không muốn truyền qua mạng.

Giới hạn kích thước input là bao nhiêu?

Thực tế, đến vài trăm kilobyte mỗi bên chạy mượt mà. Vượt quá đó, thời gian tính toán LCS tăng và trình duyệt có thể tạm dừng. Với file lớn (log nhiều MB, SQL dump lớn), diff command-line hoặc tool chuyên dụng có streaming support sẽ hiệu quả hơn.

Diff checker có thể phát hiện các đoạn văn bản bị di chuyển không?

Không — LCS-based diff thuần tuý theo vị trí và thứ tự. Nếu bạn di chuyển một đoạn từ đầu tài liệu xuống cuối, diff sẽ hiển thị vị trí gốc là xóa và vị trí mới là thêm, không phải là "move". Phát hiện di chuyển cần một lớp semantic (similarity hashing, AST analysis) vượt ngoài phạm vi text diff.