根据我理解您的问题:
git subtree
或git submodules
的原因提取只有一部分文件的历史记录到专用分支(然后可以将其推送到专用仓库)的一种方法是使用git filter-branch
:
# regex to match the files included in this subproject, used below
file_list_regex='^subproject1/|^shared_file1$|^lib/shared_lib2$'
git checkout -b subproject1 # create new branch from current HEAD
git filter-branch --prune-empty \
--index-filter "git ls-files --cached | grep -v -E '$file_list_regex' | xargs -r git rm --cached" \
HEAD
这将
HEAD
创建一个新的分支subproject1
(git checkout -b subproject1
)git filter-branch [...] HEAD
)git ls-files --cached | grep -v -E '$file_list_regex'
),使用(xargs -r git rm --cached
)--prune-empty
).--index-filter
/--cached
)上操作。虽然这是一次性操作,但根据我理解你的问题,您想要连续更新提取的子项目存储库/分支以获取新的提交。
好消息是您可以简单地重复此命令,因为git filter-branch
将始终为您的子项目分支生成相同的提交/历史记录-只要您不手动更改它们或重写主分支。
缺点是这将每次并且对于每个子项目都完全过滤历史记录。鉴于您只想将master
分支的最后5个提交添加到现有的subproject1
分支的末尾,您可以像这样调整命令:
# get the full commit ids for the commits we consider
# to be equivalent in master and subproject1 branch
common_base_commit="$(git rev-parse master~6)"
subproject_tip="$(git rev-parse subproject1)"
# checkout a detached HEAD so we don't change the master branch
git checkout --detach master
git filter-branch --prune-empty \
--index-filter "git ls-files --cached | grep -v -E '$file_list_regex' | xargs -r git rm --cached" \
--parent-filter "sed s/${common_base_commit}/${subproject_tip}/g" \
${common_base_commit}..HEAD
# force reset subproject1 branch to current HEAD
git branch -f subproject1
说明:
git filter-branch [...] ${common_base_commit}..HEAD
),直到 master~6
,我们认为它是等效于 subproject1
当前版本的提交。master~6
重写为 subproject1
(--parent-filter 'sed s/${common_base_commit}/${subproject_tip}/g'
),有效地将5个重写的提交重新基于 subproject1
。subproject1
以包含其上的新提交。进一步优化/自动化:
$file_list_regex
) 或者实际上要排除的文件 (git ls-files --cached | grep -v -E '$file_list_regex'
) 来自给定的子项目$GIT_COMMIT
) 或者在存储库本身中检入列表,以防子项目的要包括的文件可能随时间而变化git update-project subproject1
首先,让我总结一下你的问题:
从你的统计数据中,我可以看到你在一个主代码库中存储了14个子项目。这通常是一个非常糟糕的解决方案,因为请记住,每当有人克隆代码库时,它也会获取所有子项目的完整历史记录。例如,如果我想为你的其中一个子项目做出贡献,我不想携带你拥有的8096个文件。
如果这些项目彼此无关,只需将它们拆分为子代码库即可。使用GitHub,您可以创建组织。不要犹豫,创建自己的组织并将所有子项目放入其中。主要优点是每个子项目都将拥有:
如果您有相关项目,每个项目都需要从特定的提交中获取。我建议您使用git子模块。例如,如果您查看ext/
文件夹中的TortoiseGit项目,您将注意到其他存储库的链接。
另一个解决方案是使用git子树, 这似乎不是您问题的最佳解决方案。
如果您的主存储库属于以下任何一类,则应重新审视您使用Git的方式:
.exe
、.tmp
、二进制文件、生成的文件、.pdf
等)您的存储库是否在GitHub上公开?
git subtree
的一些信息:https://dev59.com/S1QJ5IYBdhLWcg3wKysQ#61273621 - Inigo