在Git仓库中将一组文件拆分为自己的仓库,保留相关历史记录

37
可能重复:如何在保留子目录的情况下拆分Git存储库? 曾经我把我的代码添加到了一个现有的Git仓库中,自那以后我已经向其中提交了很多次代码修改,另一位开发者则向仓库中的其他文件进行了提交。现在我想将我的代码拆分到它自己的仓库中,但保留我的特定文件的所有更改历史记录。
通过阅读其他人为分离代码所做的工作,我正在研究使用“filter-branch”和使用“--index-filter”或“--tree-filter”与“rm”命令来处理我不关心的文件。我不想使用“--subdirectory-filter”,因为它不适用于包含我的代码的子目录成为顶级目录(我们也共享一个子目录) 。复杂化问题的是,原始存储库中的某些文件随着时间的推移已经移动了位置,并且还有一些创建然后被删除的文件。这使得设计一个删除列表有点具有挑战性。
我正在寻找一种方式来过滤除了一系列文件/目录之外的所有内容。有人知道如何实现吗?

2
谢谢。使用 git filter-branch --prune-empty --index-filter 'git ls-tree -r --name-only --full-tree $GIT_COMMIT | grep -v "^src/pyfedpkg$" |grep -v "^src/fedpkg" |grep -v "^git-changelog" | xargs git rm --cached -r' -- --all 已完成。 - jkeating
2
与https://dev59.com/XnE85IYBdhLWcg3wZymt(依我之见)不同,因为它要求保留特定的稀疏文件集。 - rogerdpack
3
这不是重复的问题!那里提供的问题/答案(2797191)仅适用于单个目录下的文件。这个问题要求一组文件,不必要地分组在一个目录下。 - jxy
1个回答

50

只是为了解决这个问题,使其成为已回答的问题。

通过使用index-filtertree-filter并应用反向逻辑(如git ls-tree管道到(multiple)grep -v的管道到xargs用于git rm),您确实可以删除与一组狭窄文件名/目录不匹配的所有内容。这是我用来分离我的特定文件的命令:

git filter-branch \
    --prune-empty \
    --index-filter '
        git ls-tree -z -r --name-only --full-tree $GIT_COMMIT \
        | grep -z -v "^src/pyfedpkg$" \
        | grep -z -v "^src/fedpkg" \
        | grep -z -v "^git-changelog" \
        | xargs -0 -r git rm --cached -r
    ' \
    -- \
    --all

4
当一个文件在提交中被单独添加到树中时,"grep | xargs git rm" 部分会导致非零的退出码,并且 --index-filter 将失败。我不得不使用 -r 或 --no-run-if-empty 选项(GNU 扩展)来增强 xargs。我建议将答案修改为这样。 - lkraav
1
这对我来说失败了,显示"路径规范'SomeDir/SomeSubDir'没有匹配任何文件。" SomeSubDir只是一个包含空格的子目录名称的第一部分。因此,似乎这个解决方案在包含空格的子目录的仓库上不起作用。有可能的解决方法吗? - Mark Edington
2
如果您想让xargs正常工作,您需要使用-0选项;如果您想要git ls-treegrep可靠地工作,则需要使用-z选项。这样做可以确保适用于所有可能的文件名。 - ssokolow
1
git rm 命令中添加 -q 选项可以避免输出被大量的 rm '...' 日志信息淹没。 - Simon Sapin
2
@jkeating 太厉害了 - 我印象深刻,我刚刚创建了一个 git splits 扩展,将其整合到了 git 中。 - AndrewD
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接