2015-12-02 49 views
0

我需要重写分支,放弃对特定子文件夹(例如,其路径为path/to/folder)所做的所有更改及其内容在从指定的start修订版开始的修订范围之间并在HEAD结束。接受start修订版之前的更改。如何重写分支,丢弃对子文件夹的更改

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

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

+0

请举个例子吗? – hjpotter92

+0

据我了解的[文档](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

+0

这将完全删除路径/到/文件夹 – user3159253

回答

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

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是什么,以及使用9007次的提交已被重写 - 在14分37秒内过滤索引)。

+0

嗯 - 我试图使用--index-filter使用相同的命令在一个简单的测试回购,它似乎工作。然而,在数千次提交的实际回购中,却没有。你能否提供一个完整的命令行来使用--index-filter?此外,对发生的事情的一些解释会很好。我不太明白它是如何做到的。 – bright

+0

更新了答案 – user3159253