2

我們有一個相當龐大的代碼庫,包含大約60000個提交。我們希望在保留git歷史的同時重新格式化所有的.java文件。因此,我們採用的方法是使用git filter-branch --tree-filter重新格式化整個代碼庫,同時保持歷史記錄不變。但是,有幾個問題我無法找到答案。使用git rewrite重新格式化整個代碼庫

  1. 當我應用--tree過濾器,並通過重新格式化所有.java文件的根目錄下,重寫發生的命令,但在最後,我看到的所有.java文件暫存區。重寫的每一步都需要提交還是自動發生?

  2. git filter-branch似乎需要一系列的提交,這讓我想知道是否有可能在每次重寫之前保存提交ID並在發生故障時恢復。恢復很重要,因爲整個過程可能需要幾天才能完成(即使在強大的計算實例上)。

  3. 爲了重新格式化整個代碼庫,會--index-filter工作嗎?

UPDATE:澄清

  • 代碼底座約220萬行Java代碼。不進行git重寫會導致大約10%-12%的代碼庫歸因於錯誤的作者。這大約是20萬行Java代碼,這是我們想要避免的。 Git重寫使得它看起來像做出改變的人以正確的方式做到了。
+0

我不清楚你的意思是「最後......所有的.java文件都在暫存區」。過濾器分支命令實際上結束檢查過濾結果,所以當然,暫存區域是非空的,除非過濾結果爲空。 – torek 2014-09-29 18:45:19

+0

出於好奇,你打算使用什麼樣的格式化工具? Jalopy還是別的? – 2014-09-29 21:24:53

+0

我們解決的工具是從[命令行](http://blogs.operationaldynamics.com)調用Eclipse的代碼格式化程序(實際上是它的修補版本,因爲最新的版本存在對我們不起作用的錯誤) /安德魯/軟件/ java的侏儒/蝕碼格式從 - 命令行)。這有點慢,但是我們看到的其他一些工具讓我們無法理解。 – Karthik 2014-09-29 21:30:38

回答

1

回覆1:--tree-filter不需要單獨承諾:它只是轉儲相應的一些樹提交到一個臨時目錄,運行您的過濾器,然後取生成的目錄作爲新樹新承諾。 所有改變,包括創建或刪除文件,導致不同的「新」的承諾,並作爲手冊頁筆記,.gitignore而不是使用的所有其他無視規則(所以如果你創建一個.bak文件或什麼的,並且通常只需.gitignore它,你必須在你的樹型過濾器中手動刪除它)。

所有這些工作都在git的base「rewrite」臨時目錄的子目錄中完成,您可以使用-d來設置它,但默認爲.git-rewrite。 (過濾器的子目錄 - 所有這些過濾器(包括樹形過濾器)都是$tempdir/t,但這不應該是相關的。)它也都是使用特殊臨時索引(臨時區域)文件($tempdir/index)完成的。

請注意,整個臨時目錄被刪除的時間爲git filter-branch出口。


回覆2:是的,它可能保存待過濾的ID,它在$ GIT_COMMIT(環境變量)的所有過濾器運行的持續時間。 (由於過濾器大部分都是eval ed,所以您甚至可以修改環境以傳遞其他變量或更改一些;請參閱過濾器分支腳本)。


回覆3:基本上,--index-filter--tree-filter之間的不同之處在於--tree-filter提取樹到一個臨時目錄,運行您過濾,然後捲起的(可能已修改的)樹,以使新樹的新承諾。相反,--index-filter將樹加載到索引文件中;運行你的過濾器,它可以修改索引;然後使用生成的索引爲新提交創建新樹。

換句話說,樹過濾器實際上解包並重新打包索引。這就是索引過濾器更快的原因:它會跳過解壓縮/重新打包步驟。如果您必須修改實際的文件,將其全部解壓縮,修改所有文件並重新打包所有文件顯然更簡單。如果許多文件不會被修改,您可以獲得一些速度,通過解壓縮有趣的文件,修改這些文件並重新打包修改後的結果,但要做到這一點,您需要一定的低劣git知識。 (這很容易git checkoutgit add每個文件,當您去,但你也必須找到哪些文件進行修改。)

1

由於the BFG(更快,更簡單git-filter-branch替代)的作者,我傾向於給提到它,雖然它不是開箱即用的,但是要做Java源代碼重新格式化。

你提到git-filter-branch操作的故障恢復會很有幫助 - 那當然是因爲git-filter-branch太慢了。有no way to resume a git-filter-branch手術 - 但如果它更快,它不會是一個很大的問題。 BFG可以是many hundred times faster而不是git-filter-branch,因爲它只會清理任何給定版本的文件 - 不像git-filter-branch,它每次都會清理同一個文件,每次提交。

BFG支持文件中的直接文本替換,但正如我所說的,它不會執行Java源代碼重新格式化。有將是獲得該工作兩種選擇:

  1. 調用BFG圖書館,爲Christian Hoffmeister recently did - 在你的情況下,通過在自定義TreeBlobModifier調用Jalopy或一些其他的Java源代碼格式化。
  2. 更改BFG,使其支持脫殼以調用任意bash命令 - 有點像git-filter-branch--tree-filter--index-filter - 但我仍然期望它的速度更快。

選項2不會很難實現。但是,我想知道您是否可以詳細說明爲什麼要採取這種激烈的行動 - 重寫歷史記錄?相對於重寫提交和讓每個人適應已改變的歷史的麻煩,是否真的有一個很好的格式化歷史的好處?爲什麼不直接對最新的提交進行一次性格式化?

+0

在內部,我們已經反覆討論了是否需要重寫git。我們想出了很多數字,而不是重寫方式會將10%-12%的代碼庫錯誤地歸因於錯誤的作者,因此重寫是我們唯一的選擇。 – Karthik 2014-09-29 21:09:46

+0

我聽說過很多關於BFG的知識,並且曾經考慮過它,但唯一阻礙我的是它沒有處理樹型過濾器,這是我認爲我們需要的。 – Karthik 2014-09-29 21:10:35

+0

沒有「開箱即用」的方式來恢復過濾器分支,但理論上它可以完成(複製過濾器分支腳本,對它進行相當多的修改,等等:-))。這可能沒有完成,因爲重寫歷史是痛苦的,即使它完全正常工作。 – torek 2014-09-29 23:28:49

相關問題