排除子项目提交 Git

Exclude Subproject commit Git

我怎样才能排除 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 状态 显示

modified:   submodule-path (new commits)

但我在子模块中什么也没做,只拉取了最后的远程更改!我需要最后的更改

git 差异 显示

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

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

更新:

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

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

Quote from Starting with Submodules in book Pro Git

Although sbmodule DbConnector is a subdirectory in your working directory, Git sees it as a submodule and doesn’t track its contents when you’re not in that directory. Instead, Git sees it as a particular commit from that repository.

由于您使用 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

首先,让我们试着弄清楚这里的一些事情。这很难,因为当你自己使用 Git 时,它会很复杂。当您添加第二个 Git 存储库时 – 您 git push 自己的提交,以及您 git fetch 其他人的新提交 – 是也很复杂。一个子模块只不过是一个 third Git 存储库,而第三个 Git 存储库有一个 fourth Git 存储库,您可能 git push 您自己的提交,以及您可能 git fetch 其他人的新提交。因此,我们正跳入至少有 四个 Git 个存储库的情况,所有这些存储库都有些相互独立。

我们可以尝试画图,但即使是图画也会有点模糊。我们如何保持 四个 存储库的正常运行? Git 有其中两个的名字:您直接与之合作的两个,您自己。一个是 超级项目,这是您 运行正在 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 存储库。唯一不寻常的是它几乎总是处于 "detached HEAD" 模式。

您的超级项目 Git 可能有一个 origin。那是一个存储库——嗯,从技术上讲,你可以在这个 Git 中使用一个短名称来 引用 另一个存储库——你可以 git push 提交你在超级工程。您 需要在超级项目中进行提交,然后 git push 这个新提交到 origin。这个超级项目的提交到底是什么?待会见。

您的子模块 Git 有一个 origin。那是一个 不同 其他 Git 存储库:第四个 Git 在这张画得不太好的图片中。我不清楚是否要将提交发送到第四个存储库。您 do 大概想要 get 提交 from 那个存储库。有多种方法可以解决这个问题,包括使用 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,所有这些都不需要改变你自己的工作目录。整个操作运行s 在其自己的子 shell 中,因此这些 cd 操作中的 none 会影响您的位置。这似乎是您的 git submodule update --remote --merge 所做的:没有必要进行新的合并提交,因此它只是切换到由 origin 上的某个 b运行ch 名称标识的提交。)

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

在这种情况下,您可能想要强制子模块在 b运行ch 上,以便您在更正常的工作流程中工作.然后你可能想要 git checkout master 例如,然后执行各种命令。最终你可能会在你的子模块存储库中完成一个新的提交,你将需要 git pushorigin 存储库 of 子模块,以便其他人们也将能够获得此提交。

您可以将子模块留在其 b运行ch 上。子模块的 b运行ch 与超级项目 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

这通过 运行ning cd submodule-path; git rev-parse HEAD 从子模块中获取哈希 ID 以获取原始哈希 ID——显示在 git diff 中的那个——以及哈希 ID 的内容进入索引。现在 git diff——将索引与你的工作树进行比较——不会 显示这些 Subproject commit 行,但是 git diff --cached——比较当前(超级项目)提交给索引——显示它们。现在 git status 会说这些 "new commits" 已准备好提交,而不是 not-yet-staged-for-commit。

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

git commit

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

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

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

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

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