สวัสดีครับ วันนี้ขอมาเขียนเกี่ยวกับเรื่อง Git ที่เจอมาครับ สืบเนื่องจากต้องใช้ Git แบบหลายๆ Account ในเครื่องเดียว ก็เลยเจอปัญหา ตั้งแต่การตั้งค่า SSH (ถ้าเกิดใช้ HTTPS ก็ไม่เป็นไร เพราะมันให้ Login ทุกครั้งที่ Clone หรือ commit อยู่แล้ว) กับอีกส่วนคือ เมื่อมีหลายๆ Account ตัว git config ก็ย่อมแตกต่างกัน ทีนี้มันก็ไม่มีพวก asdf-vm ที่เอาไว้สลับ version แบบพวก package ด้วยซิ อยากสลับ Account git ได้บ้าง เลยเกิดมาเป็นบทความนี้ครับ

ก่อนไปเข้าเรื่อง

สมมติผมต้องการ Setup ให้ 2 Account 1. คือ Github และ 2. คือ Gitlab โดยทั้งคู่ใช้ email แตกต่างกันด้วยครับ

  1. Github - สมมติผมใช้ User - devahoy@gmail.com (ใช้ gmail)
  2. Gitlab - สมมติผมใช้ User - hello@devahoy.com (ใช้ company domain)

Setup SSH หลายๆ Account

ปกติผมจะ Setup SSH แยกกันอยู่แล้ว แต่ละ Account ก็ต้องใช้คนละ key (หรือใครใช้ key เดียวกันหมดเลย ก็ข้ามไปได้เลยจ้า)

เช่น ไฟล์หลัก ผมจะใช้ ~/.ssh/id_rsa.pub แน่นอน ส่วน public key รองๆ ตัวอย่างเช่น

  • ~/.ssh/id_rsa.pub : public key ตัวหลักที่ใช้กับ gmail
  • ~/.ssh/gitlab_key_hello_devahoy.pub : public key ที่ใช้สำหรับ gitlab

ส่วนวิธี Create new SSH Key ก็ไม่ยากครับ

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

กำหนด passphrase (Password) และตั้งชื่อ public key ที่เราจะเก็บ ก็เรียบร้อย ทีเหลือก็ไปใส่ SSH key ใน Account Setting แต่ละ Provider เอาเองเน้อ

Reference Generating new SSH key

สุดท้าย เวลาเรา connect กับ git ด้วย SSH เช่น git clone หรือ git push ที่เป็น protocal ssh มันก็จะใช้ public/private key แทนการ Authentication ด้วย Username และ Password ละ

โดยปกติ SSH มันจะใช้ตัว default คือ id_rsa.pub แต่ทีนี้ เมื่อเรา custom แล้ว อยากให้ Gitlab ไปใช้อีก public key ก็ง่ายๆ เลยครับ แก้ไขไฟล์ ~/.ssh/config เป็นแบบนี้

Host github.com
  User git
  IdentityFile ~/.ssh/id_rsa
  IdentitiesOnly yes
Host gitlab.com
  User git
  HostName gitlab.com
  IdentityFile ~/.ssh/gitlab_key_hello_devahoy
  IdentitiesOnly yes

จะเห็นได้ว่า config ผมคือ เมื่อไหร่ก็ตามที่ host เป็น github.com ผมจะให้เวลาต่อ ssh จะให้มันอ่านไฟล์ ~/.ssh/id_rsa และขณะเดียวกันถ้า host เป็น gitlab.com ผมจะให้มันอ่านไฟล์ ~/.ssh/gitlab_key_hello_devahoy ทีนี้ก็หมดปัญหาการใช้ SSH หลายๆ key แล้ว 🎉

การสลับ Account git ด้วย git config

ต่อมา ผมยังเจออีกปัญหานึงคือ การ commit git คนละ email กัน เช่นของส่วนตัว กับ ของบริษัท

ก่อนหน้านี้ ผมใช้วิธีการตั้งค่า git config ของหลายๆ Account โดยการตั้งค่าด้วย Global เป็นบัญชีหลัก ก็ config ปกติ

git config --global user.name "Devahoy"
git config --global user.email "devahoy@gmail"

ไฟล์ config ของ git ก็จะอยู่ที่ ~/.gitconfig (หรือ Home ของ user ในเครื่อง)

และ local ก็จะเป็น Account อื่นๆ ทีนี้ปัญหามันคือ การตั้งค่า local ต้องเข้าไปแต่ละ folder และทำการ ตั้งค่าใหม่

git config user.name "Devahoy"
git config user.email "hello@devahoy.com"

ซึ่งค่า config ของ git ก็จะอยู่ในแต่ละโฟลเดอร์อยู่แล้ว .git/config ทีนี้เวลา Commit ที่โฟลเดอร์ local มันก็จะใช้ name และ email ของ local ได้ไม่มีปัญหา

แต่แน่นอน เกิดปัญหาขึ้น เพราะว่า มีบาง Folder ที่ clone มาแล้วลืม config local เลยทำให้มันใช้ global config ในการ commit แน่นอน มันมองเป็นคนละ account (จริงๆไม่ใช่ปัญหาใหญ่หรอก แต่ไหนๆ จะแยกแล้ว ก็เลยแยกกันไปดีกว่า)

วิธีแก้ปัญหาที่ถูกต้อง คือ ทำ git config เป็น template ไปเลย เมื่อก่อนใช้ ตั้งค่าแต่ละ folder ตอนนี้เปลี่ยนใหม่ ตั้งค่า folder ใหญ่ไปเลย เช่น

  • โฟลเดอร์ Workspace/Github/ - ข้างในนี้เป็น global
  • โฟลเดอร์ Workspace/Gitlab/ - ข้างในนี้เป็น git local

ซึ่ง git มี includeIf ให้ใช้ครับ คือ ไปแก้ไขไฟล์ ~/.gitconfig (เป็น global config) และเพิ่มนี้ลงไปซะ

[includeIf "gitdir:~/Workspace/Gitlab/"]
  path = ~/Workspace/Gitlab/.gitconfig

กล่าวคือ เมื่อไหร่ก็ตาม ที่ git folder เราอยู่ภายใต้ Workspace/Gitlab มันก็จะไปอ่านไฟล์ config ที่ Gitlab/.gitconfig ของเรา ซึ่งเป็นแบบนี้

[user]
  name = Devahoy
  email = hello@devahoy.com

ทีนี้เวลา เรา clone repo มาไว้ในโฟลเดอร์ Workspace/Gitlab เวลา commit ตัว email เราก็จะเป็นคนละตัวกับ global ให้เลย โดยไม่ต้องมาเสียเวลา config ทุกๆครั้ง ทุกๆ folder (ซึ่งเรากำหนด template ด้วย includeIf หลายๆ config มากกว่า 2 ก้ได้นะ)

👍👍👍👍👍

สุดท้าย ต้องของคุณบทความนี้เลย ที่ทำให้ผมตั้งค่า git config ได้

Happy Coding ❤️