提问人:dunger_so 提问时间:6/26/2023 最后编辑:dunger_so 更新时间:6/26/2023 访问量:88
如何使用 Git 将仅开发文件与其他文件分开?
How to separate development-only files from the rest with Git?
问:
我正在开发一个 Lua 库,该库涉及代码生成和验证等 - 项目的很多开发代码都是用另一种语言编写的。
我想有一个分支用于库,另一个分支用于休息代码。图书馆不应该知道它依赖于某些东西——首先是为了用户的方便。不过,如果用户阅读文档,他们应该能够找到休息代码 - 它不是私有的。
分支应该同步:为了避免“在项目中写了一些代码,但不影响库”这样的错误 - 忘记更新,方便 CI,制作干净的 git 历史记录。
当前项目是 master 分支根目录下的两个文件夹。我想在不中断同步的情况下将它们分开。我可以在不使用单独的存储库的情况下实现这一点吗?或者使用单独的存储库适合这里并且很方便?参考文档或一些具有类似系统的项目可能就足够了。
同一 repo 的两个分支在这里似乎不合适 - 有必要同时在这两个部分上工作。我不想使用单独的 git 存储库 - 然后我需要使用单独的 git 历史记录,它们应该是相同的,而且管理乘重存储库似乎很不方便 - 但我没有看到其他选择。另外,我不知道如何正确同步它们,谷歌提供了“如何强制存储库具有相同内容”的结果——这不是我想要的。
开发和发布分开的 Git 是关于如何私下开发,然后推送到公共的 - 我需要两者并行。其余的似乎与我无关。
在我所知道的方法中,我不喜欢的主要事情是大多数更改都需要多次提交 - 每个分支/存储库一个。重复(例如完全相同的消息)总是会导致错误。可以避免吗?
我已经阅读了问题规则,看来,我的问题是开放的,是被禁止的。此外,它看起来对其他人没有帮助(问题,答案对像我这样不知道某些 git 可能性的人很有帮助)。我应该删除它吗?
答:
我承认我不了解所有的最新趋势,但直觉上,我会有一个叫做集成或类似的东西的分支,并且有两个分支 - 一个用于库开发,另一个用于休息代码,这样他们都可以将他们的更改推送到集成分支。如果您有多个开发人员,他们可以分支各自的专业 - 库或休息。
评论
您可以将单独的历史记录与主历史记录一起保存在一个存储库中。最简单的方法是根本不使用帮助程序,它是一个工具包,用于在单独的存储库中争吵单独的历史记录,但绕过它会弹出一些警告,并且使它们静音的样板也很容易,所以我把它包括在这里。git submodule
假设您的支持代码位于 中。将代码拆分为合并子模块的最快方法是,从干净的检出开始:support
support
git branch support $(git commit-tree -m 'Split support code to separate history' @:support)
git rm -r support
git worktree add support
git submodule add support
git config -f .gitmodules submodule.support.url ./
git add .gitmodules
git commit -m 'Split support code to separate history'
拆分历史记录的新克隆将有一个空目录,要填充它support
git submodule init
git worktree add support :support
在使用旧结构和新结构的提交之间切换的最简单方法是为它们创建单独的工作树,无论是使用工作树添加还是本地克隆。
P.S. 如果你的支持代码中有足够的历史记录,你只想将整个存储库转换为新结构,请参阅这里,这是我在构建命令之前写的。git worktree
看一看。它不能满足您的所有需求,但我认为这是一种选择。 似乎已被弃用,因为在在线文档中找不到其手册。该命令仍然可用,并且可以按照其手册中的描述工作,我们可以通过 找到。git subtree
git subtree
git subtree
git subtree --help
假设您当前的存储库有两个文件夹,并且它已经有一个现有分支。lib/
src/
main
我们可以拆分为两个单独的分支,for 和 for 。main
lib_split
lib/
src_split
src/
git switch main
git branch lib_split $(git subtree -P lib split main)
git branch src_split $(git subtree -P src split main)
现在我们有三个不同且不相关的分支。上,目录结构如下main
.
├── lib
│ └── a.so
└── src
└── a.lua
上,就像lib_split
.
└── a.so
而在 ,src_slit
.
└── a.lua
此外,我们可以介绍另一个您可以使用的分支。让我们调用它并从 创建它。main_merge
main
git checkout --orphan main_merge main
git rm -rf lib src
git commit -m'init main_merge' --allow-empty
这个新分支用于组合 和 。lib_split
src_split
git switch main_merge
# First add the subtrees
git subtree -P lib add lib_split
git subtree -P src add src_split
# If later lib_split and src_split get updated and have new commits,
# we can merge them to main_merge
git subtree -P lib merge lib_split
git subtree -P src merge src_split
如果更新了,我们还可以更新 和 .main
lib_split
src_split
git switch main
revision=$(git subtree -P lib split main)
git switch lib_split
git merge $revision
git switch main
revision=$(git subtree -P src split main)
git switch src_split
git merge $revision
# The following commands would raise an error.
# When using "git subtree split main",
# make sure the current branch is right main.
git switch src_split
git merge $(git subtree -P src split main)
# As "src" does not exist on src_split,
# git subtree split raises an error
您可以在同一存储库或不同存储库中维护 4 个分支,或者前 3 个分支,或者更多分支。这取决于您的工作流程。
阅读答案后,我得出的结论是,我需要为库提供单独的位置(分支),它将自动更新以与开发分支保持同步 - 如前所述,我想要一个提交更新以更新单独的历史记录。
因此,我将为此使用一些脚本(可能在CI中)。它将为用户生成单独的分支(这就是出现这个问题的原因),我不需要为同步而烦恼 - 我们当前的工作流程根本不会改变(使用 CI,没有人需要在本地使用脚本)。
我宁愿避免复制,但如果我设法正确理解,子树/子模块(并且没有其他建议)不会解决我的问题。他们假设,最终结果 - 依赖于开发文件的库将包含开发文件,即使它不是直接的。Worktree 可以通过将一个分支用于仅开发文件,将另一个分支用于仅库文件来帮助避免复制,但它的使用起来更加复杂(并且在不影响工作流的情况下解决问题的意外可能性看起来是一个非常重要的好处)。感谢您的回答,他们帮助我解决了我的问题。
评论
git submodule