2017-10-20 111 views
1

我將git存儲庫的內容移動到另一個存儲庫,對於所有常規提交,一切都很好。不過,我遇到了子模塊的問題。git filter-tree和修改子模塊

設置,我們從兩個回購開始。我們稱他們爲「文檔」,「行動」,我們要「文檔」的內容移動到「操作」的子目錄,像這樣:

docs/ 
    file1.txt 
    dir1/ 
    file2.txt 
    other-docs/ <- This is a git submodule 

operations/ 
    bin/ 
    do-things 
    docs/ 
    important.txt 

而且我們希望最終版本看這樣,這裏的「文檔」回購協議在操作回購「文檔/遺產」結束:

operations/ 
    bin/ 
    do-things 
    docs/ 
    important.txt 
    legacy/ 
     file1.txt 
     dir1/ 
     file2.txt 
     other-docs/ <- This is a git submodule 

我有一個使用的git filter-branch --tree-filtergit rebase一個組合的腳本(衍合新的內容到現有的內容和處理衝突如.gitignore文件)來執行實際的遷移,但是,在運行遷移後,我最終得到:

其中other-docs子模塊仍位於新回購的根部。

我明白爲什麼會發生這種情況。當我通過提交移動東西時,沒有子模塊的實際文件,因此,在「該目錄中的所有內容都按照您離開它的方式提交」模型git filter-branch --tree-filter,有沒有任何「離開「用於子模塊。

所以,第一個問題:是否有一些方面使用git filter-branch我可以解釋這一點?我想知道的一個地方是,如果我可以添加--commit-filter並弄亂那裏的東西,但我並不完全清楚提交過濾器周圍的不變量是什麼。

如果不存在,是否有其他地方我可以做到這一點。據我所知,我將不得不修改子模塊的現有提交,基本上「刪除」舊的不正確位置的子模塊,並將子模塊「添加」到新的正確位置。我想我可以通過一個交互式的rebase操作來編寫腳本,找到這些提交併修改它們。如果有更好的方法,這聽起來像很多工作。

任何想法讚賞。

回答

1

我明白爲什麼會發生這種情況。當我通過提交移動東西時,沒有子模塊的實際文件,因此,在「該目錄中的所有內容都按照您離開它的方式提交」模型git filter-branch --tree-filter,有沒有任何「離開「用於子模塊。

這就是問題所在。它似乎有點討厭。

所以,第一個問題:是否有一些方面使用git filter-branch我可以解釋這一點?我想知道的一個地方是,如果我可以添加--commit-filter並弄亂那裏的東西,但我並不完全清楚提交過濾器周圍的不變量是什麼。

可以。這不是很漂亮。

更好的做法是在--index-filter。由於the documentation提示,過濾器按列出的順序運行,所以索引過濾器在樹過濾器後運行。它可以對樹形過濾器的周圍代碼編寫的索引進行任何操作。 (樹形過濾器使用git update-index --add-remove來更新索引條目,如果需要,根據您的過濾器留下的樹來自動更新文件。)

您也可以直接在索引過濾器中執行所有操作,速度要快得多,因爲這不需要考慮實際的文件系統操作(mkdir,創建文件等)。雖然索引過濾器通常很難編寫,但命令可以構建一個全新的索引或只更新現有索引的某些部分,但必須先構建一個或一些更改,方法是先讀出舊索引(使用git ls-files --stage,也許)並操縱結果文本。

但是這讓你做你想做的。

3

樹過濾器很容易,但它們很慢,而且你發現它們不知所云。更好的方法是隻檢查你需要修改的內容,其餘的則使用git read-tree

git filter-branch --index-filter=' 

     # load up the docs-repo commit we're importing under docs/legacy/ 
     git read-tree --prefix=docs/legacy/ $(imported-commit-for $GIT_COMMIT): 

     # hoist any imported submodule configs 
     git checkout .gitmodules 
     git checkout docs/legacy/.gitmodules 2>&- && 
     sed -n "s,path ,path docs/legacy/, 
      s,^,git config -f .gitmodules ,e" && 
     git rm docs/legacy/.gitmodules && 
     git add .gitmodules 

     # any other needed content updates here 
' 
+0

尼斯:我沒有注意到--prefix保持當前索引內容不變,只是增加了新的內容。 'git checkout'和'git add'步驟有點痛苦,但幾乎每種方法都是如此。 – torek

+0

@torek Yah,如果你願意,你可以真正運行它作爲一個樹型過濾器,在讀取樹中添加一個「-u」以更新工作樹並消除簽出並添加,因爲filter-branch只會遍歷整個樹對你來說,但浪費的流失如此冒犯了我無法遵守的感情。嗯。我應該把它作爲一種選擇,讓任何人不會因爲浪費而被冒犯。 – jthill

+0

heh。不。不能讓自己發佈結果,不管它看起來更乾淨。 – jthill