我有一个在 github 上托管的项目,结构如下
github.com/example/allpackages
.
├── .git
└── packages
├── example-1
├── example-2
└── example-3
在每次推送到 github 时,我希望每个包的内容都推送到存储库,对应于存储库名称,例如
github.com/example/example1
.
├── .git
└── example1
github.com/example/example2
.
├── .git
└── example2
等。
有人对如何自动化有任何想法吗?有人提到使用 Travis-CI 来完成这项任务,但我找不到任何关于它如何工作的细节。
我的理想解决方案:
- 将是完全自动化的 - 这意味着更新不会由推送计算机触发,而是由github或外部服务触发。
- 更新时将历史记录从"allpackages"迁移到相应的子存储库
任何关于从哪里开始研究的指导将不胜感激。提前感谢!
编辑:
@VonC建议使用子模块,并使用git submodule foreach --recursive
进行提交
优点:
- 干燥 - 每个子模块的代码位于一个地方。
- 能够跟踪父模块中子模块的更改。 使用
git submodule foreach --recursive
使用别名允许对多个子模块进行单次提交
缺点:
- 查看对子模块所做的更改并不能立即清楚。必须深入研究子模块以查看进行了哪些更改。
- 使用
git submodule foreach --recursive
很麻烦,而且不像常规提交那样优雅。
对于此特定用例。"包"存储库,例如 github.com/example/example1
只会在某种意义上被阅读。我不会直接向他们推。他们只会在allpackages
更新时收到更新。需要创建它们的唯一原因是,使用它们的包管理器需要为每个包提供单独的存储库。
如果您将所有exampleX
文件夹声明为 git 存储库,并使它们成为父存储库的子模块 allpackages
,那么:
-
每个
exampleX
存储库都可以在 GitHub 上拥有自己的上游存储库 -
(从 git 1.7.11 开始(,您可以将每个推送到各自的存储库
cd allpackages git push --recurse-submodules=on-demand
一个命令,一切都被推动。
Github 不会运行存储库钩子。 正如我所读到的,使用更新后钩子设置一个 github 代理存储库,该钩子适应此答案中的自动跟踪,然后转发推送将满足规定的要求。
话虽如此,不过,我和VonC在一起。如果你不使用子模块,你就会被这样的东西所困——实际上,它只不过是脆弱的、残缺的、隐形的子模块,只适用于那个存储库,一旦有人推到那个代理之外的任何地方,就会保证会崩溃。 对于您自己的工作,在私有存储库中,这可能非常方便,并且有一些方法可以将脆弱性踢得更远,但对于共享学科来说,它还不够强大。
对于共享工作,我敢打赌,无论如何,您迟早会切换到子模块,并发现它们并不是很神秘。 所以忽略这一点并接受 VonC 的答案:-(
我仍然更喜欢我之前推荐的干净的"子模块"方法。
但是,将存储库的一个文件夹推送到独立上游存储库的另一种更黑客的方法是使用嵌套存储库技术:
cd myrepos
git clone https://github.com/example/example1
git clone https://github.com/example/allpackages
cd allpackages/packages/example-1
git --git-dir=../../../example1/.git add .
git --git-dir=../../../example1/.git commit -m "commit for example1"
git --git-dir=../../../example1/.git push
对于示例 1 GitHub 存储库,这将考虑 allpackages/packages/example-1
的工作树:--git-dir
使 Git 认为allpackages/packages/example-1
是自己的(嵌套(git 存储库,带有一个远程的"origin
"引用 GitHub。
但是:这意味着 3 个不同的推送命令,除非您将这些命令包装在脚本中并通过 git 别名调用该脚本:
git config alias.pushall '!sh pushall.sh'