我有一个git存储库(包含或多或少的项目历史记录)和一些源代码(只是一个带有少量文件的tarball),这些源代码已经分了一段时间(实际上是在2004年或2005年的某个地方)。
tarball的来源经历了很多变化,我想从中加入一些变化。现在的问题是 - 如何找出变化的源的实际分支点,以获得最小的差异。
所以我基本上想要的是在git历史中找到位置,其中代码与我拥有的源代码的tarball最相似。我不想手动这样做。
还值得一提的是,更改的源仅包含文件子集,并将一些文件拆分为更多。然而,那里的代码似乎只有很少的修改和几个补充。
如果你想自己玩这个游戏,那么带有来源的tarball就是here而Git会在Gitorious托管:git://gitorious.org/gammu/mainline.git
答案 0 :(得分:4)
在一般情况下,你实际上必须检查每一次提交,因为你无法知道你是否有一个巨大的差异,下一个是小差异,然后是另一个巨大差异,然后是中等差异...
您最好的选择可能是限制自己使用特定文件。如果您只考虑一个文件,则迭代该文件的所有版本不应该花费很长时间(使用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
获取所有具有diff大小的提交的好列表(前三列将是SHA1,添加的行数和删除的行数)。然后你可以把它传递到awk '{print $1,$2+$3}' | sort -n -k 2
,你就会有一个提交的排序列表及其差异大小!
如果你不能将自己限制在一小部分要测试的文件中,我可能会试图手工实现与git-bisect
类似的东西 - 只是尝试缩小你的方式到一个小的差异,使假设在最好的情况下接近最差情况下的提交也会有较小的差异,而远离它的提交会产生较大的差异。 (在Newton的方法和完整的二进制/网格搜索之间,可能?)
编辑:Douglas' answer中建议的另一种可能性,如果您认为某些文件可能与某些提交中的相同,则使用git-hash-object
对其进行哈希处理,并且然后看看你的历史中有什么提交。关于如何做到这一点question with some excellent answers。如果你使用少量文件(最好经常更改的文件)执行此操作,您可以很快缩小目标提交范围。
答案 1 :(得分:2)
不是一个很好的解决方案,但要猜测它可能是哪些修改:假设tar球中的某些文件由于它们已经分支而没有被更改。对tar球中的每个文件运行git hash object,然后使用git show在存储库中搜索这些文件。然后尝试找到包含这些文件的提交,可能使用git whatchanged。你的问题的答案可能是提交最常见的文件,但它仍然会有点受伤。
答案 2 :(得分:1)
根据araqnid的说法,我想出了9c6c864426bf88429e77c7e22b5aa78e9295b97a(只是要求介于0.61.0和HEAD之间的东西)这可能不是最好的)你可能会用
这样的东西做得更好git rev-list --no-merges --all | while read rev; do patchsize=$(git diff $rev | wc -c); echo $patchsize $rev; done | sort -n | less
假设您已将tarball导入git并检出该修订版(我通过解压缩然后
执行此操作git init
git add .
git commit -m "import tarball"
git remote add origin git://gitorious.org/gammu/mainline.git
所以在你这样做并运行上面之后它应该以patchsize的升序输出所有差异的大小(第一个将是0,因为它会找到当前的头部)它需要很长时间......但它应该找到最小的差异......
答案 3 :(得分:0)
叉子是怎么做的?它是别人制作的克隆,然后做了自己的工作吗?如果是这样,那真的很容易。你需要做的就是创建一个从fork中提取代码的本地分支。 git将看到forked分支的祖先指向你原始存储库中的一个提交,并将“连接点”可以说......它将重新连接从原始存储库到fork的历史记录。
你应该能够做到这一点:
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
并查看分叉分支和本地存储库的完整历史记录,看看它们是否连接。
答案 4 :(得分:0)
将tarball中的文件导入git修订版,在单独的分支或全新的分支上:修订图中的位置并不重要,我们只希望它以树形式提供。
现在对于master中的每个修订版,只需对该树/修订版('imported')进行diff操作,然后输出diff的大小。类似的东西:
git rev-list master | while read rev; do patchsize=$(git diff $rev imported | wc -c); echo $rev $patchsize; done
因此,通过非常粗略的经验法则,具有最小补丁大小的修订将是“最接近的”。 (相同的修订版将产生0的补丁大小,其他任何东西肯定都不为零,并且变化越多,越大)。
答案 5 :(得分:0)
如果您对叉子的位置有一个粗略的想法,请考虑使用Will Manley的git meld
。 (另见:View differences of branches with meld?。)
要执行此操作,请将tarball内容添加到您的存储库(无论如何您都将执行此操作)。安装Meld和git-meld
后,运行
git meld branch_from_tarball commit_to_check &
在不同的提交上,直到找到差异最小的提交。此命令将打开meld
并查看指定提交之间目录树中的更改,并隐藏相同的文件。屏幕截图示例:
Meld显示两个非常不同的提交:
显示两个类似的提交: