Git子模块的URL中没有包含用户名?

67

我有一个使用多个子模块的git仓库,这会在父仓库中创建一个跟踪文件.gitmodules。但是,有其他开发人员想要在此仓库上进行工作并检出子模块。但目前远程子模块仓库的URL包含我的用户名;在.gitmodules文件中它像这样:

[submodule foo]
  path = sub/foo
  url = https://myuser@example.com/git/foo.git

显然其他开发人员不能像myuser一样从example.com获取(他们没有我的密码); 我应该如何拥有一个主存储库,让多个开发人员可以拉取/推送,并允许他们单独访问子模块(在子模块主机服务器上设置他们所有共享的单个用户名将起作用,但这不是良好的用户管理)?


你拥有那台服务器吗?你看过 gitolite 吗?你能使用公共托管吗? - Cascabel
@Jefromi 目前使用Bitbucket进行托管,不过gitolite看起来也可以用于自主托管。 - MidnightLightning
请查看此链接:http://blog.tremily.us/posts/Relative_submodules/ - marknuzz
9个回答

48

如果我理解正确,您正在使用HTTPS上的HTTP基本身份验证,以允许特定的开发人员访问存储库。在这种情况下,您可以提交一个类似于 .gitmodules 的文件:

[submodule foo]
  path = sub/foo
  url = https://example.com/git/foo.git

...即不需要用户名,然后告诉每个开发者在他们的~/.netrc文件中放置他们的用户名和密码。如果您使用的是Windows,则可以在这里找到一些好建议。一个简单的.netrc文件可能如下所示:

machine example.com
  login myusername
  password areamandyingtotellsomeonehiscoolpassword

更新:一种不涉及使用 .netrc 的替代方法如下:

同样,从 .gitmodules 中删除 URL 中的用户名并提交和推送该更改。当有人克隆存储库时,他们首先运行:

git submodule init

...这将设置配置选项submodule.sub/foo.url.gitmodules中的URL。 但是,在执行git submodule update之前,init步骤不会将子模块克隆到位,因此您可以执行以下操作:

git config submodule.sub/foo.url https://myuser:mypass@example.com/git/foo.git

...然后:

git submodule update

为了使用正确的用户名克隆子模块。请注意,这样您用于HTTP身份验证的用户名和密码将存储在您的git配置中。


这对于系统范围的配置非常好;在极端情况下,如果您访问Git仓库的用户名与其他访问的用户名不同,则不是理想的选择。我发现从仓库URL中删除用户名会提示输入用户名和密码,所以这样做是可行的,但并不理想。如果Git允许类似于“remote.origin.user”配置选项的东西就好了…… - MidnightLightning
你真的会使用.netrc进行其他身份验证吗? - Mark Longair
我不知道别人是否会这样做,但对我来说,理想的解决方案是完全基于git及其配置的,而无需修改操作系统的其他部分。因为用户可能正在将该文件用于与之冲突的其他目的。 - MidnightLightning
@MidnightLightning:我在我的答案中添加了一个替代方案。如果可行的话,使用SSH通常比使用HTTPS更加灵活。 - Mark Longair
1
@BobbyA - 当你使用 git config 来设置某些配置时,它会修改 .git/config。这是一个单独的配置文件,具有不同的部分和含义,不同于 .gitmodules。在此示例中的 .git/config 中将有一个名为 [submodule "sub/foo"] 的部分,其中包含 url = https://myuser:mypass@example.com/git/foo.git。希望这可以帮助你。 - Mark Longair
显示剩余2条评论

34

实际上你可以在.gitconfig文件中指定一个"相对"路径来指向子模块:

[submodule foo]  
path = sub/foo  
url = ./git/foo.git

这个 URL 将引用与代码库本身相同的主机(https://example.com)。


3
它不是使用相同的主机,而是使用相同的URL,例如:ssh://user@example.com:29412/mainmodule/submodule - Pratik Anand
如果主项目的URL是https://user@host.org/team/project.git,而子模块的URL是https://user@host.org/team/submodule.git,你可以将.gitmodule文件中的子模块URL设置为`../../team/submodule.git`,这对我来说有效。你也可以尝试缩短路径,像这样`../submodule.git`。使用命令`git submodule syncgit config -e`可能会对你有所帮助。 - Gregy8
如果主项目的URL是https://user@host.org/team/project.git,子模块的URL是https://user@host.org/team/submodule.git,你可以将.gitmodule文件中的子模块URL设置为`../../team/submodule.git`,这对我来说有效。你也可以尝试将路径缩短为`../submodule.git`。使用`git submodule syncgit config -e`可能会对你有所帮助。 - undefined

29

这个帖子对我很有帮助,但我想补充一点,就是在修改.gitmodules文件内容后,你需要执行以下命令,这样git才能识别它:

这个线程对我有帮助,但我要补充的是,在修改.gitmodules文件内容后,您需要执行以下命令,以便Git能够识别它:

git submodule sync

1
这就是解决我的问题的方法。谢谢! - Vanessa
1
这也为我解决了问题。 - Zack
我无法弄清楚为什么在将我的子模块更改为SSH后,它仍然要求HTTP凭据,也许是.git缓存中的某些问题。无论如何,这个方法有效! - undefined

17

Antonk的答案对于团队来说行不通,因为个人的.gitconfig或.git/config不受版本控制。

然而,它确实让我尝试了一下.gitmodules中的URL。

[submodule foo]
path = sub/foo
url = ../foo.git

对于我来说有效,假设子模块仓库与父级仓库在同一个url中。


2
运行得非常好!除了在超级模块克隆命令行上,没有任何主机、端口或用户名。 - StellarVortex

6
你可以使用SSH身份验证。
只需替换这个。
[submodule foo]
  path = sub/foo
  url = https://myuser@example.com/git/foo.git

使用此功能

[submodule foo]
  path = sub/foo
  url = git@example.com:git/foo.git

9
你仍在指定一个用户;现在不再是假设其他维护者有myuser帐户的密码,而是假设他们拥有git用户帐户的密码,对吗? - MidnightLightning
2
没有。有些 Git 服务器只需查找您的公钥以匹配您的用户。在这些服务器中,有 Github、Atlassian Bitbucket Server(曾用名 Stash)和 Atlassian Bitbucket(SaaS 版本)。这很方便,因为您不必担心 URL 中的用户名问题。 - rcomblen

6
您可以尝试使用.insteadOf,例如:
git config --global url."ssh://YOUR_USERNAME@gerrit.foobar.com:29418/".insteadOf "ssh://gerrit.foobar.com:29418/"

每位开发人员都需要在他们工作的每台计算机上进行一次此操作。

这个的好处是你只需要做一次,然后所有东西都可以正常工作,包括 "git clone --recurse-submodules"。但是它需要 "YOUR_USERNAME" 字符串保持一致。 - StellarVortex
如果你在CI上进行克隆操作,你也可以使用env:GIT_CONFIG_PARAMETERS="'url.https://${SECRET_TOKEN}@github.com.insteadof=ssh://git@github.com'"。注意额外的引号:' - nouveu

2

我在使用Gerrit(通过ssh)时遇到了这个问题。
删除用户名后问题得到解决,
现在我的.gitmodules看起来是这样的:

[submodule "sub/module1"]
    path = sub/module1
    url = ssh://servername:29418/module1

这应该是这样工作的吗?它在Windows上可以工作,但在Linux上不行。 - BlueMagma
实际上我不确定它是否应该这样,但在Windows和Linux上对我有效。这可能取决于ssh后台正在做什么-由于您没有给出用户,它将不得不使用默认用户。 - Roman
我了解更多相关信息:实际上,为了使其正常工作,您的会话用户名必须与ssh用户名相同。或者为了绕过这个问题,您必须配置.ssh/config以针对每个ssh服务器使用特定的用户名。 - BlueMagma

2

修改你的.gitmodules文件,从url中删除用户名:

最初的回答

[submodule foo]
  path = sub/foo
  url = https://example.com/git/foo.git

最初的回答:
最后,需要注意的是:
cd foo/
git submodule init
git submodule update

# Will be prompted to provide username and password

-2

或者您可以使用HTTPS代替SSH,这将提示您输入用户名和密码:

enter image description here


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