为什么git-cvsimport缺少一个主要的补丁集?

5
这是我的以前的一个问题的后续。
我可以查看cvsps的输出(保存在我的~/.cvsps目录中),并查看一个重要且复杂提交的补丁集。但是,当我执行cvsimport更新现有的git存储库时,此提交不会显示出来。我知道git-cvsimport将忽略比10分钟更新的补丁集,以避免导入不完整的CVS提交。我认为我也听说过它会跳过无法识别相关分支的补丁集。还有哪些原因可能导致git-cvsimport忽略我的提交?我该如何调试?
这是一小部分cvsps输出:
patchset: 50064
date: 1238445635
author: skiphoppy
tag: 
tag_flags: 0
branch: HEAD 
branch_add: 1
descr:
My log message

-=-END CVSPS DESCR-=-
members:
file:ordinaryChangedFile; pre_rev:1.44; post_rev:1.45; dead:0; branch_point:0
file:newFileRenamedAndModifiedFromOldFile; pre_rev:INITIAL; post_rev:1.1; dead:0; branch_point:0
file:deletedFileGoneBecauseRenamed; pre_rev:1.2; post_rev:1.3; dead:1; branch_point:0
...

那个branch_add:1行与此有关吗?整个代码库中只有9个这样的提交;其他50090个提交都是branch_add:0。除此之外,我不知道从cvsps或git-cvsimport的角度来看有什么区别。该提交很复杂,涉及重命名多个文件和进行相关内容修改。对于CVS来说肯定很困难。当然,对于Git来说是小菜一碟,但是当真正的后端是CVS时,Git很难处理。

我还要执行三次相同类型的复杂提交,我不能每次都花4个半小时从CVS重新导入全新的Git存储库,因为cvsimport无法查看我的提交。

更重要的是,我担心我的每日运行git-cvsimport(我打算将其放入cron,甚至编写守护程序每隔五分钟运行一次)可能会错过未来的提交!我找不到让现有存储库捕获这些提交的方法;我只能在全新存储库中运行git-cvsimport并永远等待,同时失去使用许多其他分支的机会。

4个回答

7

嗯,这可能是问题所在。我的git-cvsimport命令如下:

git cvsimport -p x ...

-p x选项被用来将-x选项传递给cvsps,以告诉它忽略之前运行留下的缓存输出。我认为这样做的主要原因是为了丢弃可能不完整的最后几个补丁集,并在下次运行时完成。事实证明,它修复的问题可能更多,这可能是其中之一。
我从这篇博客文章中学到了以这种方式运行git cvsimport的方法,该文章目前是“git cvs”的谷歌搜索结果中排名最高的之一。只有在上述过程中,当我尝试通过Perl调试器运行git-cvsimport并检查真正传递给cvsps的参数时,我才发现cvsps被这样运行:
cvsps --norc x --cvs-direct ...

改为:

cvsps --norc -x --cvs-direct ...

我进行了实验验证,发现当使用-x代替x时,从cvsps得到的输出不同,并且一些补丁集会丢失(我不知道这种情况的模式是什么),由于墨菲定律的作用,cvsps似乎没有报告这个问题,因此git-cvsimport从未察觉。

因此,无论如何,需要像这样运行git cvsimport:

git cvsimport -p -x ...

我的之前的代码库已经彻底崩溃了,但我已经成功地将最后的问题提交强制合并到了它们中(尽管一些早期的提交丢失了)。所以我需要再次进行四小时的导入过程,希望这次就可以了!

最后一个提示:在 Windows 上使用 git-cvsimport 似乎根本不起作用。尽管我最终得到了类似于我们项目当前状态的树形结构,但我只得到了不到 10% 的提交次数,而且几乎所有历史记录都丢失了...


兄弟,这真的很有帮助。我使用了同样的文章并受到了伤害。 - joshk0
很高兴听到它有所帮助。cvsimport仍然存在一些错误,但希望您不会遇到它们。 :) 您是在进行一次性转换,还是将来会被困在原始的CVS存储库中进行交互? - skiphoppy

3
非常感谢!我遇到了同样的问题,通过您的帮助解决了!
我甚至找到了一个避免从头重新运行cvsimport的方法。只需将'master'和'origin'分支设置为较旧的git提交即可使cvsimport重新导入补丁,因为它包括缺失的补丁:
找到比缺失提交更旧的提交ID:
git log
将'origin'指向该提交
git branch -f origin
切换到'origin'(这样'master'不是当前HEAD)
git checkout origin
现在将'master'也指向较旧的提交
git branch -f master origin
切换回'master'
git checkout master 现在,时间完全回滚,您可以再次进行cvsimport,这次将会正确执行
git cvsimport ...

1
如果您不介意稍后重新基于或合并,则无需重置主分支。对我来说,只是回滚原点就解决了这个问题。 - Koterpillar

1
最近我遇到了这样的问题 - 在使用git cvsimport命令之后,CVS里面的提交记录没能在git里面显示出来; 而后续的提交记录却可以正常显示(这给我带来了很大的麻烦,因为我随后又制作了不可用的补丁)。
不过解决方法非常简单和愚蠢 - 我只是重置了缺失提交记录之前的cvs/master分支,然后重新运行git cvsimport即可。

很好,我打算尝试一下,虽然我没有意识到我可以移动cvs/master(它是我的repo中的远程分支)。我也有些担心,因为我不知道为什么第一次失败了,这次为什么会成功。但至少这是一个正确方向的指针! - skiphoppy
这对我来说也是一个远程分支。我模糊地记得做了一些非常恶心的事情 - 要么我使用了管道,要么(更可能的是)我只是执行了“echo 123456789abcdef > .git/refs/remotes/cvs/master”(其中123...应该是您想要重置到的提交的sha1)。 - jpalecek
我也不知道为什么这个提交被错过了,第二次才进入代码库。你说你是Perl程序员,也许你可以调试一下 - 尽管这可能很麻烦,因为它只会偶尔发生。 - jpalecek
另一种可能性是"我用远程分支做了什么"的方法是将其更改为具有相同名称的本地分支。现在我真的不确定了。 - jpalecek

-1

好消息是git-cvsimport似乎是用Perl编写的,而我恰好是一名Perl程序员,所以也许我至少可以使用Perl调试器逐步查找提交期间发生了什么。

对于任何想尝试这个的人,你必须找到git-cvsimport的完整路径,并将其提供给perl(Perl解释器)并使用-d开关:

perl -d /usr/local/libexec/git-core/git-cvsimport

我还没有想好其他选项来完成这个任务...我认为我需要直接将cvsps的输出提供给git-cvsimport。


如果您解决了问题,请提交一个bug或补丁或失败的单元测试到git邮件列表,以便为所有使用这个(不幸必需的)工具的人解决这个问题。 - Brian Phillips
1
明白了!!!又发生了...一个时间戳刚好是十分钟前的补丁集将被跳过,随后的补丁集将被导入,然后你就完了。我会报告这个问题的。 :) - skiphoppy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接