我需要重写一个分支,丢弃对特定子文件夹所做的所有更改(例如,其路径为path/to/folder
)及其内容介于一系列修订版本之间,从指定的start
版本开始到结束于HEAD
。接受start
修订之前的更改。
我考虑过使用git-filter-branch
来执行此操作,但不知道要使用哪种过滤器。我认为使用' git-reset'每个提交的子文件夹可能会有效,但是post让我质疑这种方法是否有效。
问题:如何重写上面第一段中指定的分支?
答案 0 :(得分:2)
将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
,并且在14分37秒内使用--index-filter重写了9007次提交。 / p>
答案 1 :(得分:0)
最终有效的方法是使用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
命令中。