2010-06-23 32 views
8

我有一個git倉庫(包括或多或少的項目歷史記錄)以及前段時間(實際上是在2004年或2005年某處)分開的源代碼(只是一個包含少量文件的tar包)。尋找源代碼從git分支的地方

來自tarball的資源已經經歷了很多變化,我想從中進行一些整合。現在的問題是 - 如何找出變化的信號源的分支點,以便對發生在那裏的事情進行最小的區分。

所以我基本上想要的是在git歷史中找到地方,代碼與我擁有的源代碼的tarball最相似。我不想那樣手動。

還值得一提的是,更改後的源只包含文件的子集,並將一些文件拆分爲更多。然而,在那裏的代碼似乎只有很小的修改和幾個補充。

如果你想與自己玩,一起源的壓縮包是here和Git在Gitorious託管:git://gitorious.org/gammu/mainline.git

+1

我注意到在該焦油最舊的文件進行了修改上31/10/2006 12: 57。我會在那裏開始我的搜索。 – Douglas 2010-06-23 16:25:18

+0

正如原來的帖子中提到的,我大致知道他們在2004/2005年的某個地方分叉了,但這仍然太過於手動調查。 – 2010-06-23 16:35:18

回答

4

在一般情況下,你實際上必須檢查每一個提交,因爲你無法知道你是否可能在一個巨大的差異,小差異下一個,然後另一個巨大的差異,然後媒體diff ...

你最好打賭可能是限制自己到特定的文件。如果您只考慮單個文件,則不需要很長時間就可以迭代該文件的所有版本(使用git rev-list <path>可以獲取列表,因此您不必測試每個提交)。對於每次修改文件的提交,您都可以檢查diff的大小,並相當快地找到最小值。爲少數文件做這件事,希望他們會同意!

爲自己設置差異的最好方法是通過簡單地複製你的tarball來臨時提交,所以你可以有一個叫tarball的分支來比較。這樣一來,你可以這樣做:

git rev-list path/to/file | while read hash; do echo -n "$hash "; git diff --numstat tarball $hash path/to/file; done 

讓所有與他們的差異大小的提交的一個很好的列表(前三個欄將是SHA1,添加的行數和刪除的行數)。然後,您可以將它輸入到awk '{print $1,$2+$3}' | sort -n -k 2,並且您將有一個提交列表和它們的差異大小!

如果您不能將自己限制在一小部分要測試的文件中,我可能會試圖手動執行一些與git-bisect類似的操作 - 只是嘗試縮小範圍以縮小差異,假設在所有可能性,提交接近你的最好情況也將有較小的差異,並承諾遠離它將有更大的差異。

(某處之間牛頓法和全二進制/網格搜索,大概?)編輯:另一種可能性,在Douglas' answer建議,如果你認爲某些文件可能是相同那些在某些承諾,是哈希他們使用git-hash-object,然後看看你的歷史中有什麼提交有這個blob。有關於如何做到這一點的question with some excellent answers。如果你用一些文件來做到這一點 - 最好是經常改變的文件 - 你可能能夠很快縮小目標提交的範圍。

+0

我認爲開始限制你正在查看的文件集合的好地方可能是兩個文件都是共同的,但是很長一段時間沒有改變,或者很少在任何一個(或者更好但是)樹中改變。頭文件可能是很好的候選者,只要它們不包含太多瘋狂的預處理條件。量化'#define'長行的差異變化比實際的代碼更容易。 – nategoose 2010-06-23 21:16:00

+0

這似乎是最好的辦法。我只是改變它不使用單個文件,而是一個完整的文件列表,我已經在改變的樹和有限的修訂列表中間隔我猜測一些代碼部分。謝謝。 – 2010-06-24 09:50:47

+1

這對我來說非常好,但是,我提供此警告:如果您要在* nix和Windows(或Mac)之間移動文件,*請注意LINE FEEDS *。給diff命令指定-w選項,這樣它會忽略它們,否則你可能會得到一個巨大的差異,當兩個文件除了換行以外都是相同的。 – 2011-01-14 06:20:56

0

是如何叉做?這是其他人制作的一個克隆,然後做了他們自己的工作?如果是這樣,那麼這很容易。所有你需要做的就是創建一個本地分支,從fork中提取代碼。 git將會看到分支分支的祖先指向你的原始倉庫中的一個提交,並且會「連接點」,可以這麼說......它會將歷史從原始倉庫重新連接到分支。

你應該能夠做到這一點:

git remote add thefork git://wherever.it.lives/thefork.git 

git fetch thefork 

git branch -f thefork-branch thefork/branchname 

git checkout thefork-branch 

在這一點上,你可以運行gitk,看到分叉處的全部歷史和本地資源庫,看看他們是否連接與否。

+0

啊,我不清楚分叉的來源只是一個tarball,實際上並不是git回購。將更新的問題說清楚。 – 2010-06-23 16:05:36

+0

哎!是的...這對我來說是新的...不知道我知道如何處理這種情況。 – 2010-06-23 16:14:56

2

不是一個好的解決方案,而是猜測它可能是哪些版本:假設tar球中的一些文件自分支以來沒有更改過。針對tar文件中的每個文件運行git hash object,然後使用git show在存儲庫中搜索這些文件。然後嘗試找到包含這些文件的提交,可能使用git whatchanged。你的問題的答案可能是最常見的文件的提交,但它仍然會有點擊中和錯過。

+0

這實際上是個好主意 - 我寫了我的答案,假設所有文件都有小差異,所以你將無法在回購庫中找到確切的版本。 – Cascabel 2010-06-23 16:28:43

+0

好主意,不幸的是沒有文件沒有改變。 – 2010-06-23 16:34:14

+0

@MichalČihař:然後繼續閱讀我的答案,該答案提供了一些基本方法來嘗試找到最小差異版本! – Cascabel 2010-06-24 00:11:22

0

將壓縮包中的文件導入到git修訂版本,單獨的分支或全新的版本中:修訂圖形中的位置並不重要,我們只是希望它可用作樹。

現在對於master中的每個修訂,只需比較該樹/修訂版('導入的'),然後輸出diff的大小。例如:

git rev-list master | while read rev; do patchsize=$(git diff $rev imported | wc -c); echo $rev $patchsize; done 

因此,通過非常粗略的經驗法則,具有最小補丁大小的修訂將是「最接近的」。 (一個相同的版本會產生一個0的補丁大小,而其他任何東西肯定是非零的,並且更多的變化,更大的)。

+0

不幸的是,對整個樹進行比較總是會導致最舊的版本,因爲它沒有太多額外的文件。 – 2010-06-24 09:28:11

1

基於上述,我想出了9c6c864426bf88429e77c7e22b5aa78e9295b97a(只是尋求的東西0.61.0和頭之間),這可能不是最好的),你可能會與一些做的更好像

git rev-list --no-merges --all | while read rev; do patchsize=$(git diff $rev | wc -c); echo $patchsize $rev; done | sort -n | less 

假設你什麼araqnid」已經進口包到Git和有修訂簽出(我不希望這untaring然後

git init 
git add . 
git commit -m "import tarball" 
git remote add origin git://gitorious.org/gammu/mainline.git 

所以你做到這一點,運行上面的輸出它應該找到所有不同的升序排列後的大小patchsize(第一個將是0)因爲它會找到當前的頭)它需要很長時間...但它應該找到最小的差異...

0

如果您對叉子發生的位置有一個粗略的想法,可以考慮使用Will Manley's git meld。 (另見:View differences of branches with meld?。)

要做到這一點,請將tarball內容添加到您的存儲庫(無論如何您都會這樣做)。安裝MELD和git-meld,在不同的運行提交

git meld branch_from_tarball commit_to_check & 

,直到找到一個用最少的不同之處後。該命令將打開meld並查看指定提交之間目錄樹中的更改,並隱藏相同的文件。示例屏幕截圖:

MELD示出兩個完全不同的提交:
Very different

顯示兩個類似提交: Similar