多个 Git 账户免密码登录配置

摘要

目前使用 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
2
3
4
5
6
# 生成第 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 会话连接:

1
2
3
$ssh-add ~/.ssh/id_rsa_xiaoming
$ssh-add ~/.ssh/id_rsa_superming
$ssh-add ~/.ssh/id_rsa_mingh

由于 ssh-agent 会话是一个临时的会话,在终端退出后也随之结束,为了每次启动终端时都能自动添加私钥文件:

1
2
3
$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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 第 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, 但同时需要到当前工作的项目的根目录修改远程服务器地址:

1
2
3
# 原远程服务器 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:

1
2
3
4
5
$cd <testFly 仓库根目录>
$git config --local user.name "xiaoming"
$git config --local user.email "xiaoming@test.com"
...
## 其他仓库类似配置

方法详解

  1. 为指定 git 账户生成 ssh 密钥文件实现免密码登录
1
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, 前者为私钥文件,本地私人使用,后者为公钥文件,
    可以公开使用。
  1. 添加上述私钥文件到当前 ssh-agent 会话用于认证 ssh 会话
1
ssh-add ~/.ssh/id_rsa_work
  1. 查看当前会话已添加的 ssh 私钥
1
ssh-add -L
  1. 每次启动终端时都自动添加指定私钥到当前 ssh-agent 会话中
1
echo "ssh-add ~/.ssh/id_rsa_work  >/dev/null 2>&1" >> ~/.bashrc

如果使用 zshell

1
echo "ssh-add ~/.ssh/id_rsa_work  >/dev/null 2>&1" >> ~/.zshrc
  1. 配置 ~/.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.所以其配置为:
1
2
3
4
5
6
# 此处演示 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 文件.

  1. 部署公钥到 git 服务器
    例如在 bitbucket 服务器网页上菜单 bitbucket Settings > SSH keys > Add key,
    把公钥文件里的公钥字符串拷贝粘贴到此处设置处.

    1
    2
    # 拷贝公钥字符串到系统剪贴板,此处是 macOS 的系统剪贴板
    cat ~/.ssh/id_rsa_work.pub | pbcopy
  2. 测试 ssh 能否免密码直连

    1
    ssh -vT git@bitbucket.org

    或者使用 git clone 一个当前账户下的私人项目到本地看是否成功。

  3. 修改本地 git 仓库的远程服务器地址

  • 如果你在 github 或者 bitbucket 服务器上都只注册了一个账户,在配置 ~/.ssh/config 时建议 host 与 hostname 保持一致,
    如此不用修改配置。

  • 如果你在同一个 git 服务器上有两个账户,例如在 bitbucket 上有常用的

    1
    work

    账户和不太常用的

    1
    life

    账户,

    1
    ~/.ssh/config

    可以配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 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 一样。

    • 对于

      1
      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.
  1. git 设置

    由于有多个不同的 git 账户,一般不能随意设置 git 全局设置了,尤其是

    1
    user.name

    和

    1
    user.email

    ,需要单独给每个仓库设置。

    首先移除全局设置:

    1
    git config --global --unset user.name && git config --global --unset user.email

    ,

    然后到对应的仓库根目录下执行类似于下面的命令:

    1
    2
    git config --local user.name "life"
    git config --local user.email "life@163.com"