วิธีตั้งค่า Git identity ของฉัน
(benji.dog)- ในสภาพแวดล้อมที่เก็บทั้ง repository ส่วนตัวและงานไว้ที่
~/workspaceการแยก Git identity โดยอิงจาก remote URL จะแม่นยำกว่าการอิงตำแหน่งโฟลเดอร์ includeIfของ Git สามารถโหลดการตั้งค่าตาม path ด้วยgitdirได้ แต่ถ้า repository ของหลายบัญชีปะปนกันอยู่ใน working directory เดียวกัน การแยกตาม path จะชนข้อจำกัด- หากใช้เงื่อนไข
hasconfig:remote.*.url:จะสามารถ include ไฟล์ตั้งค่าแยกตาม pattern ของ remote URL เช่น GitHub, GitLab, SourceHut หรือองค์กร GitHub เฉพาะได้ - ต้องจัดการ SSH key แยกต่างหากใน
~/.ssh/configด้วยHost,Hostname,User,IdentityFileและหากต้องการใช้ key แยกตามองค์กรแม้จะเป็นgithub.comเดียวกัน ก็จำเป็นต้องมี Host alias - เมื่อตั้งค่า
url.<base>.insteadOfร่วมด้วย จะยังใช้git@github.com:orgname/projectได้ตามปกติ แต่ภายในจะถูกแทนที่เป็นgh-work:orgnameเพื่อให้ไปใช้การตั้งค่า SSH ที่ถูกต้อง
แยกการตั้งค่า Git ตาม remote URL
- ตัวอย่าง
includeIfแบบเดิมจะ include ไฟล์ตั้งค่าต่างกันตาม path ของ local directory เช่นgitdir:~/code/**,gitdir:~/work/**- ใต้
~/codeสามารถโหลด~/.config/git/personalและใต้~/workสามารถโหลด~/.config/git/workได้ - ไฟล์ที่ถูก include มักมี Git identity และ signing key เช่น
user.name,user.email,user.signingkey
- ใต้
- หากวางโค้ดทั้งหมดไว้ใต้
~/workspacerepository ส่วนตัว,work-1,work-2อาจปะปนกันในโครงสร้าง path เดียวกัน ทำให้ยากที่จะแยกตามต้องการด้วยเงื่อนไขแบบ path เพียงอย่างเดียว - เมื่อใช้
hasconfig:remote.*.url:ของ Git จะสามารถ include ไฟล์ตั้งค่าได้เฉพาะเมื่อ repository ปัจจุบันมี remote URL ที่กำหนด- ถ้าตรงกับ
git@github.com:*/**ให้ใช้~/.config/git/config-gh - ถ้าตรงกับ
git@github.com:orgname/**ให้ใช้~/.config/git/config-gh-org - ถ้าตรงกับ
git@gitlab.com:*/**ให้ใช้~/.config/git/config-gl - ถ้าตรงกับ
git@git.sr.ht:*/**ให้ใช้~/.config/git/config-srht
- ถ้าตรงกับ
- Git จะ include การตั้งค่าที่ match เป็นลำดับสุดท้าย ดังนั้น ลำดับของเงื่อนไข จึงสำคัญ
- เงื่อนไข
github.com:orgname/**ต้องอยู่ถัดลงมาจากเงื่อนไขทั่วไปgithub.com:*/**เพื่อไม่ให้การตั้งค่าเฉพาะองค์กรถูกการตั้งค่า GitHub ทั่วไปเขียนทับ
- เงื่อนไข
- ผลลัพธ์คือ repository ที่มี remote
github.com:orgname/**จะใช้config-gh-orgส่วน repository GitHub อื่น ๆ จะใช้การตั้งค่า GitHub ทั่วไป
ปรับข้อมูลการเชื่อมต่อตามองค์กรด้วย SSH key และ insteadOf
- นอกเหนือจาก Git identity แล้ว หากต้องการ
pull·pushกับ remote จำเป็นต้องมี การตั้งค่า SSH key- สำหรับ
gitlab.comใน~/.ssh/configสามารถกำหนดIdentityFileเป็น~/.ssh/gitlab.id_ed25519 - สำหรับ
github.comสามารถกำหนดเป็น~/.ssh/github.id_ed25519ได้เช่นกัน
- สำหรับ
- ขึ้นอยู่กับการตั้งค่า
ssh-agentอาจควรเพิ่มIdentitiesOnly yesใต้IdentityFileของแต่ละHost - หากต้องการใช้ key ต่างกันตามองค์กรบน
github.comซึ่งเป็นHostnameเดียวกัน ต้องตั้งค่าHostให้แตกต่างกัน- รูปแบบการตั้งค่าคือ
Host gh-work,Hostname github.com,User git,IdentityFile ~/.ssh/work.id_ed25519
- รูปแบบการตั้งค่าคือ
- หากใช้
url "gh-work:orgname"กับinsteadOf = git@github.com:orgnameในการตั้งค่า Git จะสามารถแทนที่ Git URL ได้โดยอัตโนมัติ- ผู้ใช้ป้อนเหมือน
git clone git@github.com:orgname/project - Git จะเปลี่ยนส่วน
github.com:orgnameเป็นgh-work:orgnameแล้วใช้การตั้งค่าgh-workใน~/.ssh/config
- ผู้ใช้ป้อนเหมือน
- วิธีนี้เป็นทริกที่อ้างอิงจาก SSH and multiple Git credentials และบทความที่อ้างอิงร่วมกันมีดังนี้
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
แทนที่จะใช้
insteadOfให้โคลนรีโพซิทอรีเป็นgh-work:org/repoแล้วใส่includeIf "hasconfig:remote.*.url:gh-work:**/**"ไว้ในการตั้งค่า Gitวิธีนี้ทำให้รีโพซิทอรีที่โคลนด้วย SSH identity ที่กำหนดไว้ใต้
gh-workดึงการตั้งค่าgh-work.incมาใช้โดยอัตโนมัติ และในนั้นจะมี Git identity กับคีย์สำหรับเซ็นที่เหมือนกับการตั้งค่า SSHสุดท้ายชื่อ
gh-workจะกลายเป็นเกณฑ์ที่ใช้แยก SSH identity กับ Git identity ทำให้เข้าใจง่ายขึ้นincludeIfแยกตัวพิมพ์ใหญ่-เล็ก และลำดับความสำคัญคือการตั้งค่าตัวสุดท้ายชนะถ้าต้องการตรวจสอบว่าทำงานถูกต้องหรือไม่ ให้รัน
git remote get-url originและgit config --get user.emailผมมองว่าวิธีที่ดีกว่าคือใส่ alias แยกตาม identity ไว้ใน
.gitconfigของHOMEแล้วรันgit config-companyหรือgit config-personalทันทีหลังจาก init หรือโคลนรีโพซิทอรีเปิด
user.useConfigOnly = trueแล้วให้ alias ตั้งค่าuser.email,user.name,core.sshCommandของรีโพซิทอรีโลคัลให้ใช้คีย์ SSH ส่วนตัว/ของบริษัทตามลำดับก็พอวิธีในบทความมีข้อดีตรงที่ถ้าโคลนจากองค์กรก็ใช้งานได้เลย
เมื่อก่อนที่สตาร์ทอัพแห่งหนึ่ง เคยมีคนที่เปลี่ยน identity เป็นชื่อมั่ว ๆ เหมือนในนิทานทุกวัน
คอมมิตวันจันทร์เป็น Mr. Bunnymann วันอังคารเป็น Doctor Funtime อะไรทำนองนั้น ทำให้ลำบากมากเวลาไล่ทำ นิติวิทยาศาสตร์ด้านเวอร์ชันคอนโทรล
ถ้ามองแบบใจดี เขาอาจตั้งใจเตือนว่าทุกคนสามารถใส่อะไรก็ได้ในการตั้งค่า identity ดังนั้นไม่ควรเชื่อค่าพวกนั้นมากเกินไป
ถึงอย่างนั้น การรู้ว่าใครทำก็ยังมีประโยชน์เมื่ออยากถามรายละเอียด หรือคาดเดาสไตล์กับความเชี่ยวชาญ
ถ้าบังคับให้คอมมิตต้องมี ลายเซ็น GPG และลงทะเบียน GPG identity ที่อนุญาตไว้ ก็สามารถระบุตัวผู้เขียนจริงจากลายเซ็น แทนที่จะพึ่งเมทาดาทา author/committer ได้
แน่นอนว่า “ทำให้ง่าย” กับลายเซ็น GPG ไม่ได้เข้ากันดีเสมอไป
ถ้าไว้ใจไม่ได้ว่าพนักงานจะระบุคอมมิตของตัวเองให้ถูกต้อง ก็ควรไล่ออก
ไม่จำเป็นต้องไปแตะ
~/.ssh/config; แค่ใส่core.sshCommand = /usr/bin/ssh -o IdentitiesOnly=yes -i ~/.ssh/IdentityFile2 -aไว้ใน~/.gitconfigหรือ~/.config/git/personalตามในบทความก็พอแบบนี้ทำให้ ซับโมดูล ง่ายขึ้นแม้ไม่ใช้
insteadOfผมใช้
includeIfแบบอิงไดเรกทอรีมาตั้งนานแล้ว (https://www.bobek.cz/til/git-identities/) แต่hasconfig:remoteนี่เรียบร้อยมากจริง ๆใช้ได้ตั้งแต่ตอนโคลนรีโพซิทอรีด้วย
includeIfค่อนข้างดีตอนนี้ผมเก็บความซับซ้อนของ SSH ไว้ที่
~/.sshแล้วมี include แยกหนึ่งตัวต่อหนึ่งลูกค้า/โปรเจกต์/identityอะไรที่ไม่มีโฮสต์เนมเฉพาะอย่าง GitHub ก็ใส่ host alias เช่น
customer-githubแล้วตั้งค่าHostName github.com,IdentityFile ~/.ssh/customer_rsa,User gitจากนั้นเวลา
git cloneก็ใช้ alias นั้นอย่างเดียว จบผมเคยเจอปัญหาเดียวกัน และตอนนี้ก็เหมือนมีทางแก้แล้ว
ถ้าใช้ NixOS กับ home-manager บน Linux และ Mac การตั้งค่านี้จะง่ายขึ้น
ใส่
condition = "hasconfig:remote.*.url:git@github.com:/**"และการตั้งค่าuser.emailไว้ในprograms.git.includesก็พออ้างอิง: https://nix-community.github.io/home-manager/options.xhtml#opt-programs.git.includes
.gitconfigโดยตรงเท่าไรเงื่อนไขกับการตั้งค่าก็เหมือนในบทความ แต่เพิ่ม ขั้นตอน build/template และต้องเรียนภาษาโปรแกรมใหม่ที่มีไวยากรณ์แปลก ๆ เข้าไปอีก
ผมแยกการตั้งค่างานกับส่วนตัวด้วย
includeIf: "gitdir"อยู่แล้ว แต่hasconfig:remoteนี่เป็นฟีเจอร์ที่เปลี่ยนเกมโดยสิ้นเชิงสำหรับคอนซัลแตนต์ ผมแนะนำอย่างหนักแน่นเสมอให้ใช้ เครื่องแยกต่างหาก สำหรับงาน หรืออย่างน้อยก็ใช้ผู้ใช้ OS แยกต่างหาก
ถ้าใช้เครื่องส่วนตัวทำงาน มีความเสี่ยงที่จะเจอปัญหาใหญ่
อาจเป็นกรณีบริษัทที่ทำงานแบบรีโมตเป็นหลัก ให้เตรียมแล็ปท็อปเองและจ่ายเงินซื้อเครื่องใหม่ทุก 2–3 ปี แต่ก็ยังเป็นแล็ปท็อปส่วนตัวอยู่ หรืออาจเป็นผู้รับเหมาชั่วคราวก็ได้
ควรอธิบายให้เจาะจงกว่านี้ว่าในสถานการณ์ไหนและเพราะอะไรจึงเป็นปัญหา
ความเสี่ยงมีจริง แต่ถ้าแจกแจงไม่ได้ ก็ใกล้เคียงกับการปล่อย FUD มากกว่าการให้ความรู้
นี่คือเครื่องมือที่ผมทำไว้เพื่อเปลี่ยน Git identity ตามโปรเจกต์ได้ง่าย ๆ: https://github.com/cquintana92/git-switch-user
หลังตั้งค่า identity แล้ว รัน
$ git su Personalหรือ$ git su Workจากนั้นอีเมล ชื่อ คีย์ SSH และเลือกได้ว่าจะรวมคีย์ PGP ด้วยหรือไม่ จะถูกตั้งค่าใน.git/configของรีโพซิทอรีช่วยประหยัดเวลาไปได้มาก
เป็นเครื่องมืออายุ 12 ปีแล้ว แต่ยังดูแลอย่างต่อเนื่อง