shopsys/monorepo-tools
GitHub: shopsys/monorepo-tools
一组用于将多个独立 Git 仓库合并为 monorepo 并保持完整提交历史可逆向拆分的 Shell 脚本工具。
Stars: 698 | Forks: 65
# Shopsys Monorepo 工具
[](https://github.com/korfuri/awesome-monorepo)
**此包用于拆分我们的 monorepo,我们原样与社区分享它。我们不打算进一步支持或开发它。请随意 fork 它并根据您的需要进行调整。**
用于从现有包构建和拆分单体代码库(monolithic repository)的工具。
您可以在 [Shopsys 平台博客](https://blog.shopsys.com/how-to-maintain-multiple-git-repositories-with-ease-61a5e17152e0)上阅读有关 monorepo 方法的优缺点。
我们创建这些脚本是因为我们找不到一个能保持子包 git 历史记录不变的工具。
您可能需要更新您的 `git`(已在 `2.16.1` 版本上测试过)。
此代码库由 [shopsys/shopsys](https://github.com/shopsys/shopsys) monorepo 维护,有关变更的信息请查看其 `CHANGELOG` 文件。
## 快速开始
### 1. 下载
首先下载此代码库,以便您可以使用这些工具(例如,下载到 `~/monorepo-tools`)。
```
git clone https://github.com/shopsys/monorepo-tools ~/monorepo-tools
```
### 2. 准备一个添加了 remotes 的空代码库
您必须为您的 monorepo 创建一个新的 git 代码库,并将所有现有的包作为 remotes 添加进去。
您可以添加任意数量的 remotes。
在这个示例中,我们将准备 3 个来自 github 的包,以便合并到 monorepo 中。
```
git init
git remote add main-repository http://github.com/vendor/main-repository.git
git remote add package-alpha http://github.com/vendor/alpha.git
git remote add package-beta http://github.com/vendor/beta.git
git fetch --all --no-tags
```
### 3. 构建 monorepo
然后您可以使用 `monorepo_build.sh` 来构建您的 monorepo。
只需列出您之前添加的所有 remotes 的名称作为参数即可。
您也可以选择通过提供 `:` 来指定代码库所在的目录,否则将使用 remote 名称。
该命令将重写所有相关代码库的历史记录,就好像它们是在不同的子目录中开发的一样。
只有 `master` 分支会被合并在一起,其他分支将仅从第一个包中保留,以避免可能的分支名冲突。
```
~/monorepo-tools/monorepo_build.sh \
main-repository package-alpha:packages/alpha package-beta:packages/beta
```
这可能需要一段时间,具体取决于您的代码库大小。
现在您的 `master` 分支应该包含位于不同目录下的所有包。对于我们的示例来说,这意味着:
- **main-repository/** - 包含代码库 _vendor/main-repository_
- **packages/**
- **alpha/** - 包含代码库 _vendor/alpha_
- **beta/** - 包含代码库 _vendor/beta_
### 4. 拆分回原始代码库
从现在起,您应该在这个代码库中开发所有的包。
当您完成更改并希望更新原始代码库时,请使用 `monorepo_split.sh`,参数与之前相同。
```
~/monorepo-tools/monorepo_split.sh \
main-repository package-alpha:packages/alpha package-beta:packages/beta
```
这会将所有相关的更改推送到您所有的 remotes 中。
它将拆分并推送您的 `master` 分支,以及您在此代码库中添加的所有 tags。
其他分支不会被推送。
这可能又需要一段时间,具体取决于您的 monorepo 大小。
**_注意:_**
_拆分后代码库中的 commit 应与原始代码库中的完全一致,从而保持 git 历史记录完好无损。_
_因此,如果您之前已经检出过原始的 `master` 分支,在拆分之后,您应该能够快进(fast-forward)到新版本。_
_唯一已知的例外是签名 commit(请注意,GitHub 默认会对其 Web UI 上进行的 commit 进行签名)。_
_如果您的原始代码库中包含签名 commit,拆分后的 commit 将不会被签名。_
_这将导致 `monorepo_split.sh` 无法将未签名的 commit 推送到 remote。_
_为了解决这个问题,您可以在脚本的 `git push` 调用中添加 [`--force` 标志](https://git-scm.com/docs/git-push#git-push--f),但如果您不确定自己在做什么,这可能会导致无法预料的后果。_
### 将新包添加到 monorepo 中
当您拥有 monorepo 之后,您可能会发现在使用该 monorepo 一段时间后,有理由需要添加一个新的包。
在这种情况下,请不要使用 `monorepo_build.sh`,而是执行以下步骤:
- 创建一个新的代码库,例如 _vendor/gamma_
- 在 monorepo 中添加 remote:`git remote add package-gamma http://github.com/vendor/gamma.git`
- 在 monorepo 中创建一个新目录 **packages/gamma**
- 添加代码并提交
- 对新包使用拆分工具
~/monorepo-tools/monorepo_split.sh \
main-repository package-alpha:packages/alpha package-beta:packages/beta package-gamma:packages/gamma
## 参考
这只是包中所有工具的简要说明和使用方法。
获取详细信息请直接查看脚本并阅读注释。
### [monorepo_build.sh](./monorepo_build.sh)
从指定的 remotes 构建 monorepo。这些 remotes 必须已经添加到您的代码库并已获取。
用法:`monorepo_build.sh [:] [:] ...`
### [monorepo_split.sh](./monorepo_split.sh)
拆分由 `monorepo_build.sh` 构建的 monorepo,并将所有 `master` 分支连同所有 tags 一起推送到指定的 remotes。
用法:`monorepo_split.sh [:] [:] ...`
### [monorepo_add.sh](./monorepo_add.sh)
将指定 remotes 中的代码库添加到现有的 monorepo 中。这些 remotes 必须已经添加到您的代码库并已获取。每个代码库只会添加 master 分支。
用法:`monorepo_add.sh [:] [:] ...`
### [rewrite_history_into.sh](./rewrite_history_into.sh)
重写 git 历史(甚至是 tags),以便将所有文件路径放置在特定的子目录中。
用法:`rewrite_history_into.sh []`
### [rewrite_history_from.sh](./rewrite_history_from.sh)
重写 git 历史(甚至是 tags),以便仅保留在某个子目录中进行过更改的 commit,并将所有文件路径重写为根目录路径。
用法:`rewrite_history_from.sh []`
### [original_refs_restore.sh](./original_refs_restore.sh)
在重写后恢复原始的 git 历史。
用法:`original_refs_restore.sh`
### [original_refs_wipe.sh](./original_refs_wipe.sh)
在重写后清除原始的 git 历史。
用法:`original_refs_wipe.sh`
### [load_branches_from_remote.sh](./load_branches_from_remote.sh)
删除所有本地分支,并创建指定 remote 的所有非远程跟踪分支。
用法:`load_branches_from_remote.sh `
### [tag_refs_backup.sh](./tag_refs_backup.sh)
将 tag 引用备份到 `refs/original-tags/`
用法:`tag_refs_backup.sh`
### [tag_refs_move_to_original.sh](./tag_refs_move_to_original.sh)
将 tag 引用从 `refs/original-tags/` 移动到 `refs/original/`
用法:`tag_refs_move_to_original.sh`
## 支持
遇到困难或需要帮助时该怎么办?
最好的方式是加入我们的 [Slack](https://join.slack.com/t/shopsysframework/shared_invite/zt-11wx9au4g-e5pXei73UJydHRQ7nVApAQ)。
如果您想[报告问题](https://github.com/shopsys/shopsys/issues/new),请使用主要的 [Shopsys 代码库](https://github.com/shopsys/shopsys)。
标签:Cutter, Git, Shell脚本, SOC Prime, 代码仓库管理, 开发工具, 网络安全研究