我可以在每个项目的基础上缓存 git 凭据吗?

Can I cache git credentials on a per-project basis?

几个人正在通过网络共享在单个网络服务器上处理多个项目。每个项目都有自己的 git 存储库。在开始一个项目时,我们为从事该项目的每个开发人员提供一个个人开发环境,并为每个项目提供一个暂存环境。所有文件都归 www-data 所有,因为这是 Apache 使用的用户。

为了避免在拉取、推送和切换到新分支时多次输入用户名和密码,我们目前正在使用凭据缓存 (as found here)。

$ git config --global credential.helper
cache --timeout=900

我们面临的问题是,当某人(用户 1)执行经过身份验证的 git 操作时,他们输入了他们的凭据。在超时内,其他人(用户 2)在他们自己的存储库中执行经过身份验证的 git 操作,该操作使用用户 1 的凭据。这将导致以下两种情况之一发生:

我认为可以通过将用户名添加到 git 存储库 url 来部分缓解这个问题(例如 username@git.domain.ext/repo/name.git), 但这只适用于我们为每个用户提供个人开发环境的开始阶段。暂存环境需要多人访问,所以我们不能硬编码用户名。在我们完成初始开发并且项目上线后,我们清理开发环境,因为我们没有无限的 space。如果我们清理个人开发环境后需要进行更改,我们通常使用暂存环境进行更改,这会导致同样的问题发生。

git config --global credential.helper 命令导致凭据在服务器范围内存储。降低超时只有这么多帮助。我们可以缓存每个开发环境的凭据吗?

针对您的问题,有两种可能的解决方案:

1 - 每个开发者有一个 OS 用户。

这是更简洁的选项:每个开发人员都将连接到不同的用户帐户。将这些用户添加到组 www-data 并相应地设置文件选项:允许组成员读写。

每个用户的身份验证将被独立管理。

2 - 存储每个项目的配置

目前,--global 用户凭据的存储是在 OS 用户级别完成的。相反,您可以使用 --local,以便在项目级别存储凭据。

这将解决用户 1 和 2 之间所描述的问题。但是,您仍然可能缺乏一些可追溯性:如果两个开发人员在同一个项目上工作,如果用户 2 在用户 1 之后不久推送一些更改,用户 1 的身份验证将使用详细信息,看起来她就是推送的人 - 而实际上是 user2。

阅读 git config --help 了解有关 --local 选项和数据存储位置的详细信息。

停止使用网络共享。让用户在他们自己的机器上克隆存储库并以这种方式进行更改。不得在暂存环境中直接更改任何文件,即使通过网络共享也不应如此。

如果用户希望立即看到他们的更改并在此基础上进行实验,他们可以安装本地 Apache。

此外,您可以考虑将存储库托管在单独的服务器中,并使用部署工具从这些存储库部署到暂存环境,因为 git 并不是真正的部署工具。这可以自动化。但是,您最应该做的是停止使用网络共享并使用 git push 启动更改,而不是自己更改服务器上的文件。

我在那种共享环境中看到的一种缓解方法是使用一个名为 'git' 的包装器 shell 脚本,它将:

  • 掩盖实际的 git 命令
  • 由专用帐户启动(通过 sudo -u xxx)
  • 从以 ps id 命名的临时文件中读取凭据(xxx 拥有的文件,原始用户不可读)
  • 如果该临时文件不存在(在第一次 git 调用时),创建它并存储 username/password.
  • 将 "store" 帮助器用于 pull/push/clone 命令,使用命令本地配置 /usr/bin/git -c credential.helper 'store --file=/path/to/temp/credentials' ...,再次由包装器作为 xxx.
  • 执行

同一个脚本不仅可以请求凭据,还可以请求 authorname/email,并将其添加到其 git 命令中,设置本地 GIT_AUTHOR_NAME/EMAIL/usr/bin/git 次调用。

想法是使用本地配置执行 git 命令(本地到 git 命令本身)

我找不到与您所追求的完全匹配的选项,所以我写了一个:a git credential helper that stores credentials on a per-shell basis

设置临时加密密钥和登录数据临时目录,用于存放git在credential helper process阶段store给出的用户名和密码],然后在 get 阶段将它们还给他们。

注意事项:

  1. 我已经对其进行了测试,但只是以相当有限的方式进行了测试。它有效:同一用户的两个单独的登录 shell 可以具有单独的缓存凭据。
  2. 它相当天真:它在存储和检索凭据时忽略 git 提供的任何用户名和回购协议 URL。
  3. 它会为每次登录留下一个临时目录,其中包含一些小文件。
  4. 它存储加密的凭据,但我没有声明这在实践中有多安全。
  5. 它需要 Python 3.6、pycrypto 和 bash;我已经在 linux 和 macOS 上对其进行了测试。适应其他设置应该相当容易。

如果你 运行 遇到任何麻烦,请打开一个问题,我会看看我能做些什么。

使用git config --global credential.useHttpPath true可以解决部分问题。它消除了存储库不存在的错误,因为我们没有人有权拉取存储库,但无权推送它。两个人在不同目录中使用同一个存储库可能仍然会不小心以另一个用户的身份推送。

' 的回答是当您从事可以轻松播种的项目时的可靠建议。在我的例子中,很多项目都不容易播种,这使得它不太理想。

的答案可能是最干净的解决方案,并且可能比以下解决方案适用于更广泛的系统。


在我的例子中,我决定采用受 . git-credential-cache 启发的方法,允许两个参数,即 timeout 参数和 socket 参数。我们目前只使用 bash,它公开了包含当前 shell 的 pid 的 $BASHPID 变量。遗憾的是,我们不能直接在配置值中使用该变量,但是使用 VonC 的建议来隐藏 git 命令,我们可以创建一个别名。

我在 www-data 用户的 ~/.bashrc 文件中添加了一行并添加:

alias git="/usr/bin/git -c credential.helper='cache --timeout=7200 --socket=/var/www/.git-credential-cache/socket_$BASHPID'"

注意:socket需要是绝对路径,www-data用户的home目录刚好是/var/www/

我已经删除了全局凭证助手配置,如下所示:

git config --global --unset credential.helper

现在每个 bash shell 使用一个单独的套接字。这种方法的好处是它仍然使用 git 附带的缓存机制,这意味着它可能不会很快被破坏。缺点是隐藏命令会引入魔法行为(配置中没有设置任何内容,但无论如何它都在工作......如何?),这可能会在未来混淆同事。