如何将更改从我自己的存储库的子模块推送到其他人的存储库(我是合作者)?

双原子灾难

所以我有自己的存储库,我们称之为“我的”,它包含一个子模块存储库“他们的”。我可以访问他们的远程存储库,因此我可以直接将更改推送到它。

我正在尝试将我对“他们的”所做的更改推送回他们的远程 GitHub 存储库,但我似乎无法让它工作。我可以将更改推送到我在 GitHub 上的远程存储库“我的”,并且可以看到对“他们的”的新提交。但是当我访问他们的 GitHub 时,它没有添加最新的提交。

子模块不应该只是常规存储库,在另一个内部带有一些额外的元数据吗?如果是这样,为什么“他们的”目录中的“git push”不起作用?我试过从“他们的”内部提交和推送,然后从“cd ..”和“我的”内部提交/推送,但它也不起作用。

我已尝试此处列出的步骤:Git submodule push无济于事。我只能假设,因为我正在尝试推送到我不拥有的存储库,所以还需要做其他事情吗?

~/Mine$ git remote -v                                                                                                                                                                                                        
origin  https://github.com/myUser/Mine.git (fetch)                                                                                                                                                                                
origin  https://github.com/myUser/Mine.git (push) 

~/Mine/Their$ git remote -v                                                                                                                                                                                                    
origin  https://github.com/theirUser/Theirs.git (fetch)                                                                                                                                                                                        
origin  https://github.com/theirUser/Theirs.git (push) 
周二

你是对的:子模块本身就是一个存储库。这意味着您可以cdchdir进入子模块并以与使用任何其他 Git 存储库相同的方式开始使用它,包括运行git fetchgit checkoutgit commit等。

使子模块成为子模块的原因是,位于子模块上方某处的其他 Git 正在控制子模块,通常是通过在子模块中运行这会将子模块置于 Git 所谓的分离 HEAD模式。(控制 Git 是超级项目。)git checkout hash-id

这种“分离头”模式有点棘手。可以在这种模式下进行新的提交,但是当您这样做时,大多数普通方法都无法找到它们它们暂时很容易通过特殊名称找到HEAD,但是这个特殊名称HEAD会被超级项目强行调整,它会chdir进入子模块并再次运行,丢失1你所做的提交。git checkout hash-id

要将您在子模块 Git 存储库中所做的提交发送到某个其他 Git 存储库,您必须其他Git 存储库中为这些提交指定一个名称通常,这意味着给他们一个分支名称。您的存储库中使用分支名称没有硬性要求,因为您可以运行:

git push <remote-or-URL> HEAD:<name>

通过 name 将子模块存储库中标识的提交发送HEAD到另一个 Git,并礼貌地要求它创建或更新其名称name以指向该提交。但是大多数人不喜欢使用/使用分离的 HEAD 模式。

一般来说,这意味着要在充当某些超级项目的子模块的 Git 存储库中工作,您应该使用以下顺序:2

  1. 进入子模块。从这里到第 3 步,您只需将它用作常规 Git 存储库即可。

  2. 通过选择分支名称git checkout或创建指向当前提交分支名称退出分离的 HEAD 模式需要注意的是,如果你选择一些现有的分行名称,这可能是一个不同的从提交当前提交。或者它可能与当前提交相同

    请记住,超级项目存储库早些时候告诉这个 Git:使用这个原始提交,通过它的哈希 ID进入分离的 HEAD 模式。我们现在正在退出分离 HEAD 模式,这需要选择或创建分支名称。如果你选择一些现有的分支名称,你就会被分支名称选择的任何提交所困扰。但是,如果您正在子模块存储库中开发新的提交,您可能需要一个分支名称来记住它们。

  3. 现在,以通常的方式进行新的提交。使用git push通常的方式。提交将或不会以提交执行或不执行的通常方式进入接收存储库。如果他们确实进入了接收存储库,则会以通常的方式创建或更新该存储库的分支名称

  4. 一切完成后,退出子模块存储库,返回超级项目存储库。现在是时候在superproject 中进行新的提交了

我已经多次提到超级项目 Git 一直控制着子模块 Git。chdir进入子模块 Git 并运行. 这里的关键来自两部分:git checkout hash-id

  • 超级项目 Git 什么时候对子模块做这个?
  • 超级项目 Git哪里获取原始哈希 ID?

第一个问题的答案很复杂:git submodule update是否,但并非总是如此;3 git checkout --recursive这样做(总是);根据选项和设置,各种其他操作有时也可以做到。也就是说,它不会发生,除非和直到你问这样的事发生,但它并不总是很明显,你问这样的事发生。我们要做的是确保在第二点再次发生之前解决第二点。

第二个问题的答案——超级项目 Git 从哪里获得原始哈希ID——是它从超级项目中的提交中获取它但是您已经在子模块中进行了新的提交,并将其提交到上游到其他一些 Git 存储库,所以现在是时候在superproject 中进行新的提交,以记录正确的哈希 ID,即新的哈希 ID提交您在子模块中所做的。

与往常一样,任何提交都不能更改;和往常一样,Git索引中的任何内容(又名staging area进行新的提交当您提取一些现有提交时,Git 会将该提交中的文件读取到索引/暂存区中。如果存储库充当某个子模块的超级项目,则此步骤还会从提交中读取所需的哈希 ID(在该子模块中)到索引中。由于这不再是所需的哈希 ID,您现在的工作是将新的哈希 ID放入索引中。

在超级项目中执行此操作的命令是git add. 与往常一样,git add将内容写入索引。对于普通文件,它将该文件的副本写入索引。4但是,对于子模块,它:

  • 进入子模块片刻;
  • 那个混帐:什么是原始哈希ID为提交你确定HEAD( git rev-parse HEAD);
  • 将生成的哈希 ID(无论它是什么)填充到超级项目 Git 的索引中,在该子模块的插槽中。

无论子模块是否处于分离HEAD状态,这git rev-parse HEAD都有效,因为始终返回当前提交的原始哈希 ID。

因此, after git add path/to/submodule选择的提交(实际上是制作和推送的)的哈希 ID现在记录在超级项目索引中。您的下一次提交将记录原始哈希 ID。

假设其他一切都准备好了,您现在可以运行git commit以在超级项目中进行新的提交(这大概是,并且一直处于附加 HEAD 状态,在某个分支名称上)。一旦你提交了这个新的超级项目,你就可以git push像往常一样准备好了

请注意此处步骤的仔细排序:

  1. 进入子模块。
  2. 为简单起见,在子模块中的分支上进行提交,但是无论您如何进行提交都可以。
  3. 发送这些提交到哪里它是人们从克隆子模块,使Git有他们。此步骤需要在其他 Git 中设置分支或标签名称。
  4. 现在其他人可以访问子模块origin存储库中的提交,在 suprerproject 中创建和推送一个提交,该提交引用子模块提交的原始哈希 ID。

由于 Git 的分布式特性,可以在您的子模块中进行提交但将其推送到任何地方,然后在您的超级项目中进行提交推送它。任何获得这个新提交的人都会得到一个提交,该提交通过原始哈希 ID 指向一个提交,他们不仅没有,而且甚至无法获得. 所以第 3 步(“使提交对所有人可用”)必须push在第 4 步之前发生。(第 4 步中的“进行提交”可以更早发生——注意不要推送它,并用任何更新的提交重做它hash,如果子模块提交因任何原因必须重做。)


1失去这里的意思是“很难找到”。在提交本身不会消失的时候了:它们具有相同的宽限期,其他丢失的commit得到,你可以使用子模块Git的HEAD引用日志找到他们,以同样的方式找到丢失提交任何资料库,因为子模块刚毕竟,另一个存储库。

2因为 Git 是一组工具,而不是预先打包的解决方案,所以还有很多其他方法可以实现您的目标。这只是一种非常灵活的方式。

3特别是git submodule update有很多更新模式使用一些参数,您可以直接git submodule update检查子模块中名称,从而首先生成一个附加的 HEAD(而不是分离的 HEAD)!这是脚注 2 所指内容的一部分。的详细工作git submodule update非常复杂,所以我试图在这个答案中避免这些变体。

4从技术上讲,它用正确的文件内容写出一个blob 对象——或者如果可能的话,不改变地重用一些现有的 blob 对象——然后将 blob 对象的哈希 ID 写入索引,而不是实际的文件内容。但效果好像Git的复制该文件到索引,只要你不坐下来的水平git ls-files --stagegit update-index

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何将更改推送到在我的存储库中提高了PR的其他人的远程分支机构?

防止其他人强行推送到我的Git存储库

Github如何将我的存储库授权给其他人

如何将子模块更改推送到另一个存储库

如何要求其他人在gitlab中合并我的存储库

在我创建的存储库中提取其他人上载的文件或文件夹

我可以在存储库中提交对其他人的拉取请求的提交吗?

如何连接到我的 Github 存储库并通过 VScode 将更改推送到存储库?

我如何将提交推送到已经从本地存储库推送到 git 的 heroku?

如何将 SQL Server 示例数据库包含在我的 .NET 项目中以发送给其他人?

如何将我的git存储库推送到dokku?

Github将更改推送到其他人的分支

更新更改时出错:不安全的存储库...由其他人拥有

如何查找除我和其他开发人员以外的其他人对库所做的所有更改

如何将其他git存储库中特定文件的更改应用于我自己的仓库

错误地在我的 Azure Devops 团队的其他人的分支中工作。对将我的更改推送到服务器感到困惑

将 git 分支推送到其他存储库

如何将主干中其他人所做的更改更新到我在分支机构中的本地工作副本?

为什么我自己在git上推送的代码会像其他人一样出现?

如何将收藏与剧本一起保存并推送到自己的 github 存储库?

如何将远程存储库添加到我自己的git存储库中

无法将提交推送到我的git存储库

为什么我使用StickyGridHeaders库得到了NullPointerException,而其他人也使用相同的库呢?

是否可以将冲突的代码推送到git并让其他人解决它?

如何将本地git存储库推送到svn

如何将文件推送到存储库中的目录

当存储库更改不在本地计算机中时如何将代码推送到远程存储库

我如何从父级到子级存储库更改git子模块?

将git子模块更改推送到我自己的仓库中