Cách tôi thiết lập Git identity
(benji.dog)- Trong môi trường đặt cả kho lưu trữ cá nhân và công việc dưới
~/workspace, việc tách Git identity theo remote URL chính xác hơn là theo vị trí thư mục includeIfcủa Git có thể tải cấu hình theo từng đường dẫn bằnggitdir, nhưng nếu các kho của nhiều tài khoản bị trộn trong cùng một thư mục làm việc thì cách phân nhánh theo đường dẫn sẽ chạm giới hạn- Dùng điều kiện
hasconfig:remote.*.url:thì có thể include các tệp cấu hình riêng theo mẫu remote URL như GitHub, GitLab, SourceHut, hoặc một tổ chức GitHub cụ thể - Khóa SSH cần được quản lý riêng trong
~/.ssh/configbằngHost,Hostname,User,IdentityFile; và để dùng khóa theo từng tổ chức ngay cả trên cùnggithub.comthì cần bí danh Host - Nếu cấu hình thêm
url.<base>.insteadOf, bạn vẫn có thể dùnggit@github.com:orgname/projectnhư thường lệ, nhưng bên trong nó sẽ được thay thànhgh-work:orgnameđể đi qua đúng cấu hình SSH
Tách cấu hình Git theo remote URL
- Ví dụ
includeIftruyền thống sẽ include các tệp cấu hình khác nhau theo đường dẫn thư mục cục bộ nhưgitdir:~/code/**,gitdir:~/work/**- Dưới
~/codecó thể tải~/.config/git/personal, dưới~/workcó thể tải~/.config/git/work - Các tệp được include thường chứa Git identity và khóa ký như
user.name,user.email,user.signingkey
- Dưới
- Nếu đặt toàn bộ mã nguồn dưới
~/workspace, thì các kho cá nhân,work-1,work-2có thể bị trộn trong cùng một cấu trúc đường dẫn, khiến điều kiện theo đường dẫn khó phân tách như mong muốn - Dùng
hasconfig:remote.*.url:của Git thì chỉ khi kho hiện tại có remote URL nhất định mới include tệp cấu hình tương ứng- Nếu khớp
git@github.com:*/**thì include~/.config/git/config-gh - Nếu khớp
git@github.com:orgname/**thì include~/.config/git/config-gh-org - Nếu khớp
git@gitlab.com:*/**thì include~/.config/git/config-gl - Nếu khớp
git@git.sr.ht:*/**thì include~/.config/git/config-srht
- Nếu khớp
- Git sẽ include cấu hình khớp sau cùng, nên thứ tự điều kiện rất quan trọng
- Điều kiện
github.com:orgname/**phải nằm dưới điều kiệngithub.com:*/**chung, để cấu hình riêng cho tổ chức không bị cấu hình GitHub chung ghi đè
- Điều kiện
- Kết quả là các kho có remote
github.com:orgname/**sẽ dùngconfig-gh-org, còn các kho GitHub khác sẽ dùng cấu hình GitHub thông thường
Khớp thông tin kết nối theo từng tổ chức bằng khóa SSH và insteadOf
- Tách biệt với Git identity, để
pullvàpushtới remote thì cần cấu hình khóa SSH- Trong
~/.ssh/config, có thể chỉ địnhIdentityFilenhư~/.ssh/gitlab.id_ed25519chogitlab.com - Và
~/.ssh/github.id_ed25519chogithub.com
- Trong
- Tùy cấu hình
ssh-agent, có thể nên thêmIdentitiesOnly yesbên dướiIdentityFilecủa từngHost - Nếu muốn dùng khóa khác nhau theo từng tổ chức trên cùng
Hostnamelàgithub.com, thì cần đặtHostkhác nhau- Cấu hình sẽ có dạng
Host gh-work,Hostname github.com,User git,IdentityFile ~/.ssh/work.id_ed25519
- Cấu hình sẽ có dạng
- Nếu dùng
url "gh-work:orgname"vàinsteadOf = git@github.com:orgnametrong cấu hình Git, thì URL Git sẽ được thay tự động- Người dùng vẫn nhập như
git clone git@github.com:orgname/project - Git sẽ đổi phần
github.com:orgnamethànhgh-work:orgnameđể sử dụng cấu hìnhgh-worktrong~/.ssh/config
- Người dùng vẫn nhập như
- Cách này là một mẹo tham khảo từ SSH and multiple Git credentials, và các bài viết được tham khảo thêm gồm:
1 bình luận
Các ý kiến trên Hacker News
Thay vì dùng
insteadOf, hãy clone kho lưu trữ dưới dạnggh-work:org/repo, rồi trong cấu hình Git đặtincludeIf "hasconfig:remote.*.url:gh-work:**/**"Làm như vậy, các kho lưu trữ được clone bằng danh tính SSH được định nghĩa dưới
gh-worksẽ tự động lấy cấu hìnhgh-work.inc, trong đó có danh tính Git và khóa ký cùng các thiết lập SSHRốt cuộc, tên
gh-worktrở thành tiêu chí phân biệt danh tính SSH và danh tính Git, nên dễ hiểu hơnincludeIfphân biệt chữ hoa/thường, và về mức ưu tiên thì cấu hình cuối cùng sẽ thắngĐể kiểm tra xem nó có hoạt động đúng không, chỉ cần chạy
git remote get-url originvàgit config --get user.emailTôi cho rằng cách tốt hơn là đặt alias theo từng danh tính trong
.gitconfigởHOME, rồi ngay sau khi khởi tạo hoặc clone kho lưu trữ thì chạygit config-companyhoặcgit config-personalBật
user.useConfigOnly = true, rồi trong alias đặtuser.email,user.name,core.sshCommandcủa kho lưu trữ cục bộ tương ứng với khóa SSH cá nhân/công ty là đượcƯu điểm của cách trong bài có vẻ là nếu clone từ tổ chức thì nó cứ thế hoạt động
Trước đây ở một startup, có một người mỗi ngày đổi danh tính thành một cái tên vu vơ kiểu truyện cổ tích
Commit thứ Hai là Mr. Bunnymann, commit thứ Ba là Doctor Funtime, kiểu vậy, nên khi làm forensics cho hệ thống quản lý phiên bản thì rất bất tiện
Nếu nhìn rộng lượng, có thể người đó muốn nhắc rằng ai cũng có thể điền bất cứ giá trị nào vào cấu hình danh tính, nên không nên quá tin vào giá trị đó
Dù vậy, biết ai đã làm vẫn hữu ích khi cần hỏi chi tiết hoặc dự đoán phong cách và chuyên môn
Nếu yêu cầu commit có chữ ký GPG và đăng ký các danh tính GPG được phép, có thể nhận diện tác giả thực sự bằng chữ ký thay vì metadata tác giả/committer
Tất nhiên “đơn giản” và chữ ký GPG không phải lúc nào cũng đi đôi với nhau
Nếu không thể tin rằng nhân viên sẽ nhận diện đúng commit của chính họ, thì tôi nghĩ nên sa thải họ
Không cần động đến
~/.ssh/config; chỉ cần đặtcore.sshCommand = /usr/bin/ssh -o IdentitiesOnly=yes -i ~/.ssh/IdentityFile2 -atrong~/.gitconfighoặc~/.config/git/personalnhư trong bài là đượcNhư vậy submodule cũng dễ xử lý hơn mà không cần
insteadOfTôi đã dùng
includeIftheo thư mục từ lâu rồi (https://www.bobek.cz/til/git-identities/), nhưnghasconfig:remotethật sự gọn gàngNó hoạt động cả khi clone kho lưu trữ
includeIfkhá tốtHiện tôi để phần phức tạp của SSH trong
~/.ssh, rồi tạo một include cho mỗi khách hàng/dự án/danh tínhVới những nơi không có hostname riêng như GitHub, tôi đặt alias host kiểu
customer-github, rồi cấu hình nhưHostName github.com,IdentityFile ~/.ssh/customer_rsa,User gitSau đó chỉ cần dùng alias đó trong
git clonelà xongTôi cũng gặp vấn đề tương tự, và giờ coi như đã có lời giải
Nếu dùng NixOS và home-manager trên Linux và Mac thì cấu hình này trở nên đơn giản
Chỉ cần đặt
condition = "hasconfig:remote.*.url:git@github.com:/**"và cấu hìnhuser.emailtrongprograms.git.includesTham khảo: https://nix-community.github.io/home-manager/options.xhtml#opt-programs.git.includes
.gitconfigĐiều kiện và cấu hình giống như trong bài, nhưng còn thêm bước build/template và việc học một ngôn ngữ lập trình mới với cú pháp khác thường
Tôi vốn đã tách cấu hình công việc và cá nhân bằng
includeIf: "gitdir", nhưnghasconfig:remotelà một tính năng hoàn toàn thay đổi cuộc chơiVới consultant, tôi luôn khuyên mạnh mẽ rằng nên dùng máy riêng cho công việc, hoặc ít nhất là người dùng OS riêng
Dùng máy cá nhân cho công việc có nguy cơ khiến bạn gặp rắc rối lớn
Có trường hợp ở công ty ưu tiên làm việc từ xa, bạn tự chuẩn bị laptop và cứ 2–3 năm lại được cấp tiền mua máy mới, nhưng đó vẫn là laptop cá nhân; cũng có thể là contractor tạm thời
Cần giải thích cụ thể hơn trong tình huống nào và vì sao nó thành vấn đề
Rủi ro là có thật, nhưng nếu không liệt kê được thì nó gần với việc gieo rắc FUD hơn là giáo dục
Đây là công cụ tôi tạo để dễ đổi danh tính Git theo từng dự án: https://github.com/cquintana92/git-switch-user
Sau khi thiết lập danh tính, chạy
$ git su Personalhoặc$ git su Workthì email, tên, khóa SSH, và tùy chọn cả khóa PGP sẽ được đặt vào.git/configcủa kho lưu trữNó đã tiết kiệm cho tôi rất nhiều thời gian
Công cụ này đã 12 năm tuổi nhưng vẫn đang được bảo trì tích cực