git要求提交子模块修改内容

时间:2017-07-01 12:57:30

标签: git git-submodules youcompleteme

最近,我使用以下命令更新了vim配置存储库中的子模块:

git submodule update --recursive --remote

当我打电话给git status时,我得到了这个:

On branch master
Your branch is ahead of 'origin/master' by 5 commits.
  (use "git push" to publish your local commits)
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)

        modified:   .vim/pack/starter-pack/start/YouCompleteMe (modified content)

no changes added to commit (use "git add" and/or "git commit -a")

然后我跟随了具有修改内容的子模块链#34;并发现唯一的修改是未经跟踪的子模块提交:

On branch master
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   vendor/bottle (new commits)
        modified:   vendor/jedi (new commits)
        modified:   vendor/waitress (new commits)

no changes added to commit (use "git add" and/or "git commit -a")

这些子模块的主分支(瓶子,绝地,女服务员)都在其远程起源的主分支之后,所以我认为git submodule update所做的不仅仅是每个仓库的拉动起源,而是找到父仓库的适当版本需要。

为什么即使git使用(new commits)标记此回购标记,如果它是父模块所需的确切提交?那里发生了什么?

1 个答案:

答案 0 :(得分:1)

这里发生的事情是你的超级项目现在不一致了。具体来说,您的超级项目需要提交 gitlinks

你应该像往常一样添加新的gitlinks(git add)并提交(像往常一样)。然后,您可以像往常一样推送新提交。

子模块意味着超级项目

子模块只是一个Git存储库,由另一个Git存储库直接使用。在这种情况下,子模块本身只是一个普通的Git存储库:它不知道这个其他Git存储库。另一个存储库是我们称之为 superproject 的存储库,它 知道子模块。

任何Git存储库都需要一个带有一些数据的.git目录

通常,创建Git存储库的方法是从其他地方克隆它:

git clone http://...

或其他什么。或者,您可以在目录中运行git init。无论哪种方式,最终都会得到一个.git目录,其中包含Git存储库本身。在此.git中,您通常会定义一个名为origin远程。这是一个简短的名称(具体来说,名称origin!),用于记录网址,这是您在上面git clone提供的网址。该URL甚至可以指向您自己的存储库,例如GitHub。

(如果您从其他人的存储库开始,然后决定在GitHub上创建自己的存储库,您甚至可能有两个存储库。通常您会命名自己的存储库{{1} }和另一个origin,但就Git本身而言,这些只是任意名称。我们都同意upstream的唯一原因是这是名称origin创建的对我们来说,当我们第一次运行git clone时。)

无论如何,git clone url目录中的数据包括以下内容:

  • .git
  • 的网址
  • 任何分支的名称,以及这些分支标识的提交哈希ID。
  • 同样,标签的名称及其提交。
  • 当前提交:确切地说,在存储库中检出了什么?这可能是分支名称,在这种情况下,存储库是在分支上,或者它可能是原始提交散列ID,在这种情况下,存储库位于&# 34;独立的HEAD&#34;模式。

如果超级项目创建子模块怎么办?

超级项目需要了解每个子模块的几个方面。首先,超级项目有一个名为origin的文件。在此.gitmodules文件中,您将找到每个子模块的 URL 。您还可以找到每个子模块的路径

the gitmodules documentation中描述了此文件的确切形式和内容。引用它,假设它说:

.gitmodules

这意味着当您克隆超级项目,然后运行[submodule "libfoo"] path = include/foo url = git://foo.com/git/lib.git 时,您的Git将知道它应该运行git submodule init - url 部分 - 克隆进入git clone git://foo.com/git/lib.git目录:路径部分。

这个谜题中缺少一个关键部分。在你的Git将另一个Git克隆到include/foo后,在子模块中检出哪些提交?

在大多数普通存储库中,这不是一个大问题。检查了什么提交?我不知道,我只是跑include/foo,对吧?这让我得到分支git checkout master上的最新提交,这就是我想要的。

超级项目和子模块不会以这种方式工作。当我使用我的超级项目的子模块时,我在子模块中围绕一个特定的提交构建我的超级项目代码。例如,我可能会专门依赖其他人的master库,因此我会进入子项目并运行v3.4.1以查看特定的标记

理想情况下,我可能有我的超级项目记录标记(这会很好,而gitlinks 应该允许这样做,但目前他们不会这样做。) 1 但是Git中的标签实际上只是一个特定提交的人类可读名称。标记git checkout v3.4.1可能是提交v3.4.1或其他类似的名称。那个 - 丑陋的哈希ID - 实际上是进入gitlink的。

gitlink本身存储在每次提交中,就像常规文件存储在每次提交中一样。如果我在超级项目中使用新的或修改过的feeddadac0ffee...文件进行新提交,则新版本的README将进入Git存储库,新提交将引用新的README。之后的每次提交都会继续引用新的README

同样适用于gitlink:如果我的README引用了子模块的include/foo的哈希ID,则此处的每个提交都有一个gitlink条目,其中包含:&#34;当您检查此提交,您还应该进入v3.4.1子模块并检查哈希ID include/foo&#34;。

1 如果有人想尝试添加它,我认为有一种方法可以做到这一点,甚至可能有点向后兼容:像往常一样存储原始哈希ID,然后是NUL byte,后跟引用名称。不了解新类型gitlink的旧Git可以直接使用哈希ID,而较新的Git可以检测并使用该名称。无论如何,在从SHA-1到Git未来使用的哈希过渡中,Gitlink条目都需要进行类似的更改,所以这可能是添加它的好时机。

如果子模块的所有者发布新版本该怎么办?

所以,我用feeddadac0ffee...测试了我的超级项目,一切正常。大!但是现在负责这个v3.4.1库的人已经更新了他们的代码并发布了版本include/foo。这个新版本有一些新功能,我想使用它。

作为超级项目的所有者,我现在应该进入我的子模块v3.4.2然后git fetch。 (这可能不是git checkout v3.4.2,也许是哈希ID feeddadac0ffee。)然后我应该回到我的超级项目,进行使用新子模块所需的任何更改,测试一切,并提交。

当我进行新提交以使用子模块的deadcabbadcab005e...时,我不仅应该提交我的更改。我还需要更新我的 gitlink 。由于我已经完成v3.4.2 - 或git checkout deadcabbadcab005e,这是完全相同的事情,实际上在子模块中,我所要做的就是在我的超级项目中git checkout v3.4.2。这会将更新的gitlink添加到我的索引中,这样当我运行git add include/foo时,我会记录 new gitlink以及其他更改。

这会产生一个新的提交,我现在可以推送我的提交,如果有其他地方我也保留我的超级项目(在GitHub或其他)。