2013-02-03 124 views
2

有一個簡單的應用程序的完整源代碼,並需要創建教材基於它。所以,我在想,從完整的源代碼創建一個git倉庫,然後開始按照相反的順序簡化和刪除部分,然後提交每個更簡單的工作版本,直到只有一個「Hello,World!」。遺蹟。如何翻轉Git倉庫

問題:如何在git存儲庫中提交提交,保留提交消息等,以便它看起來像它最初按此順序提交?

只要最終結果是git倉庫,可以使用任何其他VCS來完成簡化部分。

+0

爲什麼要真正地爲此改變歷史?你可以走過去提交 –

+0

我不認爲git現在有這個功能。你可以嘗試爲它編寫一個shell腳本。 – fuz

+0

@NevikRehnel在教學情境中,任何偏離「正常」的偏差,不管是老師解釋它還是掩蓋它,都會讓老師和學生分心,並且如果可能的話通常應該避免。 – hyde

回答

2

我寫了一個腳本「git-reverse.sh」,它完全顛倒了git倉庫的所有分支。

它使用git log --pretty="%T"的組合提取樹散列,並使用git commit-tree來針對原始樹對象(文件)創建新的提交對象,但父邊反轉。

它似乎陷入了一些回購。我不知道爲什麼。

你可以在這裏找到:

https://github.com/gsylvie/git-reverse.sh

使用示例

git clone --mirror [git-clone-url] 
cd [repo.git] 
./git-reverse.sh 
git log --all --date-order --graph --decorate 

示例輸出

$ ./git-reverse.sh 
be0923ece8f73281e5e54906c29debb852894b92 - Reversed 1 of 360 (0%) 
061bca59b29e75becbde66d2e510fc2b4059ccb2 - Reversed 2 of 360 (0%) 
6a19039e05e3a0186187d0a6943634e8499b5a65 - Reversed 3 of 360 (0%) 
7afe25e8caf93eb7107471a1bd078d4adc3f6999 - Reversed 4 of 360 (1%) 
8b556f6fe97c5357c2328467a5ba01b77931ff82 - Reversed 5 of 360 (1%) 
71fd0883975154f48059ca929db8ccb659c5049a - Reversed 6 of 360 (1%) 
[etc...] 
Switched to branch 'master' 
Your branch and 'origin/master' have diverged, 
and have 199 and 159 different commits each, respectively. 
    (use "git pull" to merge the remote branch into yours) 

********************************************* 
| Git repo successfully reversed!!! :-) (-: | 
********************************************* 
To push the reversed repo: 
    rm .git/packed-refs 
    rm -rf .git/refs/remotes 
    git push --mirror [new-git-clone-url] 

WARNING: 
======== 
Pushing a reversed git repo is a profoundly destructive and confusing operation. 

You have a full 'git clone --mirror' backup stored somewhere safe, right? 
2

我會使用git format-patch來獲取補丁到文件中,按順序排序(編號文件名,然後sort -r),並使用git apply --reverse作爲新提交應用到新的空存儲庫。然後,我將使用交互式底圖(-i)來修復細節並提交消息。

無論如何,git是這個可以很容易地用歷史操縱的工具,但它需要一些工作。

編輯:

當我看到這個以後,我有一個更好的主意如何做到這一點。它不會改變基本原理,只有實現:

我想,你有一個在master分支中有歷史記錄的倉庫。因此,要提交過電流HEAD最簡單的方法是這樣的:

git checkout -b mirror 
git log --format=%H | xargs -n 1 git revert 

現在你有悠久歷史的主分支和掌握與鏡子之間的新的提交反轉從主提交。就像照鏡子一樣。我想你會想刪除舊的歷史和編輯提交消息,所以請與git rebase -i一起玩。

+0

是的,這可能是或多或少的事情。我很快就會接受你的回答(ish),除非有人加緊寫下腳本;) – hyde

+0

這是你的腳本;) –

+0

謝謝!看起來比shell'for'循環的東西好多了:) – hyde

1

如果存儲庫中的提交數量有限(我認爲這是你正在製作教材的情況),我想你可能只是按照相反的順序手動執行櫻桃選擇。

A <- B <- C <- D <- E 
        ^HEAD 

設A是第一個提交裏面是空的,而B是全套文件,而CDE正在逐步刪除文件,我想你可以通過另一分支在一個

A <- B <- C <- D <- E 
^NewHead   ^HEAD 
啓動

和櫻桃挑E,d,C,B,以新頭:

A <- B <- C <- D <- E 
^     ^HEAD 
    \- E' <- D' <- C' <- B' 
         ^NewHead 

當然,如果真的有大量的提交,出口補丁和進口(由OTH的建議之前使用腳本來操縱它們呃答案)可能是更好的選擇

0

首先我不明白你爲什麼需要改變提交。您可以按任何順序簽出相應的版本。即git checkout master~1,顯示,git checkout master~2,顯示,等等。

如果你真的需要它有你的歷史,然後嘗試使用revert重播歷史回來。例如。 git revert HEAD~5..HEAD將按相反順序恢復最後5次提交。但是,它會生成提交消息,說它是Revert "old commit message"。但是你可以編寫一個腳本來修改消息。

+0

好吧,當在github上查看歷史記錄時,或者只是'git log'時,它應該看起來像「正常」。另外,提交不需要改變,確切地說。需要生成具有所需順序提交的存儲庫。所以,正如其他答案中所解釋的那樣,它可能是一個簡單的shell腳本,導出最後一個源代碼,從中啓動新的repo,然後以相反的順序反向應用其他repo的commit diff。我只是問是否有一個現成的方法來完成這個任務,而不是在一起定製shell腳本。 – hyde

+0

你可以用git revert和rebase來實現它。唯一的問題是'revert'產生特殊的提交信息......不知道處理它有多容易。 – kan