2017-03-16 127 views
4

我有一個複雜的git回購從中我想刪除ALL文件和歷史,除了兩個文件夾,讓我們說:刪除所有除從混帳歷史的某些文件夾

foo/a 
bar/x/y 

雖然git filter-branch --subdirectory-filter會讓我選擇一個文件夾,然後創建新的根目錄,似乎沒有給我任何選擇兩個目錄的選項,並保留它們的位置。

git filter-branch --tree-filter--index-filter看起來像它會讓我迭代歷史中的每一個提交,我可以在不需要的文件夾上使用git rm

我似乎無法找到任何工作方式來獲取這些命令,只保留我想要的兩個文件夾,同時清除其他所有內容

謝謝!

+1

的解決辦法是: 'git filter-branch --prune-empty --index-filter'git ls-files | grep -vE「foo/a/| bar/x/y /」| xargs git rm -rf --cached --ignore-unmatch'' –

回答

1

你是對的:樹濾波器或索引濾波器將是與git filter-branch做到這一點的方式。

樹形過濾器比較容易,但速度要慢得多(容易慢10到100倍)。樹型過濾器的工作方式是,您提供的命令在臨時目錄中運行,該目錄包含所有且僅存在於原始(即時複製)提交中的文件。您的命令留下的任何文件都保留在複製的提交中。您的命令在臨時目錄中創建的任何文件也都位於複製的提交中。 (您可以在臨時目錄中創建或刪除目錄,因爲Git只存儲這些文件。)因此,要刪除除 A和B以外的所有內容,請編寫一個命令,刪除除了A或B:

find . -name A -prune -o -name B -prune -o -print0 | xargs -0 rm 

例如。

索引過濾器比較難,但速度更快,因爲Git不必將所有文件複製到文件樹中,然後重新掃描文件樹以構建新索引,以便複製原始提交。相反,它只提供一個索引,然後可以使用命令(例如git rm -rf --cached --ignore-unmatch)或git update-index來處理最常見的情況。但是,現在唯一的工具是Git中操縱索引的工具。沒有花哨的Unix find命令。

你當然有git ls-files,它讀出索引的當前內容。因此,你可以寫在任何一種語言,你喜歡的節目(我會使用Python先到這裏,大概,別人可能會用Perl開始),在本質上的作用:

for (all files in the index) 
    if (file name starts with 'A/' or 'B/') 
     do nothing 
    else 
     add to removal list 
invoke "git rm --cached" on paths in removal list 

如果你願意相信,沒有文件名中有嵌入式換行符,上面可以常規shell來完成的:

git ls-files | IFS=$'\n' while read path; do 
    case "$path" in A/*|B/*) continue;; esac 
    git rm --cached "$path" 
done 

這還不是特別有效的(一個git rm --cached每道!),但應該工作「開箱即用」作爲--index-filter

(未經測試,但可能工作,應該是顯著更有效:。通過grep -vgit ls-files輸出刪除所需的文件和管道grep輸出爲git update-index --force-remove --stdin這仍然不承擔任何換行符路徑名)

+0

Thanks @torek!不熟悉'find'我不得不對它解構一些,直到我找到它的工作,但這將需要大約一個小時。 我找到了一個很好的解決方案: 'git filter-branch --prune-empty --index-filter'git ls-files | grep -vE「foo/a/| bar/x/y /」| xargs git rm -rf --cached --ignore-unmatch',儘管一次迭代超過了我可以管到'xargs'的參數數量。 我解決了這個通過首先刪除整個大文件夾,使用'git filter-branch --prune-empty --index-filter'git rm -rf --cached --ignore-unmatch c/d/e /'HEAD' –

0

對於文件,我這樣做了git fast-export。但我不確定這會對目錄產生影響。所以我建議使用git fast-exportfind的組合。

git fast-export HEAD -- `find foo/a bar/x/y -type f` >../myfiles.fi 

然後創建一個新的回購,並導入流。

git init 
git fast-import <../myfiles.fi 
相關問題