在多个git服务器和用户之间进行切换的终极解决方案
在多个git服务器和用户之间进行切换的终极解决方案
在网上看到有人往GitHub提交commit的时候不小心使用了公司的邮箱,结合网友的回复,想把这个问题梳理一下再。
以上图片来自网络
为了演示这个问题,本文使用GitHub来模拟公司的git服务器,GitLab模拟私人的。往GitHub提交代码使用的公司的邮箱和用户名,往GitLab提交代码使用私人的邮箱和用户名
多个用户的验证问题
建议使用SSH Key加上 SSH config的方式。
首先使用 ssh-keygen 命令生成两对SSH key pair
$ ls .sshgithub github.pub gitlab gitlab.pub
分别把public key上传到GitHub和GitLab
https://github.com/
https://gitlab.com/
准备ssh的config文件, 对于不同的目标服务器使用不同的SSH 私钥
$ more ~/.ssh/configHost github.comIdentityFile/home/penxiao/.ssh/githubUser xiaopeng163Host gitlab.comIdentityFile/home/penxiao/.ssh/gitlab
然后就可以不用密码进行git的clone和commit了
$ git clone git@gitlab.com:zhangsan163/gitlab-test.git$ git clone git@github.com:xiaopeng163/github-test.git$ lsgithub-test gitlab-test
gitconfig
一般情况下我们会有一个全局的gitconfig, 假如下面是我的公司邮箱的话
more ~/.gitconfig[user]email = pengxiao@company.comname =PengXiao
但是这样的问题是,我们进行commit的时候,不管是往Github还是Gitlab都会使用这个username和email进行commit,这样很不好,假如你公司的电脑上,全局的gitconfig是公司的邮箱,而你去commit的一个项目却是一个私人项目,那你的个人信息就泄露了。
最笨的办法
修改每一个项目的git config来覆盖全局的config
比如我想在GitLab的项目里使用下面的邮箱, 而用户名使用global全局的。
➜ gitlab-test git:(main) more .git/config[core]repositoryformatversion =0filemode =truebare =falselogallrefupdates =true[remote "origin"]url = git@gitlab.com:zhangsan163/gitlab-test.gitfetch =+refs/heads/*:refs/remotes/origin/*[branch "main"]remote = originmerge = refs/heads/main[user]email = pengxiao@private.com
你可以手动修改这个config文件,或者进入到这个项目的文件夹,然后使用命令
$ cd gitlab-test$ git config user.email "[email protected]"
这时候新的commit就会使用这个配置了
➜ gitlab-test git:(main) touch test.txt➜ gitlab-test git:(main)✗ git add test.txt➜ gitlab-test git:(main)✗ git commit -m 'first commit'[main 6737d50] first commit1 file changed,0 insertions(+),0 deletions(-)create mode 100644 test.txt➜ gitlab-test git:(main) git logcommit 6737d50f2cb533db2d42ca2030820088bc3cb960(HEAD -> main)Author:PengXiao<pengxiao@private.com>Date:FriJul212:05:002021+0200first commitcommit b2abaefa1c786bc9f4427c382afa35cba2ca3a83 (origin/main, origin/HEAD)Author:PengXiao<pengxiao@private.com>Date:FriJul209:41:152021+0000Initial commit(END)
使用git alias或者Linux alias简化命令
http://git-scm.com/book/en/v2/Git-Basics-Git-Aliases
我们的目的是只要是私人的项目,我都想通过下面的命令,修改项目local的config
$ git config user.email "[email protected]"两条命令,虽然不多,但是也有点麻烦,我们可以通过git alias的用法,把它给简化成一个简单的命令,这个非常像linux的alias, 你可以简化任何你认为复制的命令
git config --globalalias.private'config user.email "[email protected]m"'➜ gitlab-test git:(main) more ~/.gitconfig[user]email = pengxiao@company.comname =PengXiao[alias]private= config user.email \"pengxiao@private.com\"➜ gitlab-test git:(main)
这时候每次你只需要运行一次 git private 就ok了
➜ gitlab-test git:(main) more .git/config[core]repositoryformatversion =0filemode =truebare =falselogallrefupdates =true[remote "origin"]url = git@gitlab.com:zhangsan163/gitlab-test.gitfetch =+refs/heads/*:refs/remotes/origin/*[branch "main"]remote = originmerge = refs/heads/main➜ gitlab-test git:(main) git private➜ gitlab-test git:(main) more .git/config[core]repositoryformatversion =0filemode =truebare =falselogallrefupdates =true[remote "origin"]url = git@gitlab.com:zhangsan163/gitlab-test.gitfetch =+refs/heads/*:refs/remotes/origin/*[branch "main"]remote = originmerge = refs/heads/main[user]email = pengxiao@private.com➜ gitlab-test git:(main)
终极解决方案
这个方案我也是刚从网上学到的。
以上两个方案不管是手动配置还是alias,都需要记住,万一忘了,还是有可能会把公司邮箱泄露出去的。有一个比较好的终极解决方案
•公司项目和私人项目放到不同的目录•在不同的目录使用不同的git config
我们可以使用 git version 2.13开始支持的conditional configuration includes. 文档见 https://git-scm.com/docs/git-config#_includes
首先把项目放到不同的目录:
•公司项目放到company目录•私人项目放到private目录
这样的灵活性就非常非常大了。
➜ tmp mkdir company➜ tmp mkdir private➜ tmp cd company➜ company git clone git@github.com:xiaopeng163/github-test.gitCloninginto'github-test'...remote:Enumerating objects:3,done.remote:Counting objects:100%(3/3),done.remote:Total3(delta 0), reused 0(delta 0), pack-reused 0Receiving objects:100%(3/3),done.➜ company cd ../private➜private git clone git@gitlab.com:zhangsan163/gitlab-test.gitCloninginto'gitlab-test'...remote:Enumerating objects:3,done.remote:Counting objects:100%(3/3),done.remote:Total3(delta 0), reused 0(delta 0), pack-reused 0Receiving objects:100%(3/3),done.➜private cd ..➜ tmp tree ..├── company│└── github-test│└── README.md└──private└── gitlab-test└── README.md4 directories,2 files➜ tmp
创建一个private的git config
➜~ more ~/.gitconfig-private[user]email = pengxiao@private.comname =PengXiao➜~
在global的gitconfig里设置当使用私人目录的时候,就加载私人的git config
➜~ more ~/.gitconfig[user]email = pengxiao@company.comname =PengXiao[includeIf "gitdir:~/tmp/private/"]path =.gitconfig-private
我们验证一下,首先是提交公司的项目,可以看到邮箱是使用的公司邮箱
➜~ cd tmp/company/github-test➜ github-test git:(master) touch test.txt➜ github-test git:(master)✗ git add test.txt➜ github-test git:(master)✗ git commit -m 'first commit'[master a64b46f] first commit1 file changed,0 insertions(+),0 deletions(-)create mode 100644 test.txt➜ github-test git:(master) git logcommit a64b46f0cecac00c2791f169a722b805596eec71 (HEAD -> master)Author:PengXiao<pengxiao@company.com>Date:FriJul212:39:332021+0200first commit
然后我们在测试一下私人项目, 提交的commit就是私人邮箱了。
➜~ cd tmp/private/gitlab-test➜ gitlab-test git:(main) more .git/config[core]repositoryformatversion =0filemode =truebare =falselogallrefupdates =true[remote "origin"]url = git@gitlab.com:zhangsan163/gitlab-test.gitfetch =+refs/heads/*:refs/remotes/origin/*[branch "main"]remote = originmerge = refs/heads/main➜ gitlab-test git:(main) touch test.txt➜ gitlab-test git:(main)✗ git add test.txt➜ gitlab-test git:(main)✗ git commit -m 'first commit'[main b91a660] first commit1 file changed,0 insertions(+),0 deletions(-)create mode 100644 test.txt➜ gitlab-test git:(main) git log➜ gitlab-test git:(main)commit b91a6607e20bb07b55e60ffa7478f25e3d621cd8 (HEAD -> main)Author:PengXiao<pengxiao@private.com>Date:FriJul212:41:592021+0200first commit
你学会了么。