🔍
← Quay lại hướng dẫn

Cách đọc kết quả diff: Hiểu về tệp patch và các thay đổi

· Thẻ: diff-output, unified-diff, patch-file, diff-format, git-diff

Cách đọc kết quả diff: Hiểu về tệp patch và các thay đổi

Kết quả diff là ngôn ngữ phổ quát của các hệ thống quản lý phiên bản. Mọi nhà phát triển đều gặp kết quả diff thường xuyên — khi đánh giá mã nguồn, khi giải quyết xung đột hợp nhất (merge conflict), hoặc khi áp dụng các bản vá từ các đóng góp mã nguồn mở. Tuy nhiên, nhiều nhà phát triển chưa bao giờ học cách đọc kết quả diff một cách hiệu quả.

Hướng dẫn này giải thích cách đọc kết quả diff ở các định dạng phổ biến nhất, cách hoạt động của tệp patch và cách diễn giải các thay đổi một cách tự tin.

Kết quả diff là gì?

Kết quả diff là một biểu diễn có cấu trúc về những khác biệt giữa hai tệp hoặc các tập hợp tệp. Tiện ích diff, được tạo ra bởi Douglas McIlroy tại Bell Labs vào những năm 1970, vẫn là nền tảng của Git, Mercurial và hầu hết các hệ thống quản lý phiên bản khác.

Khi bạn chạy git diff hoặc bất kỳ lệnh diff nào, kết quả đầu ra hiển thị chính xác điều gì đã thay đổi, thay đổi ở đâu và thay đổi như thế nào — ở định dạng mà cả con người và máy móc đều có thể đọc được.

Hiểu về định dạng Unified Diff

Định dạng unified diff là định dạng đầu ra được sử dụng rộng rãi nhất hiện nay. Nó nhóm các thay đổi thành các hunk, mỗi hunk được đặt trước bởi các dòng ngữ cảnh giúp bạn định vị thay đổi trong tệp.

Giải phẫu tiêu đề hunk

Mỗi hunk bắt đầu bằng một tiêu đề trông như thế này:

@@ -start,count +start,count @@

Hãy phân tích điều này:

| Phần | Ý nghĩa | |------|---------| | @@ | Dấu phân cách đánh dấu điểm bắt đầu của một hunk | | -3,7 | Trong tệp gốc, hunk này bắt đầu ở dòng 3 và trải dài 7 dòng | | +3,8 | Trong tệp mới, hunk này bắt đầu ở dòng 3 và trải dài 8 dòng | | @@ | Dấu phân cách kết thúc |

Dòng ngữ cảnh ngay sau tiêu đề (thường là tên hàm hoặc một chú thích gần đó) giúp bạn xác định phần nào của tệp chứa thay đổi.

Các dòng trong một hunk

Mỗi dòng bên trong một hunk được thêm tiền tố là một ký tự duy nhất:

 context line (unchanged)
-added line    (present in new file, absent in old)
+added line    (present in new file, absent in old)
  • Các dòng ngữ cảnh bắt đầu bằng một khoảng trắng. Chúng giống hệt nhau trong cả hai phiên bản và cung cấp các điểm tham chiếu.
  • Các dòng bị xóa bắt đầu bằng dấu trừ (-). Chúng tồn tại trong tệp cũ nhưng đã bị xóa.
  • Các dòng được thêm bắt đầu bằng dấu cộng (+). Chúng mới xuất hiện trong tệp đã thay đổi.

Ví dụ thực tế

Dưới đây là một diff hiển thị một hàm đang được sửa đổi:

@@ -5,7 +5,9 @@
 def greet(name):
-    print("Hello, " + name)
-    print("Welcome!")
+    message = f"Hello, {name}!"
+    print(message)
+    print("We are glad to see you.")
+
     if name == "admin":
         print("You have admin privileges.")

Cách đọc diff này:

  • Phiên bản cũ in "Hello, " cộng với tên, sau đó in "Welcome!".
  • Phiên bản mới xây dựng một chuỗi thông báo được định dạng, in nó ra, thêm một dòng chào mừng bổ sung và giữ nguyên phần kiểm tra quyền admin.
  • Hai dòng đã bị xóa (các dòng -), ba dòng đã được thêm (các dòng +) và dòng + trống giữ lại một dòng trống để dễ đọc.

Tệp Patch: Các diff bạn có thể áp dụng

Tệp patch chỉ đơn giản là một diff được lưu vào một tệp — theo quy ước với phần mở rộng .patch hoặc .diff. Tệp patch đóng vai trò là một cách di động để chia sẻ các thay đổi mà không cần chia sẻ toàn bộ mã nguồn.

Tạo một patch

Sử dụng Git, tạo một patch từ commit gần nhất của bạn:

git format-patch HEAD~1

Hoặc tạo một patch từ các thay đổi chưa được commit:

git diff > my-changes.patch

Áp dụng một patch

Áp dụng một patch vào kho lưu trữ mục tiêu:

git apply my-changes.patch

Hoặc sử dụng lệnh patch cổ điển:

patch -p1 < my-changes.patch

Cờ -p1 loại bỏ thành phần thư mục đầu tiên khỏi đường dẫn tệp, điều này giải thích cho sự khác biệt về cấu trúc thư mục giữa người tạo patch và người áp dụng patch.

Các định dạng kết quả diff phổ biến

Ngoài unified diff, bạn có thể gặp các định dạng sau:

Normal Diff

Đầu ra mặc định của lệnh diff ban đầu. Các thay đổi được hiển thị dưới dạng các chỉ dẫn để thay đổi, thêm hoặc xóa dòng bằng cách sử dụng các lệnh như a (thêm vào), c (thay đổi) và d (xóa).

3c3
< Hello world
---
> Hello beautiful world

Context Diff

Một định dạng cũ hơn cung cấp ba dòng ngữ cảnh xung quanh mỗi thay đổi. Nó sử dụng dấu chấm than để chỉ ra các dòng đã thay đổi.

Side-by-Side Diff

Không phải là định dạng tệp đơn — thay vào đó, nó hiển thị hai cột cạnh nhau. Điều này phổ biến trong các công cụ diff đồ họa và các trình kiểm tra diff trực tuyến.

Đọc kết quả diff trong đánh giá mã nguồn

Khi xem xét một pull request, hãy tập trung vào các yếu tố sau:

  1. Các tiêu đề hunk: chúng cho bạn biết tệp và hàm nào bị ảnh hưởng.
  2. Tỷ lệ giữa các dòng được thêm và bị xóa: một số lượng lớn thay đổi trong các tệp quan trọng đáng được chú ý kỹ hơn.
  3. Các dòng ngữ cảnh: chúng cho bạn thấy logic xung quanh, giúp bạn đánh giá liệu thay đổi có đúng hay không.
  4. Các thay đổi chỉ về khoảng trắng: nhiều công cụ diff làm nổi bật những thay đổi này khác đi, vì chúng có thể làm rối mắt việc đánh giá.

Các phương pháp tốt nhất để diễn giải diff

  • Đọc diff từ trên xuống dưới, từng tệp một — điều này khớp với thứ tự mà các thay đổi được tạo ra.
  • Chú ý đến các dòng ngữ cảnh không đổi gần mã đã sửa đổi; chúng tiết lộ mối quan hệ cấu trúc giữa mã cũ và mã mới.
  • Sử dụng một công cụ hỗ trợ tô sáng cú pháp trong chế độ xem diff — màu sắc giúp phát hiện các mẫu dễ dàng hơn.
  • Khi xem xét các diff lớn, hãy bắt đầu với các tệp kiểm thử để hiểu hành vi mà tác giả dự định thay đổi.

Hiểu về kết quả diff là một kỹ năng nền tảng cho sự phát triển cộng tác. Khi bạn đã thoải mái đọc diff, bạn sẽ điều hướng việc đánh giá mã nguồn, xung đột hợp nhất và tệp patch một cách tự tin hơn nhiều.

Cách đọc kết quả diff: Hiểu về tệp patch và các thay đổi - CoolTool