排除子项目提交Git

时间:2019-09-30 15:03:33

标签: git git-submodules

如何排除Subproject commit ....,我没有在子模块中进行任何更改,仅从远程存储库中提取更改!我认为在创建子模块时,我在主存储库中提交了一些不需要的东西。有什么想法吗?

1)当我在主存储库中创建子模块 git diff 时,也显示了

submodule-path:
    Subproject commit 5a8162ff9a602deb96956854346988e1ee45672e

我犯了这个

2)然后有人提交了子模块,因此它具有以下日志

2ff89a2bfcaa0 last commit
5a8162ff9a602d  first commit

3)我用

更新了子模块

git submodule update --remote --merge

4)现在显示 git status

modified:   submodule-path (new commits)

但是我没有在子模块中进行任何更改,仅拉出了最后的远程更改!我需要最后一次更改

git diff 显示

diff --git a/submodule-path b/submodule-path
index 5a8162f..2ff89a2 160000
--- a/submodule-path
+++ b/submodule-path
@@ -1 +1 @@
-Subproject commit 5a8162ff9a602deb96956854346988e1ee45672e
+Subproject commit 2ff89a2bfcaa014885a70b0da86e997ecd8d0688

3 个答案:

答案 0 :(得分:1)

更新:

这不是错误。子模块就是以这种方式工作的。

主存储库不跟踪子模块的文件。它仅跟踪子模块的url和提交ID(子模块在特定点的状态)。

Quote from Starting with Submodules in book Pro Git

  

尽管sbmodule DbConnector是工作目录中的子目录,但是Git会将其视为子模块,并且当您不在该目录中时,它不会跟踪其内容。相反,Git将其视为来自该存储库的特定提交

由于您使用git submodule update更新了模块,所以您必须进行更改(实际上是更新的提交ID)。如果您不想更新子模块的跟踪信息,只需不要在开始时使用git submodule update或放弃更改。


很可能子模块是HEAD分离的。进入子模块,重置子模块以修复HEAD分离状态。

# Do this in the submodule
git reset --hard origin/master

然后将子模块更新为最新提交。

# run in the project's root, not the submodule's
git submodule update --remote --merge

答案 1 :(得分:1)

首先,让我们尝试在此处弄清楚一些事情。很难,因为当您自己使用Git时,它很复杂。当您添加第二个Git存储库时,git push您自己的提交,以及git fetch从中其他人的新提交, 也很复杂。子模块不过是一个第三个Git存储库,而那个第三个Git存储库具有一个第四个Git存储库,您可能会git push自己提交给它,并且从中您可以git fetch别人的新提交。因此,我们正进入一种情况,即至少有四个 Git存储库,所有这些存储库在某种程度上都是相互独立的。

我们可以尝试绘制图片,但即使图片也会有些混乱。我们如何保持四个存储库的整齐? Git有两个名字:您直接与两个人打交道。一个是 superproject ,它是您运行git diff并看到以下内容的地方:

diff --git a/submodule-path b/submodule-path
index 5a8162f..2ff89a2 160000
--- a/submodule-path
+++ b/submodule-path
@@ -1 +1 @@
-Subproject commit 5a8162ff9a602deb96956854346988e1ee45672e
+Subproject commit 2ff89a2bfcaa014885a70b0da86e997ecd8d0688

另一个是子模块本身:如果您cd submodule-path并运行各种Git命令,您将看到它是一个普通的Git存储库。唯一不寻常的是它几乎总是处于“分离头”模式。

您的超级项目Git可能有一个origin。那是一个存储库,从技术上讲,您可以在此Git中使用它的简称来引用另一个存储库,您可以git push在超级项目中提交到该存储库。您需要在超级项目中进行提交,然后将这一新提交git push提交到origin。超级项目提交到底包含什么?我们待会儿见。

您的子模块Git 有一个origin。那是另一个不同的其他Git存储库:这幅画得不是很好的第四张Git。我不清楚您是否要将提交发送到第四个存储库。您要做可能是想从该存储库中获得一个提交。有多种解决方法,包括使用git submodule update --remote,也许还有其他选择。我更喜欢cd submodule-path并直接在子模块Git中开始工作 ,因为这样可以将问题减少到您已经知道该怎么做的事情:根据出现的新提交操作一个本地Git存储库在其origin中。

假设您只想在子模块中获取一些新的提交

在这种情况下,您可以:

cd submodule-path           # begin working in your submodule
git fetch                   # update origin/*
git checkout origin/master  # get a detached HEAD on the desired commit
                            # (this assumes `origin/master` is the
                            # desired commit; it's impossible for me
                            # to know which commit you desire)

,现在子模块具有所需的提交作为其分离的HEAD。这里git push没什么可做的:驻留在该存储库中的所有提交都是从该子模块的origin的Git获得的提交。

(使用git submodule update --remote可以为您完成cd submodue-pathgit fetchgit checkout origin/master,而无需更改您自己的工作目录。整个操作在其子目录中运行shell,这样所有cd操作都不会影响您的位置,这似乎是您的git submodule update --remote --merge所做的:无需进行新的合并提交,因此只需切换到由标识的提交即可。 origin上的一些分支名称。)

但是如果您需要在子模块中进行新的提交...

在这种情况下,您可能希望将子模块强制在分支上,以便在更正常的工作流程中工作。然后,您可能想要例如git checkout master,然后执行各种命令。最终,您可能会在子模块存储库中进行新的提交,您需要git push到子模块的origin存储库 中,以便其他人可以也能够获得此提交。

您可以将子模块保留在其分支上。子模块的分支与超级项目Git无关:超级项目Git仅关心在子模块中检出了 commit 的情况。 (这就是为什么在上述较早的情况下,我们只需切换分离的HEAD。)

现在,子模块Git在正确的提交上,您必须进行新的超级项目提交

这时,您可以cd从子模块退回到超级项目。您会在git diff中看到与上面引用的内容完全一样的内容,并且git status会说:

modified:   submodule-path (new commits)

这不一定意味着子模块存储库中的任何 new 提交都不在子模块存储库的origin中。这仅表示子模块存储库处于提交状态(无论其是否为HEAD,是否为分离的),而不是当前超级项目状态表示应 处于打开状态的提交。

这里的问题是,在某种程度上,当前的超级项目提交存在缺陷。 是正确的,但现在已不再适用,就像如果您在本地编辑文件README.md时当前的超级项目提交有缺陷。这意味着您需要在超级项目中 进行新的,更正的提交。超级项目Git将根据超级项目存储库索引中的内容进行新的提交,因此您现在需要更新索引。

如果您更改了README.md文件,则更新索引的方式是:

git add README.md

但是您更改的不是README.md文件。相反,它是子模块哈希ID。因此,您需要在索引中记录新的哈希ID。您这样做的方式是:

git add submodule-path

这通过运行cd submodule-path; git rev-parse HEAD从子模块中获取哈希ID,以获取原始哈希ID(在git diff中显示的原始哈希ID),并将该哈希ID填充到索引中。现在git diff(将索引与您的工作树进行比较)不会再显示这些Subproject commit行,而git diff --cached(将当前行进行比较(超级项目)提交到索引-显示出来。现在git status会说这些“新提交”已准备好提交,而不是尚未提交阶段。

此时,您可以git add其他任何超级项目文件(如果索引中需要更新的文件)。然后:

git commit

超级项目中的

将进行新的提交,该提交将记录您在子模块路径上运行git add时放入超级项目的索引中的哈希ID。

您(本地)已完成更新,但是这里有一些需要考虑的事情

请注意,超级项目中的每个提交都会在子模块中记录哈希ID。每次您git checkout进行一次不同的超级项目提交时,不仅将正确的超级项目文件提取到(超级项目)索引和(超级项目)工作树中,还将提取记录的子模块哈希ID到(超级项目)索引中。默认情况下,它不{em> cd进入子模块,并git checkout通过其哈希ID进行特定的提交。您可以使用设置更改此设置,也可以将--recursive添加到git checkout;或者,您也可以运行git submodule update,告诉您的Git一次cd进入每个子模块,并告诉git checkout当前记录在(超级项目)索引中的哈希ID。

有时,您需要将您在超级项目中所做的新提交git push {对超级项目的origin}进行origin,以便新提交及其新记录的哈希ID出现在超级项目git push的Git中。您可以随时执行此操作,但是假设您 did 在您的子模块中 进行了新提交,而您尚未在子模块本身中使用origin进行发送这些新提交到子模块的git fetch。在这种情况下,您在超级项目中所做的新提交记录了仅存在于本地子模块存储库中的提交的哈希ID。如果有人运行origin到超级项目Git的git push,他们将从您发送的新提交中获得此新的哈希ID,但不能查找在< em>其子模块的克隆。因此,如果确实进行了新的子模块提交,通常最好先git push进行它们的提交,然后然后 {{1}}进行新的超级项目的提交。

(如果您未提交任何新的子模块,则这里没有问题。)

答案 2 :(得分:0)

运行命令git submodule update -f --init应该可以解决您的问题,这会将您的子模块重置为远程HEAD

相关问题