git 别名 ssh-add .gitconfig

git alias ssh-add .gitconfig

.gitconfig 我创建了一个这种类型的别名:

[alias]
    something = "!eval `ssh-agent -s` && ssh-add ~/.ssh/id_acub && git config --global user.email <email> && git config --global user.name <user.name>"

此时,运行 git something 正确显示了信息,但它没有像我预期的那样工作。

如果我在控制台输入一行:

eval `ssh-agent -s` && ssh-add ~/.ssh/id_acub && git config --global user.email <email> && git config --global user.name <user.name>

那么一切正常。

别名有什么问题?

让我们从一个比 ssh-agent -s 更简单的例子开始:

$ sh -c 'FOO=bar; echo FOO is now $FOO'
FOO is now bar
$ echo FOO is now $FOO
FOO is now

为什么这不起作用?为什么我的登录 shell 的 FOO 变量没有设置,而当我设置其他 shell 实例的 FOO 变量时?

好吧,我希望答案是显而易见的:my shell 没有设置 FOO。我设置了一些 other shell 的 FOO 变量。我告诉 other shell 打印它,它被设置了。然后 other shell 完成——退出——并将控制权交还给我的登录名 shell,当我告诉我的登录名 shell 打印我的登录名时shell的FOO,没有设置。

ssh-agent -s 所做的是打印出 一些作业。让我们试试看:

$ sh -c 'echo FOO=bar'
FOO=bar
$ echo FOO is now $FOO
FOO is now

当然这也没有用,因为我只是打印了一些说明。没有人遵循这些指示。

所以让我们再尝试一件事:

$ eval `sh -c 'echo FOO=bar'`
$ echo FOO is now $FOO
FOO is now bar

这一次,我:

  • 让另一个命令打印一些指令
  • 告诉 我的 shell 遵循 那些指示
  • 然后让我的 shell 打印出 shell 的 $FOO
  • 设置

并且由于我的 shell 按照说明 更改了 一些 我的 shell,现在 我的 shell 的 FOO 已设置。

ssh-agent 的设计是相同的:它做一些工作,然后——在各种模式下,包括 -s——打印出一些指令 shell关注。您需要 eval 才能 shell 遵循这些说明。

这一切都很好,只要遵循这些说明的 shell 是 您的 shell,就可以做您想做的事。但是,当您创建 Git 别名时,Git 本身会运行一个 新的、不同的 shell。 shell 遵循说明,完成后,您的 shell 不受影响。

这意味着您不能用 Git 别名做您想做的事。您必须使用会影响 您的 shell 的别名或函数,而不是会启动一个新的 shell、影响它,然后让它终止并拥有的别名或函数这些影响消失了。

请注意,某些更改(例如 git config --global)存储在 文件 中,而不是您的 shell。当 shell 消失时,这些变化 不会 消失。这是一个关键的区别:文件系统状态存储在各个进程之外。如果 ssh-agent 所做的一切都存储在文件系统状态中,它 可以 工作,但是 ssh-agent 所做的一些事情并没有存储在那里。