在下面的示例中,我想证明对Git子模块进行更改并在本地提交它可能会导致一种非常糟糕的情况,我希望找到一个可行的解决方案(除了答案"伙计,不要使用Git子模块它是邪恶的")
我首先创建两个存储库:一个主项目及其子模块:
~ $ for r in main sub; do mkdir $r; cd $r; git init; cd ..; done
Initialized empty Git repository in ~/main/.git/
Initialized empty Git repository in ~/sub/.git/
让我们把一些内容放到子模块中:
~/ $ cd sub
~/sub $ touch sub && git add sub
~/sub $ git commit -m "Added sub"
[master (root-commit) a14ce2f] Added sub
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 sub
然后我们在主项目中导入该子模块:
~/sub $ cd ../main
~/main $ git submodule add ../sub sub
Cloning into '~/main/sub'...
done.
~/main $ git commit -am "Added submodule sub"
[master (root-commit) bd37219] Added submodule sub
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 sub
现在的问题是:我想在本地修改子模块的猴子补丁。
~/main $ cd sub
~/main/sub $ echo "Monkey patched"" >> sub
> echo "Monkey patched"^C>> sub
~/main/sub $ echo "Monkey patched" >> sub
~/main/sub $ git commit -am "Local hotfix"
[master 0b37958] Local hotfix
1 file changed, 1 insertion(+)
~/main/sub $ ..
~/main $ git commit -am "Hijacked sub-module"
[master 1b3a4af] Hijacked sub-module
1 file changed, 1 insertion(+), 1 deletion(-)
一切看起来都很漂亮,因为它看起来如此,但邪恶就在那里。
Alice希望在该项目上工作,因此她克隆了主存储库(让我们想象主服务器被Bob推送到集线器的某个地方)
~/main $ ..
~/test $ git clone main alice
Cloning into 'alice'...
done.
~/test $ cd alice
~/alice $ git submodule init
Submodule 'sub' (~/sub) registered for path 'sub'
到目前为止,爱丽丝很高兴直到现在:
~/alice $ git submodule update
Cloning into '~/sub'...
done.
error: Server does not allow request for unadvertised object 0b3795831f31cf8e9c4444a021936c12210e24c6
Fetched in submodule path 'sub', but it did not contain 0b3795831f31cf8e9c4444a021936c12210e24c6. Direct fetching of that commit failed.
如果很明显Git没有跟踪主存储库中的猴子补丁,而是跟踪子模块的本地历史记录。
这对我来说就像是Git子模块的设计失败,或者我只是误解了我今天要求的东西。
有没有办法
我正在开发嵌入式固件开发,其中每个新项目都包含:
有时我需要修补物理组件的代码库。例如,我想通过提高无线电功率来扩展蓝牙IC的原生范围(这不是驱动程序通常允许的功能)。
答案 0 :(得分:2)
我的回答如果有点偏。这里的问题是如何在本地更改内容而不将其发布到子模块的远程存储库中(因为这并不总是可行),但仍然允许其他人使用您的更改。
您必须以某种方式将更改发布给您的队友。因此,更改不能仅保留在子模块中。以下之一将实现这一目标:
在本地修改子模块完全没问题。你必须记住的一件最重要的事情是:
仅在推送子模块存储库中的更改后才推送主存储库中的子模块更改。
您的示例并未真正涵盖这一点,因为您没有推送到远程服务器。我在这里看一个集中的工作流程,因为这是大多数人根据我的经验所做的事情。
修改子模块,提交并提交主存储库中的子模块更改,但只推送后者时,远程主存储库引用服务器端未知的子模块提交,生成{{1错误。当您首先将子模块更改推送到子模块的存储库,然后主存储库更改时,Alice可以克隆主存储库,初始化并更新子模块并继续进行更改。
现在您的示例中的问题是您仅在Server does not allow request for unadvertised object
中修改了子模块,而在子模块存储库本身(~/main/sub
中的子模块)中没有。当Alice从~/sub/
克隆时,子模块引用~/main/
,其中您更新的提交未知。您必须将更改推送到~/sub/
以使提交公共可用,之前您允许任何人在主存储库中获取更新的子模块提交。