有没有一种方法可以缓存https凭证以推送提交?

2096

我最近在GitHub上将我的存储库同步到https://(由于防火墙问题),每次都会要求输入密码。

有没有一种方法可以缓存凭据,而不是每次进行身份验证 git push


2
现在您可以使用凭据助手来加密包含您凭据的 _netrc 文件。请参见下面我的回答。我发现这比在Windows上有点不稳定的 git-credential-winstore.exe(内存缓存)更安全。 - VonC
一个安全易用的SSH或个人访问令牌的替代方案是通过Git凭据管理器使用OAuth,详见我的回答https://dev59.com/om435IYBdhLWcg3wkA5e#71286601。 - Colonel Panic
28个回答

2629
自Git 1.7.9(发布于2012年)以来,Git中有一种简洁的机制可以避免为HTTP / HTTPS一直输入密码,称为credential helpers
您只需使用以下凭据助手之一即可:
git config --global credential.helper cache

credential.helper cache value告诉Git在内存中缓存你的密码一段特定的时间。默认值为15分钟,你可以使用以下命令设置更长的超时时间:

# Cache for 1 hour
git config --global credential.helper "cache --timeout=3600"

# Cache for 1 day
git config --global credential.helper "cache --timeout=86400"

# Cache for 1 week
git config --global credential.helper "cache --timeout=604800"

如果需要,您也可以永久存储您的凭据,参见下面的其他答案。

GitHub的帮助文件还建议,如果您使用Homebrew安装Git,并且正在使用Mac OS X操作系统,您可以使用本地的Mac OS X密钥库:

git config --global credential.helper osxkeychain

对于 Windows 系统,有一个名为Git Credential Manager for Windowsmsysgit 中的 wincred的助手。

git config --global credential.helper wincred # obsolete

使用Git for Windows 2.7.3+(2016年3月):
git config --global credential.helper manager

对于Linux,您可以使用(在2011年)gnome-keyring(或其他密钥环实现,如KWallet)。

现在(2020),在Linux上会是以下这样:

Fedora

sudo dnf install git-credential-libsecret
git config --global credential.helper /usr/libexec/git-core/git-credential-libsecret

Ubuntu

sudo apt-get install libsecret-1-0 libsecret-1-dev
cd /usr/share/doc/git/contrib/credential/libsecret
sudo make
git config --global credential.helper /usr/share/doc/git/contrib/credential/libsecret/git-credential-libsecret

81
不要以明文形式存储密码。从Git 1.7.9开始,你可以使用凭证助手。在OS X上,可以使用git config --global credential.helper osxkeychain命令。其他操作系统请参考https://help.github.com/articles/set-up-git。 - dazonic
6
就翻译而言,意思是说:“就这件事来说,osx钥匙串的东西是基本GIT源代码的一部分,它不是Brew或MacPorts或其他流行工具的独有组件。你甚至不需要从头构建git - 只需转到contrib/credential/osxkeychain/并运行make命令即可。” - synthesizerpatel
3
使用双重验证需要使用 Github 所称的“个人访问令牌”(Person Access Token)。实际上,你应该始终使用它,因为与密码不同,你可以控制其访问权限。只需将 URL 中的密码替换为令牌,例如 https://username:PERSONAL_ACCESS_TOKEN@github.com/username/project.git。这使得存储在磁盘上的明文密码几乎可以安全使用。 - Russell Stuart
13
"git config --global credential.helper cache" 在Windows系统下无法使用:https://dev59.com/PGgt5IYBdhLWcg3w8h_e。在Windows系统中使用[gitcredentialstore](http://gitcredentialstore.codeplex.com/),就能愉快地使用了。 - Sebastian J.
9
有没有办法将这个超时设置为无限大? - sudo
显示剩余20条评论

787

您还可以使用git-credential-store将Git永久存储您的凭据,如下所示:

git config credential.helper store

注意:虽然这很方便,但 Git 会将你的凭据以明文形式存储在项目目录下的本地文件(.git-credentials)中(请参见下文的“主目录”)。如果您不喜欢这样做,请删除此文件并切换到使用缓存选项。

如果您希望Git每次连接到远程存储库时都要求您输入凭据,可以运行此命令:

git config --unset credential.helper

为了将密码存储在.git-credentials中,而不是项目目录中,可以使用--global标志,并将其存储在%HOME%目录下。

git config --global credential.helper store

7
在Windows上,您可以下载一个辅助工具来配置将加密版本的GIT密码存储在Windows凭据存储中,请参见https://confluence.atlassian.com/display/STASH/Permanently+authenticating+with+Git+repositories。 - Contango
80
我发现必须指定 --global,否则它会尝试将设置存储在当前仓库中: git config --global credential.helper store - Rag
6
为什么要使用缓存而不是永久存储?是为了共享计算机或其他原因吗? - Michael J. Calkins
3
我正在使用 Windows 上的 GIT 1.9.5 版本,--global 标志是多余的。即使没有此标志,凭据文件也会在 %USER_HOME% 目录中创建。 - jFrenetic
2
如果不是以纯文本形式存储,那么它受到什么保护?你的密码?那么当你连接到git时,它不是必须要求你输入管理员密码吗?难道为了获取另一个密码而需要输入密码不是有点奇怪吗? - Cruncher
显示剩余5条评论

119
TLDR; 使用 Git 1.8.3+ 中的加密 netrc 文件
保存 Git 存储库 HTTPS URL 的密码可以使用 ~/.netrc(Unix)或 %HOME%/_netrc(注意 _)(Windows)。
但是:该文件将以明文形式存储您的密码。
解决方案:使用GPG(GNU Privacy Guard)加密该文件,并使 Git 在每次需要密码时对其进行解密(用于push/pull/fetch/clone操作)。
注意:从Git 2.18(2018年第二季度)开始,您现在可以自定义用于解密加密的.netrc文件的GPG。
请参见commit 786ef50commit f07eeed(由Luis Marsano('')于2018年5月12日提交)。
(由Junio C Hamano -- gitster --合并到commit 017b7c5中,2018年5月30日)

git-credential-netrc:接受gpg选项

git-credential-netrc被硬编码为始终使用'gpg'进行解密,而不管选项。
这在像Debian这样的发行版中是一个问题,因为现代GnuPG被称为其他名称,例如'gpg2'。


Windows的逐步说明

在Windows上:

(Git在其发行版中有一个gpg.exe,但使用完整的GPG安装包包括gpg-agent.exe,它将记住与您的GPG密钥相关联的密码短语。)

  • Install gpg4Win Lite, the minimum gnupg command-line interface (take the most recent gpg4win-vanilla-2.X.Y-betaZZ.exe), and complete your PATH with the GPG installation directory:

      set PATH=%PATH%:C:\path\to\gpg
      copy C:\path\to\gpg\gpg2.exe C:\path\to\gpg\gpg.exe
    
(注意 'copy' 命令:Git 需要一个 Bash 脚本来执行命令 'gpg'。由于 gpg4win-vanilla-2 自带 gpg2.exe,你需要复制它。)
  • Create or import a GPG key, and trust it:

      gpgp --import aKey
      # or
      gpg --gen-key
    

(确保为该密钥设置密码短语。)

  • Trust that key

  • Install the credential helper script in a directory within your %PATH%:

      cd c:\a\fodler\in\your\path
      curl -o c:\prgs\bin\git-credential-netrc https://raw.githubusercontent.com/git/git/master/contrib/credential/netrc/git-credential-netrc.perl
    

注意:该脚本在Git 2.25.x/2.26中被重命名,请见下文。

是的,这是一个Bash脚本,但它将在Windows上工作,因为它将被Git调用。

  • Make a _netrc file in clear text

      machine a_server.corp.com
      login a_login
      password a_password
      protocol https
    
      machine a_server2.corp.com
      login a_login2
      password a_password2
      protocol https
    
(不要忘记 'protocol' 部分:根据您使用的 URL,选择 'http' 或 'https'。)
  • Encrypt that file:

      gpg -e -r a_recipient _netrc
    
现在您可以删除_netrc文件,只保留加密的_netrc.gpg文件。
  • Use that encrypted file:

      git config --local credential.helper "netrc -f C:/path/to/_netrc.gpg -v"
    
(Note the '/': C:\path\to... wouldn't work at all.) (请注意 '/':在路径中使用 'C:\path\to...' 将完全无法工作。)(您可以首先使用 -v -d 查看正在发生什么。)
从现在开始,任何使用 HTTP(S) URL 并需要身份验证的 Git 命令都将解密 _netrc.gpg 文件并使用与您联系的服务器相关联的登录名/密码。 第一次,GPG 会要求您输入 GPG 密钥的密码以解密文件。 其他时间,由第一个 GPG 调用自动启动的 gpg-agent 将为您提供该密码。
这样,您可以将 多个 URL / 登录名 / 密码存储在一个文件中,并将其加密存储在您的磁盘上。
我觉得它比“缓存”助手更方便,因为您需要记住和键入每个远程服务的不同密码 (每个会话只需一次),才能将该密码缓存在内存中。

随着Git 2.26(2020年第一季度)的发布,用于使用.netrc的示例凭据助手已经更新,可以直接使用。详情请参见patch/discussion

查看commit 6579d93commit 1c78c78(2019年12月20日)由Denton Liu (Denton-L)提交。
(合并自Junio C Hamano -- gitster --commit 1fd27f8中,2019年12月25日)

contrib/credential/netrc: 使 PERL_PATH 可配置化

签署者: Denton Liu

git-credential-netrc 中的 Perl 解释器的 shebang 路径是硬编码的。
然而,一些用户可能会将其位于不同的位置,因此必须手动编辑脚本。

在脚本中添加 .perl 前缀,以将其标记为模板并忽略生成的版本。
增加 Makefile,使其从 git-credential-netrc.perl 生成 git-credential-netrc,就像其他 Perl 脚本一样。

Makefile 配方无耻地从 contrib/mw-to-git/Makefile 中窃取。

还有:

随着 2.26(2020 年第一季度)的到来,用于使用 .netrc 的示例凭据助手已更新,可以直接使用。

查看commit 6579d93commit 1c78c78(2019年12月20日)由Denton Liu (Denton-L)提交。
(由Junio C Hamano -- gitster --commit 1fd27f8中合并,2019年12月25日)

contrib/credential/netrc:在仓库外工作

签署者:Denton Liu

Currently, git-credential-netrc does not work outside of a git repository. It fails with the following error:

fatal: Not a git repository: . at /usr/share/perl5/Git.pm line 214.

There is no real reason why need to be within a repository, though. Credential helpers should be able to work just fine outside the repository as well.

Call the non-self version of config() so that git-credential-netrc no longer needs to be run within a repository.

Jeff King (peff)添加:

I assume you're using a gpg-encrypted netrc (if not, you should probably just use credential-store).
For "read-only" password access, I find the combination of pass with config like this is a bit nicer:

[credential "https://github.com"]
username = peff
helper = "!f() { test $1 = get && echo password=`pass github/oauth`; }; f"

2013年与Git.pm相关的"fatal: Not a git repository"错误消息已在Git 2.39(2022年第四季度)中得到修复。

请查看由Jeff King (peff)于2022年10月22日提交的commit 20da61f
请查看由Michael McClimon (mmcclimon)于2022年10月16日提交的commit 77a1310
(合并自Junio C Hamano -- gitster --于2022年10月28日提交的commit 330135a

Git.pm:信任rev-parse查找裸库

签名作者:Jeff King

在初始化仓库对象时,我们运行 "git rev-parse --git-dir"(man) 命令来让 Git 的 C 语言版本找到正确的目录。但有趣的是,如果失败了,我们不会自动说 "不是 git 仓库"。相反,我们会进行自己的纯 Perl 检查以查看是否在裸仓库中。这没有多少意义,因为 rev-parse 会报告裸仓库和非裸仓库。这种逻辑来自于 d5c7721 ("Git.pm: Add support for subdirectories inside of working copies", 2006-06-24, Git v1.4.3-rc1 -- merge),但我没有看到任何原因说明为什么我们不能只依赖 rev-parse。更糟糕的是,由于我们将从 rev-parse 收到的任何非错误响应视为非裸仓库,因此即使在裸仓库中,我们也会错误地设置对象的 WorkingCopy。但情况变得更糟了。自从 8959555 (setup_git_directory(): add an owner check for the top-level directory, 2022-03-02, Git v2.36.0-rc2 -- merge)(2022-03-02 添加顶层目录的所有者检查)之后,这是明显错误的(而且危险的)。Perl 代码没有实现相同的所有权检查。更糟糕的是,在 "找到" 裸仓库后,它会在环境中设置 GIT_DIR,告诉任何后续的 Git 命令我们已经确认了目录是正确的,并且信任我们。也就是说,当使用 Git.pm 的仓库发现代码时,它重新打开了 8959555 填补的漏洞。我们可以通过依赖 rev-parse 来告诉我们何时不在仓库中来修复这个问题,从而修复漏洞。此外,我们将询问其 --is-bare-repository 函数以告诉我们是否为裸仓库,并依赖于它。

1
在 Linux 上尝试相同的操作... git config --local credential.helper "netrc -f /home/me/.netrc.gpg -v -d" ...然后我得到了 "git: 'credential-netrc' 不是一个 git 命令。请参阅 'git --help'"。 - sunny
4
这句话的意思是:curl -o c:\prgs\bin\git-credential-netrc https://raw.github.com/git/git/master/contrib/credential/netrc/git-credential-netrc 的目的是让你把 git-credential-netrc 复制到你的路径中( $PATH ),这样 git 才能调用 'credential-netrc'。 - VonC
嗯,在Windows 7电脑上,_netrc 对我没用,但是使用 .netrc 并在其中传递 --netrc 参数给 youtube-dl 就可以了。 - Iulian Onofrei
1
@GwynethLlewelyn 谢谢。我已经相应地编辑了答案。如果您发现任何其他过时的信息,请不要犹豫自行编辑。 - VonC
@aldokkani 抱歉回复晚了,我在工作。这个旧的(2013年)答案是针对Windows的,在当时它没有受益于良好的凭据助手(如Linux的凭据助手)。今天我不会使用它,因为现在有GCM4W:https://github.com/microsoft/Git-Credential-Manager-for-Windows。我已经编辑了Mark Longair的答案,添加了Linux更新的凭据助手:https://stackoverflow.com/posts/5343146/revisions - VonC
显示剩余3条评论

53

使用凭证存储。

对于 OS XLinux 上的 Git 2.11+,请使用 Git 的内置凭证存储

git config --global credential.helper libsecret

对于在Windows上的msysgit 1.7.9+:

git config --global credential.helper wincred

对于 OS X 上的 Git 1.7.9+,请使用以下命令:

git config --global credential.helper osxkeychain

3
我确信这是正确的方式,但不幸的是我遇到了一个错误:git: 'credential-gnome-keyring' 不是一个 git 命令。请参见 'git --help'。 - codepleb
3
在Linux上使用libsecret之前,您需要执行以下步骤:https://dev59.com/WVoV5IYBdhLWcg3wLsT5#40312117 - Lavamantis
1
还有一件事 - 如果您在Github上启用了2FA,您的密码将无法使用。但是您可以在Github“设置”页面上创建个人访问令牌,该令牌可作为您的密码使用。 https://github.com/github/hub/issues/822 - Lavamantis
3
安全问题:Windows凭据管理器会使明文密码对于任何已登录到您的Windows帐户的人都可访问。他们只需要向凭据管理器发送请求,例如printf "protocol=https\nhost=git.mycompany.com\n" | git credential-manager get更多详细信息在此处)。您应该始终使用 个人访问令牌 ,当然还要在GitHub帐户上启用2FA。 - cjs
1
简单但很棒的答案!这在我的 openSUSE 13.2 上直接奏效,尽管它看起来是一个相当老的安装。 - cchwala
显示剩余3条评论

46

有一种简单而古老的方法可以将用户凭证存储在HTTPS URL中:

https://user:password@github.com/...

您可以使用 git remote set-url <remote-repo> <URL> 命令来更改 URL。

这种方法的明显缺点是您必须以纯文本形式存储密码。 您仍然可以只输入用户名 (https://user@github.com/...),这样至少可以节省一半的麻烦。

您可能更喜欢切换到 SSH 或使用 GitHub 客户端软件。


2
用户名/密码可能需要进行编码,请参见https://stackoverflow.com/a/34611311/3906760。 - MrTux

43
你可以直接使用

git config credential.helper store

下次使用拉取或推送时输入密码,它将以明文形式存储在文件.git-credentials中(有点不安全,但只需将其放入受保护的文件夹中)。

就像这个页面上所述的那样:

git-credential-store


3
对于Git for Windows 2.7.3(2016年3月发布):https://github.com/git-for-windows/git/releases?after=v2.8.4.windows.1,应该使用`git config credential.helper manager`。 - VonC

23

对我来说并不明显,我需要先下载助手! 我在 Atlassian's Permanently authenticating with Git repositories 找到了 credential.helper 下载。

引用:

如果您想在OS X上使用具有凭据缓存功能的Git,请按照以下步骤操作:

下载二进制文件 git-credential-osxkeychain。

运行下面的命令以确保该二进制文件可执行:

chmod a+x git-credential-osxkeychain

将其放入目录/usr/local/bin中。

运行以下命令:

git config --global credential.helper osxkeychain

23
在 GNU/Linux 系统上,使用 ~/.netrc 文件也可以很好地工作:
$ cat ~/.netrc
machine github.com login lot105 password howsyafather

这可能取决于Git在HTTPS传输方面使用的网络库。


4
请确保还要运行命令 chmod 0600 ~/.netrc。该命令的作用是设置文件 ~/.netrc 的权限为只有当前用户可读写。 - poolie
我只想在这里留下一个链接,指向Ubuntu netrc manpage。我需要为另一个用户(/home/git/.netrc)创建它,然后更改所有权给该用户。 - zacharydl

23

只需要将登录凭据作为URL的一部分即可:

git remote rm origin
git remote add origin https://username:mypassword@github.com/path/to/repo.git

注意:我不建议使用这种方法,但如果你赶时间而且别的方法都行不通,你可以使用这个方法。


12
邮箱地址中的 @ 符号需要用 %40 替代,这样才能正常使用。 - Tarun Gupta
如果电子邮件地址中有一个“+”符号怎么办?我尝试了相同的转义,但推送时显示“未找到存储库”。 - killjoy
4
使用"%2B"代替"+"。 - Tarun Gupta
将密码以明文形式存储并且易于访问可能不是最优解决方案。 - reducing activity

16

你可以使用 Git Credential Manager(GCM)插件,它目前由GitHub维护。好的一点是,它将密码保存在Windows凭据存储中,而不是明文。

在项目的发布页面上有一个安装程序。这也会安装内置凭据管理器的官方版本Git for Windows。它允许GitHub(和其他服务器)进行两步验证。并且拥有一个用于最初登录的图形界面。

对于Cygwin用户(或已经使用官方Git for Windows的用户),您可能更喜欢手动安装。从发布页面下载zip包。提取包,然后运行install.cmd文件。这将安装到您的~/bin文件夹中。(请确保您的~/bin目录已添加到PATH环境变量中)。然后可以使用以下命令进行配置:

git config --global credential.helper manager

当Git向任何服务器进行身份验证时,Git将运行git-credential-manager.exe


3
任何登录您帐户的人都可以轻松访问密码的明文。他们只需要发送一个请求到凭据管理器,例如 printf "protocol=https\nhost=git.mycompany.com\n" | git credential-manager get更多细节在此)。您应该始终使用 个人访问令牌,当然还要在GitHub账户上使用双重身份验证。 - cjs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接