8

我有一个 git 存储库(涵盖或多或少的项目历史)和单独的源(只是一个带有少量文件的 tarball),它们在一段时间前(实际上是在 2004 或 2005 年的某个地方)分叉了。

来自 tarball 的源代码已经发生了很多变化,我想从中加入一些变化。现在的问题是 - 如何找出更改源的实际分支点,以获得那里发生的事情的最小差异。

所以我基本上想要的是在 git 历史中找到一个位置,该位置的代码与我拥有的源代码最相似。而且我不想手动执行此操作。

还值得一提的是,更改后的源仅包括文件的子集,并且已将一些文件拆分为更多文件。然而,其中的代码似乎只进行了小的修改和一些添加。

如果你想自己玩,带有源代码的 tarball 在这里,Git 托管在Gitoriousgit://gitorious.org/gammu/mainline.git

4

6 回答 6

4

在一般情况下,您实际上必须检查每一个提交,因为您无法知道您是否可能有一个巨大的差异,然后是小差异,然后是另一个巨大的差异,然后是中等差异......

您最好的选择可能是将自己限制在特定文件中。如果您只考虑一个文件,那么迭代该文件的所有版本应该不会花费很长时间(用于git rev-list <path>获取列表,因此您不必测试每个提交)。对于修改文件的每个提交,您可以检查差异的大小,并很快找到最小值。对少数文件执行此操作,希望他们会同意!

设置差异的最佳方法是通过简单地复制到您的 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- 只需尝试将您的方式缩小到一个小的差异,假设很可能提交接近在你最好的情况下,差异也会更小,远离它的提交也会有更大的差异。(可能介于牛顿方法和完整的二进制/网格搜索之间?)

编辑:道格拉斯的回答中建议的另一种可能性,如果您认为某些文件可能某些提交中的文件相同,请使用 对它们进行哈希处理git-hash-object,然后查看您的历史记录中的哪些提交具有该 blob。关于如何做到这一点,有一个问题有一些很好的答案。如果您使用少量文件(最好是经常更改的文件)执行此操作,您可能能够很快缩小目标提交的范围。

于 2010-06-23T16:27:38.630 回答
2

不是一个很好的解决方案,但要猜测它可能是哪些修订:假设 tar 球中的某些文件自从分支后没有更改。对 tar 球中的每个文件运行git hash object ,然后使用git show在存储库中搜索这些文件。然后尝试查找包含这些文件的提交,可能使用git whatchanged。您的问题的答案可能是最常见文件的提交,但它仍然会有点命中注定。

于 2010-06-23T16:21:58.517 回答
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 并检查了该修订版(我通过 untaring 然后

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

所以在你这样做并运行上面它应该输出所有差异的大小以patchsize的升序排列(第一个将是0,因为它会找到当前的头)它需要很长时间......但它应该找到最小的差异......

于 2010-06-23T18:41:49.597 回答
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并查看分叉分支和本地存储库的完整历史记录,并查看它们是否连接。

于 2010-06-23T15:54:44.760 回答
0

将 tarball 中的文件导入到 git 修订版中,在单独的分支上或全新的分支上:修订图中的位置并不重要,我们只希望它作为树可用。

现在对于 master 中的每个修订版,只需针对该树/修订版(“导入”)进行比较,然后输出差异有多大。就像是:

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

因此,根据非常粗略的经验法则,具有最小补丁大小的修订版将是“最接近的”。(相同的修订版会产生 0 的补丁大小,其他任何内容肯定会不为零,并且更改的越多,越大)。

于 2010-06-23T16:29:14.100 回答
0

如果您对分叉发生的位置有一个粗略的了解,请考虑使用 Will Manley 的git meld. (另请参阅:查看分支与融合的差异?。)

为此,请将 tarball 内容添加到您的存储库(无论如何您都会这样做)。安装 Meld and 后git-meld,运行

git meld branch_from_tarball commit_to_check &

在不同的提交上,直到找到差异最小的提交。此命令将打开meld并查看指定提交之间的目录树中的更改,并隐藏相同的文件。示例截图:

Meld 显示了两个非常不同的提交:
非常不一样

显示两个类似的提交: 相似的

于 2013-01-11T19:18:11.907 回答