2013-08-01 48 views
17

問題

既然我已經提交類似如下:我如何簡單地線性化我的git歷史記錄?

A - B - C - D - G - H 
    \  /
     - E - F - 

如何獲得以下僅第一家長完全線性的歷史?

例如,我想:

A - B - C - D - G'- H' 

據預計,G和H的SHA1的會發生變化,如上所述。 (由於顯而易見的原因)。如果sha1的A,B,C和D也改變,那麼我想知道爲什麼。

背景

的目的是爲了避免潛在的合併的提交,將做一個天真的git的變基-i時,會出現。

真正的問題是希望更深入地瞭解,以確定哪些提交是在一個特定的分支,例如,如果我們有如下圖:

I - J - K - L - M 
\ ///
    - N - O - P - 

其中N被合併到K,但Ø與--strategy = our合併爲L,P合併爲M.

我希望能夠線性化我的歷史記錄,以便可以識別和檢查此類有問題的提交。我希望有一棵樹可以識別出O沒有放入上游分支,即使我可能通過使用git cherry也可能將N和P識別爲可能從上游分支丟失,但是這裏的任何建議都將被讚賞。

+2

要改寫你的問題,你想修改每個合併提交,只保留其第一個父,忘記合併的分支(保留差異當然) – CharlesB

+0

@CharlesB:是的,沒錯! – Arafangion

回答

17

正如你所說的,下面的命令作品:

git filter-branch --parent-filter 'cut -f 2,3 -d " "' 

爲什麼?

您提出的問題可以通過使用簡單的提交來轉換每個合併提交來解決:這將簡單地移除合併的特徵分支,因爲它們將變成孤立。

每個提交都有一個或多個父提交。合併提交是獲得多個合併的提交。 Git將它存儲在歷史記錄的每個提交對象中。

git filter-branch命令,用--parent-filter選項,允許重寫所有提交的母公司,傳遞給過濾器-p SHA1,重複,如果有一個以上的父母。我們的過濾器會削減父母,並強制每個承諾擁有一位父母。

對於獎金,這裏是如何做手工的精確提交,通過重新創建一個新的提交:

  • 得到承諾樹和第一父

    tree=`git show -s --format=%T SHA1` 
    parent=`git show -s --format=%P SHA1 | cut -d " " -f1` 
    
  • 化妝一個新的提交具有相同的樹,相同的消息,並且只保留第一個父代作爲祖先

    git show -s --format=%B SHA1 | git commit-tree $tree -p $parent 
    
+1

這讓我想起了:'​​git filter-branch --parent-filter'cut -f 2,3 -d「」''看起來很有效,但我還不確定邊緣情況或性能。不過,我確實有數百個相當大的提交。我會等待你的回答,你可能會有更好的/更好的解決方案。 – Arafangion

+0

我不知道,但似乎簡單得多。我想在這種腳本中使用'--commit-filter',但我也看到了'--parent-filter'選項,儘管我不明白你的命令中的'cut -f 2,3'是什麼? – CharlesB

+0

父過濾器指定了一個程序,需要stdin中的輸入,如'-p sha1 -p sha1 -p sha1',每個-p指定一個父項。 (該字符串與三位父母合併提交)。 '-d'「'指定我們將其解釋爲由空格分隔的列表。 -f指定了「Take the second,and third item」。這導致第一個'-p sha1',我們完成了。 – Arafangion

5

具有以下手工進行:

git rebase -i D-sha1 

編輯文件有G設置爲「編輯」。保持「選擇」H.保存並關閉編輯器。

現在Git允許您編輯G commit,讓我們將其修改爲F commit的壓縮合並。你想:

#cancel the merge commit and position HEAD to D 
git reset --hard HEAD~ 
#squash merge and continue 
git merge --squash F-sha1 
git rebase --continue 

請注意,你必須解決同樣的矛盾,如果你不得不在第一合流......

正如你說你只會有新的SHA1對G和H.

+0

我如何識別'G'和'H'?可以說我有一個大型倉庫。不僅僅是我強調的微不足道的情況,還有許多這些合併提交。 – Arafangion

+0

如果過於複雜的歷史,不同的合併提交會線性化,那麼您可能會遠離這一點。 Git rebase不會正確地執行它 – CharlesB

+0

我完全知道git rebase不會這樣做。我期待的答案將涉及git filter-branch和--parent-filter集合。 – Arafangion

相關問題