我们有一个大型存储库,其子文件夹为platforms
,
sdk/
.git/
android/
ios/
unity/
windows/
我们现在要打破自己的存储库。保留所有历史和那里的分支。
我已经运行了命令
git filter-branch -f --prune-empty --subdirectory-filter android -- --all
看起来它已经运行了我想要的,促使子文件夹android
成为这个新存储库的根目录,然后我将其推送到新的远程源(在GitHub上)
执行此操作时,我收到一条错误消息,指出文件太大而无法推送到远程,但此文件的路径为
unity/QAApp/...
其他子文件夹的历史记录中存在我认为不会filter-branch --subdirectory-filter
采用的文件。
我正在考虑运行手册
git filter-branch -f --prune-empty --tree-filter \
'git rm -rf --ignore-unmatch ios unity windows && rm -rf ios unity windows' \
-- --all
但似乎这是我理解filter-branch subdirectory-filter
应该做的双重工作。这是预期的行为,还是我错误地运行了一个或另一个命令?
答案 0 :(得分:1)
在使用git邮件列表的人员后退一点,看起来这似乎是filter-branch的一个问题。这里的主要问题是filter-branch只与与你指定的子目录交互的分支进行交互。如果你有一些从未做过的分支,命令就不会靠近它们,让你在你的回购中留下你可能不想要的历史记录。
获得我想要的第一种方法是清除所有不与子目录交互的分支,在本例中为android
,
path=android/
git for-each-ref --format='%(refname)' |
while read ref; do
if test "$(git rev-list --count "$ref" -- "$path")" = 0; then
echo "delete $ref"
fi
done | git update-ref --stdin
此代码段会遍历您的git repo所具有的每个分支引用,检查它是否具有对您子目录的引用,如果没有,则将其删除。
接下来更改filter-branch命令
git filter-branch -f --prune-empty --tag-name-filter cat --subdirectory-filter android -- --all
在命令中添加--tag-name-filter cat
会重做标记并阻止标记分支保留不需要的历史记录。
最后要做的就是擦拭保持备份的历史记录,
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
过滤器分支存储与其交互的每个分支的备份。这是正确和正确的行为,但为此目的,当您想要重写所有历史记录并了解您正在做的事情的后果时,删除备份是正确的,也可以。
在这之后,你得到一个正确的重做repo,只有该子目录中的历史记录,其他一切都被丢弃,包括从未与该子目录交互过的分支。