Nỗi ám ảnh mang tên Merge Conflict trong file dữ liệu
Nếu bạn từng thức trắng đêm chỉ để “soi” từng dấu ngoặc trong file package-lock.json bị conflict, bạn không đơn độc. Cảm giác nhìn thấy hàng nghìn dòng code lẫn lộn với những ký hiệu <<<<<<< HEAD thực sự là một cơn ác mộng về mặt thị giác.
Tôi nhớ rõ một dự án cũ khi cả team đang gồng mình chạy deadline. Tôi thực hiện merge branch feature vào develop và file composer.lock bị xung đột nặng. Thay vì dùng công cụ, tôi tự tin ngồi xóa dấu conflict bằng tay. Chỉ vì thiếu một dấu phẩy, tôi đã làm hỏng cấu hình lockfile khiến hệ thống CI/CD bị treo suốt 2 tiếng. Sự cố này không chỉ làm chậm tiến độ mà còn gây ức chế cho cả đội. Đó là lúc tôi nhận ra: Đừng bao giờ dùng sức người cho những việc mà Git có thể làm tốt hơn.
Mặc định, Git so sánh xung đột theo từng dòng (line-based). Cơ chế này hoạt động hoàn hảo với Java, Python hay C++. Tuy nhiên, với các file có cấu trúc chặt chẽ như JSON, XML hoặc Lockfiles, cách tiếp cận này thường phá vỡ cú pháp sau khi merge. Đây chính là lúc Git Merge Driver trở thành vị cứu tinh của bạn.
Git Merge Driver thực chất là gì?
Hãy coi Git Merge Driver như một “trọng tài” mà bạn thuê riêng để xử lý các vụ va chạm dữ liệu. Thay vì để Git tự quyết định và báo lỗi, bạn chỉ định một kịch bản (script) bên ngoài để tự động giải quyết xung đột dựa trên logic riêng.
Mỗi khi Git phát hiện file bị thay đổi ở cả hai phía, nó sẽ kiểm tra tệp .gitattributes. Nếu file đó được gán một Merge Driver riêng, Git sẽ lập tức gọi driver đó thay vì trình merge mặc định.
Cơ chế vận hành của một Merge Driver
Một driver chuyên nghiệp thường nhận 3 tham số đầu vào từ Git:
- %O: Phiên bản gốc (Ancestor) – điểm chung cuối cùng của hai nhánh.
- %A: Phiên bản hiện tại của bạn (Ours).
- %B: Phiên bản từ nhánh đang được merge vào (Theirs).
Driver sẽ đọc 3 tệp này, áp dụng logic để gộp dữ liệu và ghi kết quả cuối cùng đè vào tệp %A.
Hướng dẫn cấu hình Git Merge Driver chi tiết
Bước 1: Khai báo Driver trong cấu hình Git
Bạn nên cấu hình ở mức dự án (local) để đồng bộ hóa với mọi thành viên. Hãy mở terminal tại thư mục gốc và chạy các lệnh sau:
git config merge.json-merge.name "Trình tự động merge file JSON"
git config merge.json-merge.driver "python3 path/to/json_merge_script.py %O %A %B"
Trong đó, json-merge là tên định danh. Tham số driver chính là đường dẫn tới script xử lý mà chúng ta sẽ viết.
Bước 2: Phân quyền xử lý trong .gitattributes
Hãy tạo hoặc cập nhật file .gitattributes để “giao việc” cho driver mới:
*.json merge=json-merge
package-lock.json merge=json-merge
Dòng này ra lệnh cho Git: “Khi thấy file .json bị conflict, đừng hiện cảnh báo, hãy gọi ngay json-merge ra xử lý”.
Bước 3: Viết Script xử lý thông minh
Dưới đây là ví dụ script json_merge_script.py đơn giản bằng Python để gộp các key JSON:
import sys
import json
def merge_json(base_path, ours_path, theirs_path):
try:
with open(base_path) as f: base = json.load(f)
with open(ours_path) as f: ours = json.load(f)
with open(theirs_path) as f: theirs = json.load(f)
# Logic: Gộp key từ cả hai phía, ưu tiên thay đổi mới nhất
result = {**base, **ours, **theirs}
with open(ours_path, 'w') as f:
json.dump(result, f, indent=2)
sys.exit(0) # Thành công
except Exception:
sys.exit(1) # Thất bại, để Git xử lý thủ công
if __name__ == "__main__":
merge_json(sys.argv[1], sys.argv[2], sys.argv[3])
Giải pháp “mì ăn liền” cho Lockfiles: Union Merge
Nếu bạn ngại viết script, Git cung cấp sẵn driver union. Driver này sẽ giữ lại dòng code của cả hai bên khi có xung đột. Cách này cực kỳ hiệu quả cho các file danh sách như .gitignore.
Để áp dụng nhanh cho lockfiles, hãy thêm vào .gitattributes:
package-lock.json merge=union
yarn.lock merge=union
Lưu ý: union có thể làm file lockfile bị sai lệch nhẹ. Bạn nên chạy npm install lại sau khi merge để đảm bảo tính toàn vẹn.
Sử dụng thư viện chuyên dụng (Khuyên dùng)
Đừng cố gắng tái phát minh bánh xe. Cộng đồng đã phát triển những công cụ cực mạnh như npm-merge-driver cho NodeJS.
npx npm-merge-driver install --global
Công cụ này tự động tối ưu hóa package-lock.json, đảm bảo file sau khi merge luôn hợp lệ và không gây lỗi cài đặt.
Những lưu ý “sống còn” khi dùng Merge Driver
Dựa trên kinh nghiệm thực tế, tôi có 3 lời khuyên dành cho bạn:
- Kiểm chứng lại kết quả: Dù driver thông minh đến đâu, hãy luôn chạy
npm testhoặc kiểm tra cú pháp bằngjsonlintsau khi merge. - Chia sẻ cấu hình team: Hãy commit file
.gitattributes. Với cấu hình trong.gitconfig, bạn nên viết một script setup tự động cho các thành viên mới. - Cẩn thận dữ liệu nhạy cảm: Tránh để script tự động ghi đè các thiết lập bảo mật quan trọng trong file cấu hình môi trường.
Tổng kết
Tùy chỉnh Git Merge Driver là khoản đầu tư nhỏ nhưng mang lại lợi nhuận lớn về năng suất. Nó giúp team loại bỏ những thao tác thủ công nhàm chán và giảm thiểu sai sót do con người. Nếu dự án của bạn có quá nhiều file JSON phức tạp, hãy thiết lập driver ngay hôm nay. Chúc bạn có những lần merge êm ái!

