多个 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

hosthostname 一致的两个常用账户则不需要修改远程服务器地址了。

为了保证对应账户下的 git 仓库使用对应的账户名和邮箱进行 commit, push 等,
还需要进行每个 git 仓库设置对应的 user.nameuser.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_workid_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 时建议 hosthostname 保持一致,
    如此不用修改配置。

  • 如果你在同一个 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"
    • 使用上述配置,对于要新 clonework 账户下的仓库或是本地已存在的仓库,不需要修改任何配置,因为 hosthostname 一样。

    • 对于

      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"