我需要重写分支,放弃对特定子文件夹(例如,其路径为path/to/folder
)所做的所有更改及其内容在从指定的start
修订版开始的修订范围之间并在HEAD
结束。接受start
修订版之前的更改。如何重写分支,丢弃对子文件夹的更改
我考虑过使用git-filter-branch
来做到这一点,但不知道使用哪个过滤器。我认为对每个提交使用'git-reset'到子文件夹可能会有效,但是这个post让我质疑这种方法是否可行。
问题:如何重写上面第一段中指定的分支?
我需要重写分支,放弃对特定子文件夹(例如,其路径为path/to/folder
)所做的所有更改及其内容在从指定的start
修订版开始的修订范围之间并在HEAD
结束。接受start
修订版之前的更改。如何重写分支,丢弃对子文件夹的更改
我考虑过使用git-filter-branch
来做到这一点,但不知道使用哪个过滤器。我认为对每个提交使用'git-reset'到子文件夹可能会有效,但是这个post让我质疑这种方法是否可行。
问题:如何重写上面第一段中指定的分支?
什么最终工作是使用git-filter-branch
与git rm
的组合来删除提交中添加的新文件和'git checkout'来恢复状态。
git filter-branch -f --prune-empty --index-filter 'git rm -rfq -- path/to/subdir && git checkout -f <the-good-state-sha1> -- path/to/subdir' -- start..HEAD
这里start
是起始提交和<the-good-state-sha1>
是start
的父的提交的哈希值。 注意:path/to/subdir
需要指定两次,如图所示,一次在rm
命令中,一次在checkout
命令中。
使用git-filter-branch与--tree-filter
,可能与--prune-empty
。整个命令序列可以是这样的:
GOOD_STATE=<some-revision>
DIR_TO_PRESERVE="relative/path/to/directory"
BRANCH_TO_REWRITE=<branch-to-rewrite>
export GOOD_STATE DIR_TO_PRESERVE BRANCH_TO_REWRITE
git filter-branch --tree-filter \
'rm -rf "${DIR_TO_PRESERVE}" && git checkout -f ${GOOD_STATE} -- "${DIR_TO_PRESERVE}"' \
--prune-empty ${BRANCH_TO_REWRITE} --not ${GOOD_STATE}
其更快的替代方案--index-filter
都可以使用。但作为一个命令,你不应该使用git rm...
,因为这会完全删除路径。相反,你应该使用git reset
重置给定文件夹的索引:
git filter-branch --index-filter \
'git reset -q ${GOOD_STATE} -- "${DIR_TO_PRESERVE}"'' \
--prune-empty ${BRANCH_TO_REWRITE} --not ${GOOD_STATE}
要加快一件事可能会暂时将存储库复制到更快的文件系统(我在Linux上使用tmpfs
是什么,以及使用9007次的提交已被重写 - 在14分37秒内过滤索引)。
嗯 - 我试图使用--index-filter使用相同的命令在一个简单的测试回购,它似乎工作。然而,在数千次提交的实际回购中,却没有。你能否提供一个完整的命令行来使用--index-filter?此外,对发生的事情的一些解释会很好。我不太明白它是如何做到的。 – bright
更新了答案 – user3159253
请举个例子吗? – hjpotter92
据我了解的[文档](https://www.kernel.org/pub/software/scm/git/docs/git-filter-branch.html)你应该很好'git filter-branch --index -filter'git rm --cached --ignore-unmatch path/to/folder'commit..HEAD' – Vogel612
这将完全删除路径/到/文件夹 – user3159253