2014-03-04 18 views
6

我想合併多個Git倉庫(讓我們說repoA和repoB)到一個新的倉庫。新的存儲庫(repoNew)應該在一個單獨的子目錄中包含每個repoA和repoB。由於我到現在爲止只在本地工作,我可以做任何我想要的存儲庫。如何重寫Git歷史記錄以便所有文件都在子目錄中?

在這些情況下,標準方法似乎是使用git filter-branch來重寫每個repoA和repoB的歷史記錄,使其看起來好像它們一直位於子文件夾中,然後將它們合併到repoNew中。

第一步是什麼讓我困擾。我很清楚SO的答案,如How can I rewrite history so that all files, except the ones I already moved, are in a subdirectory?(Dan Molding的回答),這正是我想要的。

他建議沿着以下線的東西:

git filter-branch --prune-empty --tree-filter ' 
if [[ ! -e repoA ]]; then 
    mkdir -p repoA 
    git ls-tree --name-only $GIT_COMMIT | xargs -i mv {} repoA 
fi' 

的結果應該是<repoA-GIT-base>下的文件夾結構現在應該在<repoA-GIT-base>/repoA。然而,這種情況並非如此。上面的命令在不同的提交隨機失敗,像「MV的消息:無法移動‘SRC’到‘repoA/src目錄’

改寫歷史時所描述的如何避免這些錯誤提交

編輯?

您應該考慮移動像這樣排除.gitignore

git filter-branch --prune-empty --tree-filter ' 
if [[ ! -e repoA ]]; then 
    mkdir -p repoA; 
    git ls-tree --name-only $GIT_COMMIT | 
    grep -ve '^.gitignore$' | 
    xargs -i mv {} repoA; 
fi' 

的命令仍然在隨機失敗貌似我試了幾次,每次在不同的提交中發生「無法移動」的失敗。我觀察到,當我排除.gitignore時,通過所有提交的機會似乎增加。我能夠在所有三個不同的存儲庫中連續執行此操作,而不會失敗。當我再次嘗試它時,僅僅爲了獲得其中一個存儲庫的另一個丟棄副本的樂趣,它再次失敗。

因爲我也有時難以刪除由於涉嫌使用某些文件的流程而丟失的副本,所以問題可能與Windows 7文件訪問處理有關,但我無法做出認真假設。

繼續嘗試,直到它成功當然是荒謬的,並可能無法在提交大量提交(我的只有~30)的倉庫工作。

信息:我在Windows 7 64位企業版上使用了git版本1.7.10.msysgit.1的git-bash。

+0

我發佈了[我的答案](http://stackoverflow.com/a/22144094/955926)與昨天的幾乎相同的問題,只是作爲替代實際粉碎回購協議。 –

+0

這是我最初想要做的方式,但我想保留單個文件的歷史記錄。由於我忘記了一些重要的事情,所以我也編輯了這個問題 – svenhuebner

回答

1

我已經寫了一個基於libgit2的程序來過濾git分支的另一個目的,我稍微改變了做你想在這裏做的。你可以試試它。

正是在git_filter的子目錄分支在github上:

https://github.com/slobobaby/git_filter/tree/subdir

我只是測試它在我們的100000提交後倉庫裏,花了43秒。

我寫了程序,因爲基於git filter-branch的解決方案花了幾天到幾周才完成。

示例配置過濾「測試」存儲庫並將所有內容放入「測試」子目錄中 - 您可以更改此項以執行所需操作。

2

我懷疑你正在尋找沿git subhistory的東西。這是一個非常小的項目,似乎沒有得到很好的維護,但它也被設計成幾乎完全符合你的描述。試一試!

+0

非常好的項目。這一個爲我做了詭計。我發現的唯一缺陷是它不能將一個子項目合併到一個空的回購站(即將多個項目合併成一個新的空回購站,每個子回收站都在一個子目錄中),但是git本身在這方面是片狀的。 – dataless

相關問題