排除子项目提交 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-path
和git fetch
和git checkout origin/master
,所有这些都不需要改变你自己的工作目录。整个操作运行s 在其自己的子 shell 中,因此这些 cd
操作中的 none 会影响您的位置。这似乎是您的 git submodule update --remote --merge
所做的:没有必要进行新的合并提交,因此它只是切换到由 origin
上的某个 b运行ch 名称标识的提交。)
但是如果你需要在子模块中进行新的提交...
在这种情况下,您可能想要强制子模块在 b运行ch 上,以便您在更正常的工作流程中工作.然后你可能想要 git checkout master
例如,然后执行各种命令。最终你可能会在你的子模块存储库中完成一个新的提交,你将需要 git push
到 origin
存储库 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
新的超级项目提交。
(如果你没有提交任何新的子模块,这里没有问题。)
我怎样才能排除 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-path
和git fetch
和git checkout origin/master
,所有这些都不需要改变你自己的工作目录。整个操作运行s 在其自己的子 shell 中,因此这些 cd
操作中的 none 会影响您的位置。这似乎是您的 git submodule update --remote --merge
所做的:没有必要进行新的合并提交,因此它只是切换到由 origin
上的某个 b运行ch 名称标识的提交。)
但是如果你需要在子模块中进行新的提交...
在这种情况下,您可能想要强制子模块在 b运行ch 上,以便您在更正常的工作流程中工作.然后你可能想要 git checkout master
例如,然后执行各种命令。最终你可能会在你的子模块存储库中完成一个新的提交,你将需要 git push
到 origin
存储库 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
新的超级项目提交。
(如果你没有提交任何新的子模块,这里没有问题。)