11 điểm bởi GN⁺ 4 giờ trước | 3 bình luận | Chia sẻ qua WhatsApp
  • Quy tắc bỏ qua tệp trong Git được chia thành ba cấp độ theo phạm vi chia sẻ: .gitignore, .git/info/exclude, và ~/.config/git/ignore
  • .gitignore được commit cùng với mã nguồn của kho lưu trữ, nên đây là nơi đặt quy tắc dùng chung mà cả nhóm hoặc dự án cần áp dụng
  • Các mục như tệp cá nhân hoặc tệp phục vụ công việc cục bộ, vốn cần trong kho lưu trữ nhưng khó đưa thành quy tắc chung cho cả nhóm, phù hợp hơn khi đặt trong .git/info/exclude
  • Những tệp cần được loại trừ lặp đi lặp lại ở mọi kho lưu trữ, như .DS_Store trên macOS, có thể được đưa vào ~/.config/git/ignore, tức tệp ignore toàn cục của máy
  • git check-ignore -v <tên_tệp> hữu ích khi cần lần theo quy tắc nào đang khiến một tệp bị bỏ qua; nếu không có quy tắc khớp thì sẽ không có đầu ra

Vị trí áp dụng quy tắc ignore trong Git

  • Git có thể xử lý quy tắc bỏ qua tệp ở ba vị trí
    • .gitignore
    • .git/info/exclude
    • ~/.config/git/ignore

.gitignore: quy tắc dùng chung được commit vào kho lưu trữ

  • .gitignore là tệp thông dụng để ghi tên các tệp cần bỏ qua
  • Nó được check in vào Git cùng với phần còn lại của mã nguồn
  • Các tệp khớp với quy tắc trong .gitignore sẽ không được git xem xét khi chạy lệnh

.git/info/exclude: quy tắc cá nhân theo từng kho lưu trữ

  • Tệp exclude nằm trong thư mục .git của mọi kho lưu trữ Git
  • Các thay đổi trong tệp này không được check in vào Git
  • Trong kho Git mới, tệp này thường chứa vài dòng chú thích
  • Nó phù hợp với các tệp bạn chỉ muốn bỏ qua trong riêng kho đó nhưng không muốn đưa vào .gitignore
    • Ví dụ: nếu bạn muốn không commit notes.txt, vốn chỉ cần cho quy trình làm việc cá nhân, mà cũng không muốn thêm nó vào .gitignore của dự án, hãy thêm notes.txt vào .git/info/exclude

~/.config/git/ignore: quy tắc toàn cục cho máy

  • Tệp ignore toàn cục nằm tại ~/.config/git/ignore trong thư mục home
  • Những tên tệp thêm vào đây sẽ bị bỏ qua toàn cục ở cấp máy
  • Nó không được check in vào Git và không gắn với kho lưu trữ cụ thể nào
  • Đây là nơi phù hợp để đặt các tệp bạn muốn bỏ qua trong mọi kho Git trên máy tính
    • Ví dụ: trên macOS, việc thêm .DS_Store vào đây là phù hợp

Thay đổi đường dẫn tệp ignore toàn cục

  • Có thể chỉ định tệp khác làm tệp ignore toàn cục
  • Để dùng .gitignore_global làm tệp Git ignore toàn cục, chạy lệnh sau
git config --global core.excludesFile ~/.gitignore_global
  • Để quay lại thiết lập mặc định, chạy lệnh sau
git config --global --unset core.excludesFile

Kiểm tra quy tắc nào đang bỏ qua một tệp

  • Có thể dùng git check-ignore -v <tên_tệp> để kiểm tra một tệp cụ thể đang bị bỏ qua bởi quy tắc nào
  • Để kiểm tra .DS_Store đang bị bỏ qua như thế nào, chạy lệnh sau bên trong kho Git
git check-ignore -v .DS_Store
  • Nếu .gitignore của kho lưu trữ đang bỏ qua .DS_Store, ví dụ đầu ra sẽ như sau
$ git check-ignore -v .DS_Store
.gitignore:1:.DS_Store	.DS_Store
  • Nếu .git/info/exclude của kho lưu trữ đang bỏ qua .DS_Store, ví dụ đầu ra sẽ như sau
$ git check-ignore -v .DS_Store
.git/info/exclude:7:.DS_Store	.DS_Store
  • Nếu tệp ~/.config/git/ignore toàn cục đang bỏ qua .DS_Store, ví dụ đầu ra sẽ như sau
$ git check-ignore -v .DS_Store
/Users/nelson/.config/git/ignore:2:.DS_Store	.DS_Store
  • Nếu tệp ignore toàn cục tùy chỉnh .gitignore_global đang bỏ qua .DS_Store, ví dụ đầu ra sẽ như sau
$ git check-ignore -v .DS_Store
/Users/nelson/.gitignore_global:1:.DS_Store	.DS_Store
  • Nếu không có quy tắc nào bỏ qua một tệp cụ thể, lệnh git check-ignore -v sẽ không in ra gì

3 bình luận

 

Có lẽ cũng hữu ích nếu đưa những thứ như đặc tả công việc hoặc tệp plan.md vào .git/info/exclude.

 

Thì ra còn có thể thiết lập ở thư mục gốc nữa haha

 
Ý kiến Hacker News
  • Bài viết thú vị, nhưng lại thiếu tính năng gần như bỏ qua mà tôi thích nhất trong Git là .gitattributes
    Với file này, bạn có thể chỉ định để Git “bỏ qua” phần khác biệt của một số tệp nhất định. Ví dụ, trong dự án Node, package-lock.json gần như chỉ là nhiễu nếu nhìn từ góc độ Git. Nó chỉ hiện ra những khác biệt khổng lồ chứa phiên bản cụ thể của thư viện, còn thông tin phiên bản thực sự mà con người dễ đọc thì đã có riêng trong package.json
    Nếu thêm một dòng package-lock.json -diff vào .gitattributes ở thư mục gốc của dự án, tệp đó vẫn được stage/commit bình thường nhưng git diff sẽ không còn hiện những thay đổi khổng lồ vô nghĩa nữa

    • package-lock.json không nên bị xem là nhiễu. Nếu không định cập nhật có chủ ý thì bạn không nên thay đổi nó, nếu không sẽ tự dưng phơi bày trước rủi ro chuỗi cung ứng
      Nếu thay đổi trong package-lock.json thường xuyên xuất hiện ngoài dự kiến thì chắc chắn là đang làm gì đó sai
    • package-lock.json cho thấy toàn bộ phụ thuộc bắc cầu, còn package.json chỉ cho thấy phụ thuộc trực tiếp. Vì vậy nói cái sau mới là “phiên bản thật mà con người đọc được” là không đúng
      Hai file này phục vụ mục đích khác nhau, và nói rằng luôn có thể bỏ qua diff của file lock là điều nguy hiểm
    • Nếu đứng ở góc độ nâng cấp dependency và truy vết nguyên nhân bug, tôi sẽ rất bực nếu git diff không hiển thị thay đổi trong file lock
      Tôi hiểu vì sao nó trông giống như nhiễu ở cấp dòng, nhưng lúc cần thì nó thật sự rất cần thiết
  • Thiết lập loại trừ toàn cục/theo người dùng là tính năng nên được biết đến rộng rãi hơn. Tôi thường nhận các thay đổi muốn thêm file liên quan đến IDE/OS/AI vào .gitignore của mọi dự án, nhưng khi giải thích rằng đưa chúng vào cấu hình chuẩn thì sẽ bị bỏ qua ở mọi nơi, không cần đụng vào từng dự án, và cũng tránh nguy cơ lỡ commit ở những dự án chưa cập nhật .gitignore, thì đa số đều rất thích
    Nguyên tắc cá nhân của tôi là .gitignore trong repository chỉ nên dùng cho các mục riêng của repository như build artifact hay thư mục dependency, còn phần lớn công cụ của người dùng nên nằm trong cấu hình riêng của từng người

    • Việc phải thường xuyên nhắc mọi người về cấu hình .gitignore toàn cục chính là hệ quả tự nhiên của nguyên tắc cho rằng .gitignore trong repo chỉ nên dùng cho các mục riêng của repo
      Nếu muốn tốn ít thời gian của mọi người hơn thì cứ cho các file đó vào .gitignore của mọi dự án vẫn tốt hơn
    • Tôi vẫn luôn thêm những file đó vào .gitignore của dự án để người thiếu hiểu biết không vô tình thêm chúng vào project
      Đằng nào cuối cùng cũng sẽ phải xóa chúng khỏi Git, và người đó sẽ gặp phiền toái, nên tôi chặn trước như một sự tử tế. Có lẽ từ nay tôi sẽ bớt tử tế hơn
    • Tôi thích dùng gitignore hơn vì nó vẫn tồn tại ngay cả khi rebuild development container
      Nếu buộc phải tránh gitignore thì vẫn có thể khôi phục/giữ lại cấu hình bằng script tạo môi trường hoặc volume, nhưng như vậy sẽ cần thêm script hoặc cấu hình mount devcontainer thay vì chỉ một dòng trong .gitignore
    • Việc cứ nhìn cùng một hành vi sai lặp đi lặp lại, nhưng lại đặt ra quy tắc cứng nhắc cấm rõ ràng cách dễ nhất để sửa nó, chẳng phải là mâu thuẫn sao
  • Với cấu hình Git toàn cục và file ignore, tôi nghĩ nên đặt trong ~/.config/git/ignore~/.config/git/config thay vì tạo ~/.gitignore_global rồi sửa cấu hình
    Nếu tận dụng ~/.config/ cho nhiều mục đích thì số lượng dotfile ở cấp thư mục gốc sẽ giảm đi đáng kể
    Lý do Git exclude ít được dùng hơn là vì nó không được commit vào repository, nên mỗi lần muốn dùng lại phải tạo lại. Không phải là nó tệ, chỉ là đó là lý do nó ít phổ biến hơn

    • Thêm nữa, nếu quản lý phiên bản thư mục ~/.config thì về sau sẽ dễ chỉnh sửa và chia sẻ hơn
    • Bạn cũng có thể dùng ~/.cvsignore cho các công cụ khác dùng cùng loại file đó
  • Không nhớ đã học ở đâu, nhưng tôi đã thêm attic vào global Git ignore
    Nhờ vậy tôi có thể tạo một thư mục attic trong bất kỳ dự án nào để chứa đủ thứ linh tinh tuyệt đối không nên commit. Đến giờ tôi vẫn chưa thấy repository nào thực sự kiểm tra sự tồn tại của thư mục như vậy

    • Cũng có thể làm theo hướng gần như ngược lại, nhưng phải làm riêng từng trường hợp
      Nếu có một thư mục như attic thì bạn có thể tạo attic/.gitignore và ghi /**, khi đó thư mục đó và mọi thứ bên trong sẽ bị bỏ qua, kể cả chính file ignore
      Thường thì tôi đặt tên thư mục theo đúng một ký tự U+1F4A9, nhưng HN không cho chèn nó vào bình luận
    • Trường hợp của tôi thì dùng aux
      Tôi chỉ đặt một .gitignore chứa đúng một dấu sao * trong đó để ẩn nó đi, thế là chính nó và mọi thứ bên trong đều bị bỏ qua
    • Tôi cũng làm vậy, chỉ là đặt tên là .local
    • Của tôi là scratch/
      Tới giờ vẫn chưa bị phản tác dụng
  • Về ignore theo người dùng, với macOS thì thêm .DS_Store vào đó là lý tưởng, nhưng mọi người dùng Mac trong dự án đều phải làm vậy
    Nếu có từ hai người trở lên thì có thể sẽ tốt hơn nếu không giao cho từng người tự xử lý

    • Tôi không chắc nó đến từ đâu, nhưng trên cả hai máy Mac của tôi (một chạy Ventura, một chạy Sequoia) đều có mục .DS_Store trong file ~/.gitignore_global, và trong cấu hình Git toàn cục cũng có thiết lập bỏ qua các mục trong file đó
      File này trên máy Mac mới có ngày tạo từ hai ngày trước khi tôi đặt mua máy, và tôi không nhớ là mình đã tự cấu hình, nên có vẻ nó đã có sẵn mặc định. Máy Mac cũ chắc cũng tương tự, và nhìn theo phiên bản macOS thì rất có thể đây đã là mặc định từ khá lâu rồi
      Vì vậy có lẽ thời phải thêm .DS_Store/ vào .gitignore giờ đã qua rồi
    • Cách nhìn về thiểu số và đa số ở đây khá lạ. Nếu một người dùng macOS làm việc trên mười dự án, thì nên thêm dòng đó vào cả mười dự án hay nên xử lý một lần ở phía người dùng đó?
  • Trời, sao tôi lại không biết chuyện này nhỉ? Tôi là lập trình viên phần mềm chuyên nghiệp 20 năm mà chỉ toàn dùng .gitignore
    Giờ mới nhận ra là tôi chưa từng tự hỏi liệu có cách nào tốt hơn việc làm rối .gitignore bằng đủ loại mục loại trừ chỉ liên quan đến riêng mình hay không. Tôi cứ thế chấp nhận thế giới như nó hiện ra trước mắt
    Hôm nay thế giới tốt đẹp hơn một chút rồi

  • Tôi dùng .git/info/exclude rất nhiều. Nó cực hợp cho script/Makefile chỉ dùng cục bộ, không cần cho cộng tác viên khác hoặc họ cũng không thể dùng được

    • Tôi tò mò không biết ví dụ nào về các script mà cộng tác viên khác không thể dùng được. Chẳng hạn như script cho quy trình làm việc với PR à?
    • Từ khá lâu rồi tôi đã dùng một hàm shell để đẩy toàn bộ file chưa được theo dõi đang hiện trong git status vào .git/info/exclude
      Thường tôi áp dụng nó sau khi addcommit những thứ thực sự muốn đưa vào repository
  • Tôi dùng file excludes như thế này để áp dụng cấu hình Git theo cấp dự án khác nhau cho một thư mục dự án chứa nhiều repository
    https://laszlo.nu/blog/project-level-git-config.html

  • Tôi có một số alias liên quan đang dùng
    assume = update-index --assume-unchanged
    unassume = update-index --no-assume-unchanged
    assumed = "!git ls-files -v | grep ^h | cut -c 3-"
    unassumeall = "!git assumed | xargs git update-index --no-assume-unchanged"
    assumeall = "!git st -s | awk {'print $2'} | xargs git assume"

  • Với các file đã được theo dõi sẵn thì còn có git update-index --[no]-skip-worktree
    Nó có thể hữu ích cho thử nghiệm cục bộ, nhưng không phải là tính năng Git hiển thị rõ ràng ở đâu đó nên dùng hơi phiền. Bạn phải nhớ là mình đã bật nó, và nếu quên thì có thể cản trở những thao tác khác như checkout