Cấu hình Git Diff Driver tùy chỉnh: Xem nội dung file PDF, Word, SQLite và ảnh thay vì dữ liệu nhị phân

Git tutorial - IT technology blog
Git tutorial - IT technology blog

Tuần trước mình cần review lại lịch sử thay đổi của một file tài liệu Word trong dự án. Chạy git log -p contract.docx lên thì terminal hiện ra một đống ký tự binary vô nghĩa. Không biết phiên bản nào thêm điều khoản gì, ai sửa đoạn nào — không trace được gì cả.

Git rất mạnh với file text, nhưng với file nhị phân (PDF, Word, SQLite, ảnh…), mặc định nó chỉ nói Binary files differ rồi dừng lại. Vấn đề này giải quyết được bằng một tính năng ít người biết: Git Diff Driver.

Git Diff Driver là gì?

Git Diff Driver là cơ chế cho phép bạn chỉ định một command bên ngoài để xử lý việc diff thay vì dùng engine mặc định của Git. Khi Git gặp file có diff driver được cấu hình, nó gọi command đó — thường là một tool convert file nhị phân sang text — rồi diff phần text output như bình thường.

Quy trình hoạt động như sau:

  1. Git phát hiện file report.pdf thay đổi
  2. Git đọc cấu hình: file *.pdf dùng diff driver tên pdf
  3. Git gọi driver pdf, chạy lệnh pdftotext để convert file thành plain text
  4. Git diff hai phiên bản text output đó như với file thông thường

Kết quả: thay vì thấy Binary files differ, bạn thấy đúng đoạn văn bản nào thêm, xóa, sửa.

Thiết lập chỉ gồm hai bước:

  1. Khai báo driver trong ~/.gitconfig (hoặc .git/config của repo)
  2. Gán driver đó cho loại file trong .gitattributes

Thực hành: Cấu hình từng loại file

1. File PDF — dùng pdftotext

Cài pdftotext từ gói poppler-utils:

# Ubuntu/Debian
sudo apt install poppler-utils

# macOS
brew install poppler

Thêm vào ~/.gitconfig:

[diff "pdf"]
    textconv = pdftotext -layout -enc UTF-8 - -

Rồi khai báo trong .gitattributes của repo:

*.pdf diff=pdf

Test thử:

git diff HEAD~1 HEAD -- report.pdf

Thay vì Binary files differ, terminal giờ hiện đúng đoạn text nào thêm hay bị xóa trong PDF. Mình xài cái này nhiều nhất khi review hợp đồng hay spec kỹ thuật — xem được ngay trong terminal mà không cần mở Acrobat để so sánh từng phiên bản.

2. File Word/DOCX — dùng pandoc

Có hai lựa chọn. Mình thích pandoc hơn vì nó xử lý format tốt hơn:

# Ubuntu/Debian
sudo apt install pandoc

# macOS
brew install pandoc

Khai báo driver trong ~/.gitconfig:

[diff "docx"]
    textconv = pandoc --to=plain

Nếu chỉ muốn extract text đơn giản hơn, dùng docx2txt:

pip install docx2txt
[diff "docx"]
    textconv = python3 -c "import docx2txt,sys; print(docx2txt.process(sys.argv[1]))"

Thêm vào .gitattributes:

*.docx diff=docx
*.doc  diff=docx

3. File SQLite — dump ra SQL để diff

SQLite database là binary, nhưng nội dung bên trong hoàn toàn có thể đọc được nếu dump ra SQL. Viết một shell script nhỏ, lưu vào /usr/local/bin/git-sqlite-diff:

#!/bin/bash
sqlite3 -readonly "$1" .dump
chmod +x /usr/local/bin/git-sqlite-diff

Thêm vào ~/.gitconfig:

[diff "sqlite3"]
    textconv = git-sqlite-diff

Gán cho các file database trong .gitattributes:

*.db      diff=sqlite3
*.sqlite  diff=sqlite3
*.sqlite3 diff=sqlite3

Khi diff, Git hiện ra SQL INSERT/CREATE TABLE thay đổi — review được ngay mà không cần mở database client. Một lưu ý thực tế: database vài chục MB dump ra .dump có thể ra hàng triệu dòng INSERT. Trong trường hợp đó, chỉ dump schema thôi là đủ để biết cấu trúc thay đổi chỗ nào:

#!/bin/bash
sqlite3 -readonly "$1" .schema

4. Hình ảnh — diff metadata bằng exiftool

Với ảnh, không thể diff pixel, nhưng có thể diff metadata: kích thước, ngày tạo, camera settings, GPS… Cài exiftool:

# Ubuntu/Debian
sudo apt install libimage-exiftool-perl

# macOS
brew install exiftool

Thêm vào ~/.gitconfig:

[diff "image"]
    textconv = exiftool

Rồi khai báo trong .gitattributes:

*.png  diff=image
*.jpg  diff=image
*.jpeg diff=image
*.gif  diff=image
*.webp diff=image

Muốn xem thêm thông tin về kích thước pixel và color profile? Dùng identify từ ImageMagick:

sudo apt install imagemagick

# Trong ~/.gitconfig:
[diff "image"]
    textconv = identify -verbose

Cấu hình toàn cục vs per-repo

Có hai nơi để đặt cấu hình driver:

  • ~/.gitconfig: áp dụng cho tất cả repo trên máy — thích hợp cho PDF, DOCX, ảnh vì các tool này dùng được ở mọi project
  • .git/config: chỉ áp dụng cho repo hiện tại — thích hợp khi driver đặc thù cho project đó

File .gitattributes nên commit vào repo để cả team cùng được hưởng lợi. Driver definition thì mỗi người cài tool và config trên máy mình.

File .gitattributes đầy đủ cho một project điển hình:

# Binary file diff drivers
*.pdf     diff=pdf
*.docx    diff=docx
*.doc     diff=docx
*.db      diff=sqlite3
*.sqlite  diff=sqlite3
*.sqlite3 diff=sqlite3
*.png     diff=image
*.jpg     diff=image
*.jpeg    diff=image
*.gif     diff=image
*.webp    diff=image

Dùng được với git log và git show

Diff driver không chỉ hoạt động với git diff mà còn với các lệnh khác:

# Xem thay đổi trong lịch sử
git log -p -- report.pdf

# So sánh hai branch
git diff main..feature-branch -- database.db

# Xem nội dung file ở commit cụ thể
git show abc1234:report.pdf | pdftotext - -

Một điểm quan trọng: driver chỉ chạy khi hiển thị diff, không ảnh hưởng đến cách Git lưu trữ file. File vẫn được lưu dạng binary trong object store — hoàn toàn an toàn.

Mình từng mất code quan trọng vì force push nhầm branch — từ đó luôn xem kỹ lịch sử trước khi làm bất cứ thao tác gì với branch chung. Chính vì vậy, đọc được diff của file binary không chỉ là tiện — nó giúp bạn biết chính xác mình đang push gì lên, không phải đoán mò qua tên commit.

Xử lý lỗi thường gặp

  • Driver không chạy: Kiểm tra tên driver trong gitconfig có khớp với tên trong .gitattributes không (phân biệt hoa/thường). Ví dụ diff=pdf phải khớp với [diff "pdf"]
  • Tool không tìm thấy: Git cần tool nằm trong $PATH. Thử chạy lệnh trực tiếp trên terminal trước để xác nhận
  • Output quá nhiều với SQLite lớn: Thay .dump bằng .schema để chỉ hiện cấu trúc bảng
  • PDF tiếng Việt bị lỗi encoding: Thêm -enc UTF-8 vào lệnh pdftotext là xong

Kết luận

Git mặc định coi file binary như hộp đen — biết nó thay đổi, nhưng không nói được cái gì thay đổi. Diff Driver phá vỡ giới hạn đó: PDF, Word, SQLite, ảnh — tất cả đều review được như file code bình thường.

Setup một lần, dùng mãi. Và nếu làm việc trong team, hãy commit file .gitattributes vào repo ngay — chỉ cần mỗi người cài thêm các tool cần thiết trên máy của mình là cả team cùng được hưởng lợi.

Share: