Xử lý triệt để lỗi LF/CRLF và quản lý file nhị phân bằng .gitattributes

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

Tại sao dự án của bạn cần .gitattributes?

Lỗi “modified” ảo ma khi làm việc giữa Windows và Mac là nỗi ám ảnh của nhiều team dev. Bạn vừa git pull code mới về, chưa kịp gõ dòng nào mà Git đã báo hàng chục file bị thay đổi. Mở git diff lên, bạn thấy toàn bộ nội dung file bị thay thế bởi chính nó, chỉ khác mỗi ký tự xuống dòng ẩn bên dưới.

Thủ phạm là sự khác biệt giữa LF (\n) trên Unix/macOS và CRLF (\r\n) trên Windows. Trước đây, nhiều người thường dùng git config --global core.autocrlf true. Tuy nhiên, cách này phụ thuộc vào ý thức cá nhân. Chỉ cần một thành viên quên cấu hình hoặc dùng tool GUI ghi đè, toàn bộ commit log sẽ trở nên hỗn loạn.

Tôi từng mất hơn 3 tiếng để debug một script shell (.sh) chạy trên Docker. Hóa ra một bạn dùng Windows đã vô tình đổi nó sang CRLF. Kết quả là bash script trên Linux báo lỗi ^M: bad interpreter và không thể thực thi. Để tránh những lỗi ngớ ngẩn này, .gitattributes là giải pháp bắt buộc cho mọi dự án chuyên nghiệp.

File này giúp ép buộc quy tắc Git ngay tại cấp độ repository. Bất kể đồng nghiệp của bạn dùng hệ điều hành nào, Git sẽ luôn xử lý file theo đúng chuẩn chung của cả team.

Triển khai .gitattributes trong 30 giây

Bạn chỉ cần tạo một file tên là .gitattributes tại thư mục gốc của dự án. Hãy coi nó như file .gitignore nhưng dành cho định dạng file. Sau khi tạo xong, hãy commit nó lên repo để mọi thành viên đều nhận được cấu hình này.

# Tạo file nhanh từ terminal
touch .gitattributes

Cấu trúc file tuân theo quy tắc: [mẫu file] [thuộc tính]. Git sẽ ưu tiên đọc các quy tắc từ trên xuống dưới. Các khai báo phía sau sẽ ghi đè quy tắc phía trước nếu có trùng lặp.

Bộ quy tắc “vàng” cho dự án thực tế

Dưới đây là cấu hình tôi thường áp dụng để đảm bảo dự án chạy mượt mà trên mọi môi trường.

1. Xử lý xuống dòng tự động (End-of-Line)

Đầu tiên, hãy thiết lập quy tắc chung cho toàn bộ file văn bản. Dòng dưới đây giúp Git tự động nhận diện file text. Nó sẽ tự convert sang LF khi lưu vào database Git. Khi checkout ra máy local, Git sẽ tự điều chỉnh theo hệ điều hành của người dùng.

# Quy tắc mặc định cho mọi file văn bản
* text=auto

Với các file đặc thù cần chạy trên server Linux hoặc file thực thi của Windows, bạn nên chỉ định rõ:

# Ép dùng LF cho script chạy trên Unix/Linux/Docker
*.sh text eol=lf
*.py text eol=lf
*.js text eol=lf

# Ép dùng CRLF cho các file batch của Windows
*.bat text eol=crlf
*.cmd text eol=crlf

2. Bảo vệ file nhị phân (Binary Files)

Git đôi khi cố gắng “sửa” lỗi xuống dòng cho cả ảnh hoặc file PDF. Việc này có thể làm hỏng file (corrupt) hoàn toàn. Tôi từng gặp trường hợp file .png tăng dung lượng thêm vài KB và không thể mở được do Git tự chèn thêm ký tự xuống dòng.

Hãy dùng thuộc tính binary để báo cho Git biết: “Đừng đụng vào nội dung bên trong”.

# Đánh dấu các file ảnh là nhị phân
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary

# Các file tài liệu, font và file thực thi
*.pdf binary
*.woff binary
*.ttf binary
*.exe binary
*.dll binary

3. Mẹo nhỏ cho file CSV và Excel

Nếu bạn làm việc với dữ liệu CSV, việc ép định dạng CRLF sẽ giúp các bạn dùng Excel trên Windows mở file mà không bị lỗi nhảy cột hoặc lỗi font.

# Đảm bảo CSV luôn thân thiện với Excel trên Windows
*.csv text eol=crlf

Cách áp dụng cấu hình cho dự án cũ

Sau khi tạo .gitattributes, các file đã commit từ trước vẫn giữ nguyên định dạng cũ. Bạn cần thực hiện thao tác “làm sạch” (renormalization) để áp dụng quy tắc mới cho toàn bộ repo:

# 1. Xóa index của Git (yên tâm, lệnh này không xóa file thật)
git rm --cached -r .

# 2. Thêm lại toàn bộ file để Git áp dụng quy tắc mới
git add .

# 3. Commit và đẩy lên server
git commit -m "Chỉnh sửa định dạng xuống dòng theo .gitattributes"

Để kiểm tra một file đang nhận thuộc tính gì, hãy dùng lệnh git check-attr. Đây là cách nhanh nhất để debug khi có file nào đó “cứng đầu” không tuân thủ quy tắc.

# Kiểm tra file script.sh
git check-attr -a script.sh

# Kết quả mong đợi:
# script.sh: text: set
# script.sh: eol: lf

Một lưu ý quan trọng: hãy test kỹ trên một branch riêng. Nhờ một đồng nghiệp dùng hệ điều hành khác pull về chạy thử trước khi merge vào main. Nếu không có file nào bị báo “modified” vô lý, bạn đã thành công.

Làm chủ .gitattributes giúp lịch sử commit của team sạch sẽ hơn. Bạn sẽ không còn phải tốn thời gian cho những pull request chứa hàng nghìn dòng thay đổi chỉ vì dấu xuống dòng. Hãy thiết lập nó ngay hôm nay để bảo vệ dự án của bạn.

Share: