安得万里风,飘飖吹我裳。
唐 杜甫 《夏夜叹》
摘要
目前使用 git 作为文件版本控制工具的开发者越来越多,同时一个开发者可以拥有多个不同 git 服务器的帐号或者同一个 git 服务器的不同帐号。
例如,小明在公司有个公司搭建的 git 服务器帐号用于工作开发,同时在目前流行的 github 和 bitbucket 上也有帐号,在业余时间 fork 一些项目,然后做一些 contributes. 这时小明就会遇到一个问题,账户这么多,如果每次使用 git 软件在终端进行 add, commit 后,需要 push 到本地仓库对应的远程服务器时,如果没有事先配置好 ssh 免密码登录或是其他密钥管理方法, 每次都需要输入对应的服务器账户密码来进行安全认证。
有没有什么方法可以一劳永逸地解决这个多 git 账户自动匹配免密码登录问题呢?
本文描述了在 Terminal 环境下使用 ssh 协议的多个不同 git 服务器帐号的 git 仓库如何自动匹配免密码登录的方法。
快速预览
主要解决两个问题,免密码登录 和 多账户自动匹配,前者可以使用 ssh 公私钥对解决,后者通过编辑 ssh 配置文件解决。
场景模拟
小明目前有 3 个 git 服务器账户,账户信息分别如下:
- 第 1 个是公司购买的 bitbucket 付费账户,用于日常工作开发, 其账户名为
xiaoming
, 关联邮箱为xiaoming@test.com
,
目前工作项目的仓库地址为git@bitbucket.org:xiaoming/testFly.git
. - 第 2 个是自己私人申请的免费 bitbucket 账户, 用于管理和保存私人的配置文件等或者 fork 一些项目研究做些贡献,其账户名为
superming
,关联邮箱为
superming@gmail.com
, 目前关注的项目仓库地址是git@bitbucket.org:superming/superman.git
. - 第 3 个账户也是自己私人申请的免费 github 账户,这里是开源的天堂,小明经常在此 star, watch, fork 项目等,其账户名为
mingh
, 关联邮箱为
mingh@gmail.com
.
为了实现这 3 个账户自动匹配免密码登录,小明首先依次生成了三对密钥文件:
# 生成第 1 个名为 xiaoming 账户的密钥对
$ssh-keygen -t rsa -f ~/.ssh/id_rsa_xiaoming -C "xiaoming@test.com"
# 生成第 2 个名为 superming 账户的密钥对
$ssh-keygen -t rsa -f ~/.ssh/id_rsa_superming -C "superming@gmail.com"
# 生成第 3 个名为 mingh 账户的密钥对
$ssh-keygen -t rsa -f ~/.ssh/id_rsa_mingh -C "mingh@gmail.com"
接着手动添加了这 3 对密钥对的私钥文件到 ssh-agent
会话用于自动认证 ssh
会话连接:
$ssh-add ~/.ssh/id_rsa_xiaoming
$ssh-add ~/.ssh/id_rsa_superming
$ssh-add ~/.ssh/id_rsa_mingh
由于 ssh-agent
会话是一个临时的会话,在终端退出后也随之结束,为了每次启动终端时都能自动添加私钥文件:
$echo "ssh-add ~/.ssh/id_rsa_xiaoming >/dev/null 2&1" >> ~/.bashrc
$echo "ssh-add ~/.ssh/id_rsa_superming >/dev/null 2&1" >> ~/.bashrc
$echo "ssh-add ~/.ssh/id_rsa_mingh >/dev/null 2&1" >> ~/.bashrc
由于小明用的是 zshell
, 需要把 ~/.bashrc
改成 ~/.zshrc
.
接下来就要配置 ~/.ssh/config
配置文件实现账户自动匹配:
# 第 1 个 xiaoming bitbucket 工作账户
host xiaoming_work
hostname bitbucket.org
Port 22
User git
IdentityFile "~/.ssh/id_rsa_xiaoming"
# 第 2 个 superming bitbucket 私人账户
host bitbucket.org
hostname bitbucket.org
Port 22
User git
IdentityFile "~/.ssh/id_rsa_superming"
# 第 3 个 mingh github 私人账户
host github.com
hostname github.com
Port 22
User git
IdentityFile "~/.ssh/id_rsa_mingh"
由于工作账户新项目创建不频繁,所以使用了 xiaoming_work
作为 host
, 但同时需要到当前工作的项目的根目录修改远程服务器地址:
# 原远程服务器 origin 地址为 git@bitbucket:xiaoming/testFly.git
$git remote remove origin
$git remote add origin xiaoming_work:xiaoming/testFly.git
而 host
与 hostname
一致的两个常用账户则不需要修改远程服务器地址了。
为了保证对应账户下的 git 仓库使用对应的账户名和邮箱进行 commit
, push
等,
还需要进行每个 git 仓库设置对应的 user.name
和 user.email
:
$cd <testFly 仓库根目录>
$git config --local user.name "xiaoming"
$git config --local user.email "xiaoming@test.com"
...
## 其他仓库类似配置
方法详解
-
为指定 git 账户生成 ssh 密钥文件实现免密码登录
ssh-keygen -t rsa -f ~/.ssh/id_rsa_work -C "work@163.com"`
-
-t rsa
指定生成密钥类型(type)为 rsa 非对称加密; -
-f ~/.ssh/id_rsa_work
指定生成密钥存放文件(file)为~/.ssh/id_rsa_work
, 该文件名可以由用户自己命名,
建议该文件统一放在~/.ssh/
目录下以便于管理; -
-C "work@163.com"
给该密钥添加注释(comment),一般使用关联该 git 账户的 email.
执行此命令后需要你输入要生成的密钥文件的口令(密码)和重复输入口令,连按回车键即可设置密钥文件口令为空从而实现免密码登录。
然后你就会在~/.ssh
目录下找到新生成的密钥文件分别为id_rsa_work
和id_rsa_work.pub
, 前者为私钥文件,本地私人使用,后者为公钥文件,
可以公开使用。
-
-
添加上述私钥文件到当前 ssh-agent 会话用于认证 ssh 会话
ssh-add ~/.ssh/id_rsa_work
-
查看当前会话已添加的 ssh 私钥
ssh-add -L
-
每次启动终端时都自动添加指定私钥到当前 ssh-agent 会话中
echo "ssh-add ~/.ssh/id_rsa_work >/dev/null 2>&1" >> ~/.bashrc
如果使用 zshell
echo "ssh-add ~/.ssh/id_rsa_work >/dev/null 2>&1" >> ~/.zshrc
-
配置
~/.ssh/config
文件实现多 git 账户自动匹配认证登录
编辑~/.ssh/config
ssh 配置文件(如果没有该文件就手动新建,touch ~/.ssh/config
),
以 bitbucket 帐户为例,例如账户work
下的一个 git 仓库地址为:git@bitbucket.org:work/test.git
, 从仓库地址可以看出此仓库的
用户名(User
)为git
, 主机名(hostname
)为bitbucket.org
, 通信端口号(Port
)一般为22
.所以其配置为:# 此处演示 bitbucket 下注册的账户名为 work 的账户的 ssh 配置 host git@bitbucket.org # 主机别名,用户自定义,具有唯一性 hostname bitbucket.org # git 远程服务器主机名 Port 22 # git 服务器端口号,一般默认为 22 User git # git 仓库地址中 @ 符号前的用户名,常见为 git, 注意与你在该服务器上申请的账户名区分 IdentityFile "~/.ssh/id_rsa_work" # 刚开始生成的密钥文件存放位置
其中
hostname
,User
,Port
对应于 git 仓库地址里的信息,而host
可以认为是一个别名,表示了这一主机的别名,
可随意命名,用于区分具有同一个hostname
的不同账户的仓库。IdentityFile
为私钥认证文件,即上文生成的id_rsa_work
文件. -
部署公钥到 git 服务器
例如在 bitbucket 服务器网页上菜单bitbucket Settings > SSH keys > Add key
,
把公钥文件里的公钥字符串拷贝粘贴到此处设置处.# 拷贝公钥字符串到系统剪贴板,此处是 macOS 的系统剪贴板 cat ~/.ssh/id_rsa_work.pub | pbcopy
-
测试 ssh 能否免密码直连
ssh -vT git@bitbucket.org
或者使用
git clone
一个当前账户下的私人项目到本地看是否成功。 修改本地 git 仓库的远程服务器地址
- 如果你在 github 或者 bitbucket 服务器上都只注册了一个账户,在配置
~/.ssh/config
时建议host
与hostname
保持一致,
如此不用修改配置。 - 如果你在同一个 git 服务器上有两个账户,例如在 bitbucket 上有常用的
work
账户和不太常用的life
账户,~/.ssh/config
可以配置如下:# personal git account "work" in bitbucket host git@bitbucket.org hostname bitbucket.org Port 22 User git IdentityFile "~/.ssh/id_rsa_work" # personal git account "life" in bitbucket host lifebucket hostname bitbucket.org Port 22 User git IdentityFile "~/.ssh/id_rsa_life"
- 使用上述配置,对于要新
clone
的work
账户下的仓库或是本地已存在的仓库,不需要修改任何配置,因为host
与hostname
一样。 - 对于
life
账户下的仓库:- 新 clone 的仓库需要修改仓库地址url,例如
git clone git@bitbucket.org:life/tutorial.git
改为git clone lifebucket:life/tutorial.git
- 已经存在的仓库,切换到该仓库根目录,执行
git remote remove origin && git remote add origin lifebucket:life/tutorial.git
.
- 新 clone 的仓库需要修改仓库地址url,例如
- 使用上述配置,对于要新
- git 设置
由于有多个不同的 git 账户,一般不能随意设置 git 全局设置了,尤其是user.name
和user.email
,需要单独给每个仓库设置。
首先移除全局设置:
git config --global --unset user.name && git config --global --unset user.email
,
然后到对应的仓库根目录下执行类似于下面的命令:git config --local user.name "life" git config --local user.email "life@163.com"