如何重写分支,丢弃对子文件夹的更改

时间:2015-12-02 09:35:44

标签: git git-filter-branch git-reset

我需要重写一个分支,丢弃对特定子文件夹所做的所有更改(例如,其路径为path/to/folder)及其内容介于一系列修订版本之间,从指定的start版本开始到结束于HEAD。接受start修订之前的更改。

我考虑过使用git-filter-branch来执行此操作,但不知道要使用哪种过滤器。我认为使用' git-reset'每个提交的子文件夹可能会有效,但是post让我质疑这种方法是否有效。

问题:如何重写上面第一段中指定的分支?

2 个答案:

答案 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-branchgit 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命令中。