2015-12-02 48 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