无损迁移CVS到Git的历史记录

44

我想知道是否有一种方法可以将我的代码从CVS源代码控制迁移到Git?

如果是的话,那么我的提交历史记录怎样处理?


这里有一个很好的答案解决了你的问题 :) https://dev59.com/TXNA5IYBdhLWcg3wpfmu#17135045 - Lionel P.
1
可能是从CVS到Git的迁移工具存在吗?的重复问题。 - kolen
@kolen:看起来是这样。 - einpoklum
我在 Stack Overflow 上找不到一个好的解决方案,但是我在 https://superuser.com/a/1451527/120672 找到了一个很棒的。 - Ken Williams
9个回答

30

以下是我使用cvs2git工具,将SourceForge的CVS仓库迁移到了Git。这个工具可以在Windows和Linux上使用,不需要编译,因为它只是用Python写的(最新版本在此处,但我记得我使用的是GitHub开发版本)。

此外,使用这种方法时,您不需要拥有该仓库,例如,您可以将您没有所有权的SourceForge项目进行迁移(您只需要有检出权限,因此它适用于任何公共仓库)。

如何从SourceForge的CVS导入到Git。
首先,您需要下载/检出CVS仓库的整个历史记录(而不仅是HEAD/Trunk):

rsync -av rsync://PROJECT.cvs.sourceforge.net/cvsroot/PROJECT/\* cvs

然后使用cvs2git(Python脚本,在所有平台上均可工作,无需编译):

python cvs2git --blobfile="blob.dat" --dumpfile="dump.dat" --username="username_to_access_repo" --options=cvs2git.options --fallback-encoding utf-8 cvs

这应该会生成两个文件,blobdump,包含了您的整个cvs历史记录。您可以在文本编辑器中打开它们,检查内容是否正确。

然后在另一个文件夹中初始化您的git仓库:

mkdir gitexport/
cd gitexport
git init

然后将导出的CSV历史记录加载到git:

cat ../{blob,dump}.dat | git fast-import

然后将 Git 提交光标放到历史记录的末尾:

git reset --hard

最后,如果需要的话,您可以将更改推送到远程 git 存储库:

git push -u origin master
当然,您需要先运行git remote add origin https://your_repo_url
注意:cvs2git.optionscvs2git的JSON格式配置文件,在其中可以指定各种转换,例如作者名称(以便在导入后将其昵称自动转换为全名)。请查看此处的文档包含的示例选项文件

2
在浏览和尝试了所有其他解决方案之后,这个对我起作用了! :D - jonasespelita
1
它对我也起作用了,我没有rsync的选项,但我可以手动复制存储库。记住始终手动将项目复制到文件夹中或执行rsync而不是checkout。 - Lyju I Edwinson
在Linux上,您可以使用“apt install cvs2svn”安装“cvs2git”。 - rubo77
当我的 CVS 根目录是“pserver”时,我该如何使用您的第一行中的 rsync - einpoklum
@einpoklum,很抱歉我在CVS方面没有太多经验,无法回答你的问题,或许其他人可以吗?您也可以尝试玩弄该命令,直到它起作用,或使用TortoiseCVS以简化该过程。 - gaborous
尽管这个答案声称cvs2git适用于所有平台,但我无法在Windows上运行它,因为显然cvs2git使用本地安装的CVS客户端来执行本地检出(:local:)。Windows CVSNT客户端不支持此功能,并显示错误信息“cvs [checkout aborted]: Couldn't open default trigger library: No such file or directory”。幸运的是,Cygwin中的CVS客户端支持本地检出,在Cygwin安装中运行cvs2git成功完成。 - Tim De Baets

22

我个人没有将CVS转换为Git的经验,但我相信Eric Raymond的cvs-fast-export是需要使用的工具。他在这里发布了man页herecvsps是另一个由Eric维护的工具,但它最近已被弃用,改用cvs-fast-exportcvs2git是另一个建立在一些与cvs2svn相同的机器上的工具。后者非常熟练,因此我有很高的期望cvs2git同样出色。

值得注意的一点是,CVS是一个相当有缺陷的RCS。可能会存在无法精确反映在Git中的内容。换句话说,在这里存在一定的阻抗不匹配,但是这些工具会尽力保存尽可能多的内容。确保检查您的转换,并且您对结果满意。您可能需要修复部分Git历史记录以获得更令人满意的结果,但我不认为您需要这样做。


2
在我看来,cvs-fast-export 有一个很大的缺陷...它使用 C 语言。这意味着更难调试问题,特别是因为它在 stdout 输出内容并从 stdin 读取内容。它还会重新编号 CVS 版本,与 RCS 文件中的版本不同,如果您尝试确定问题,可能会令人困惑。尽管如此,这仍应该是被接受的答案。+1 - 0xC0000022L
4
我最开始尝试了cvs2git,但是它依赖于anydbm包和一个不同于默认的dbm引擎。当你安装所有必需的Python库并让它运行起来时,你已经完成了下载和编译cvs-fast-export的10倍工作量,而后者不需要任何外部库。我发现cvs-fast-export在转换我的CVS存储库方面做得非常出色。 - Edward Falk

12

您可以使用git-cvsimport将CVS存储库导入到Git中。默认情况下,这会检出每个修订版本,为您提供相对完整的历史记录。

根据您的操作系统,您可能需要单独安装支持此功能。例如,在Ubuntu机器上,您需要安装git-cvs软件包。

本答案详细介绍了更多信息。


4
git-cvsimport 相对于 CVS 历史中的问题更具弹性,但会导致 (默默地) 不一致的结果。我已经阅读了很多关于类似问题的 SO 答案,并想知道有多少人实际上在拥有真正的“创伤”和问题的存储库中进行了实际的实际转换。 - 0xC0000022L
2
在我的情况下:cvs-fast-export 没有导入任何历史记录,cvs2git 甚至没有导入一个文件(在示例选项文件上出现错误),而 git-cvsimport 则使用非常接近于 This answer 链接上的语法完成了工作。 - Alex

4
我最近(2016年)使用了Eric Raymond的reposurgeon将一个来自sourceforge的CVS repo导入到git中。我非常惊喜地发现它工作得非常好。 在之前使用cvs2svn和其他工具的经验之后,我毫不犹豫地推荐reposurgeon用于这种任务。
Eric已经将迁移过程纳入了Reposurgeon文档中,标题为“存储库转换指南”。

2
我使用Docker来运行,按照@gaborous提供的优秀步骤,并基于的https://github.com/mhagger/cvs2svn Dockerfile代码。这样做的好处是在镜像中安装了所有必需的工具,可以立即运行。
按照上述步骤,但将Python执行替换为Docker运行。
  1. 克隆https://github.com/mhagger/cvs2svn到本地目录,我们将其称为$DIR。

    cd $DIR

  2. 编辑Dockerfile

将Dockerfile复制到Dockerfile-cvs2git并进行编辑。
ENTRYPOINT ["cvs2git"]

构建名为cvs2git的docker镜像:
docker build --target=run --tag cvs2git . -f Dockerfile-cvs2git
  1. 将cvs2git-example.options复制到cvs2git.options。

cvs2git.options提供了两个内容:

  • blob和dump文件的名称和位置
  • CVS子模块名称

编辑cvs2git.options

..  
blob_filename=r'/tmp/git-blob.dat',  
..  
dump_filename=r'/tmp/git-dump.dat',  
..  
run_options.set_project(  
  r'/cvs/<my-sub-repo>',  
..
  1. 运行Docker镜像。

为CVS根仓库位置和输出文件位置的tmp指定Docker卷(-v)。 注意,cvs2git.options提供了运行的配置。

  docker run -it --rm  -v /opt/CVS/<root-repo>/:/cvs -v /opt/tmp:/tmp \
    cvs2git \
    --options=cvs2git.options \
    --fallback-encoding utf-8
  1. 按照@gaborous的指示进行操作,从以下步骤开始:

    mkdir gitexport/
    cd gitexport
    git init

    将 /opt/tmp/{blob,dump}.dat 文件内容导入到git中,使用命令:git fast-import


1

gaborous答案使用了git fast-import,但在日志信息UTF-8编码时可能会失败。

从Git 2.23(2019年第二季度)开始,这将变得更好: git fast-export/import”配对已经被教导能够更好地处理具有不同于UTF-8编码的日志消息的提交。

请参见 提交 e80001f, 提交 57a8be2, 提交 ccbfc96, 提交 3edfcc6, 提交 32615ce (2019年5月14日) 由 Elijah Newren (newren) 提交。
(由Junio C Hamano -- gitster --提交 66dc7b6中合并,2019年6月13日)

fast-export: 仅在用户请求时自动重新编码提交信息

自动重新编码提交信息(并删除编码头)会影响到可逆的历史重写尝试(例如 sha1sum <-> sha256sum 转换,某些子树重写),并且似乎与 fast-export 在其他地方遵循的通用原则不一致,即要求明确的用户请求来修改输出(例如 --signed-tags=strip--tag-of-filtered-object=rewrite)。
新增一个--reencode标志供用户使用,并像其他 fast-export 标志一样,默认设置为“abort

这意味着 Documentation/git-fast-export 现在包括:

 --reencode=(yes|no|abort)::

指定如何处理提交对象中的编码标头。
当要求“中止”(默认情况下)时,遇到这样的提交对象时,该程序将停止运行。
使用“是”,提交消息将重新编码为UTF-8。
使用“否”,原始编码将被保留。 fast-export:如果无法重新编码,则避免剥离编码标头。
fast-export遇到带有“编码”标头的提交时,它会尝试重新编码为UTF-8,然后删除编码标头。但是,如果由于例如提交消息中的一个字符在旧编码中无效而无法重新编码为UTF-8,则需要保留原始编码,否则我们将丢失理解原始提交消息中的所有其他(有效)字符所需的信息。 fast-import:支持“编码”提交标头。
由于git支持除UTF-8以外的编码格式的提交消息,因此允许“fast-import”导入这样的提交。
这对于不想重新编码来自外部系统的提交消息的人可能很有用,并且对于使用专门编码在其提交历史记录中的Git存储库来实现可逆历史记录重写(例如sha1sum<-> sha256sum过渡或子树工作)也可能很有用。 Documentation/git-fast-import现在包括:

encoding

可选的encoding命令指示提交消息的编码方式。
大多数提交都是UTF-8,省略了编码,但这使得可以将提交消息导入到git中而无需首先重新编码。

要查看这个测试,它使用了一个带有非ASCII字符的作者名称,但没有特殊的提交信息。
它确保重新编码为UTF-8后大小正确,通过检查其大小来完成:

如果不重新编码,则提交对象将是240字节。

  • 删除“encoding iso-8859-7\n”标题会减少20个字节。
  • 圆周率字符π从iso-8859-7中的\xF0\360)重新编码为UTF-8中的\xCF\x80\317\200)会增加一个字节。

检查预期大小。


随着 Git 2.29(2020年第四季度)的推出,用于导入的打包头得到了更好的管理。

请看提交 7744a5d, 提交 014f144, 提交 ccb181d (2020年9月6日) 由René Scharfe (rscharfe)提交。
(由Junio C Hamano -- gitster --合并于提交 9b80744, 2020年9月18日)

fast-import:使用write_pack_header()

签名作者:René Scharfe

调用write_pack_header()函数来哈希和写入打包头,而不是手动编写此函数。这样可以消除重复代码和神奇的版本号2——自从c90be46abd(“更改快速导入的打包头创建方式以使用pack.h”,2006-08-16,Git v1.5.0-rc4——合并)以及pack.h(再次)自29f049a0c2(还原“将打包创建移至版本3”,2006-10-14,Git v1.4.3)以来一直在使用。保留HTML标签。

1
为了将一个项目从sourceforge克隆到github,我执行了以下步骤。
PROJECT=some_sourceforge_project_name
GITUSER=rubo77
rsync -av rsync://a.cvs.sourceforge.net/cvsroot/$PROJECT/\* cvs
svn export --username=guest http://cvs2svn.tigris.org/svn/cvs2svn/trunk cvs2svn-trunk
cp ./cvs2svn-trunk/cvs2git-example.options ./cvs2git.options
vim cvs2git.options # edit run_options.set_project
cvs2svn-trunk/cvs2git --options=cvs2git.options --fallback-encoding utf-8

https://github.com/$GITUSER/$PROJECT.git 创建一个空的 git。

git clone git@github.com:$GITUSER/$PROJECT.git $PROJECT-github
cd $PROJECT-github
cat ../cvs2git-tmp/git-{blob,dump}.dat | git fast-import
git log
git reset --hard
git push

0

我最近使用“CVS远程访问程序”或crap(GitHub)取得了成功并获得了相对愉快的体验。

它显然可以处理其他转换工具无法处理的CVS存储库的各种复杂性,但我对细节不是很熟悉。与cvs2git一样,它也遵循转储文件的路径,这些文件实际上是使用git-fast-import导入到git中的。

我建议使用它的原因是,当我发现其中的缺陷时,我能够将我所缺少的功能添加到现有代码中,并且这并不是那么可怕。我的PR正在等待审核,还有一堆错误报告。


0

使用 cvs2svn 迁移从 CVS 到 Git

分享迁移 CVS 到 Git 的所有步骤

1. 在任意目录中创建一个名为 cvsProject 的目录

Rsync:同步您的 CVS 存储库: 1. $rsync -av CVSUserName@CVSipAdrress:/CVS_Path/ProjectName/* ~/anyDir/ProjectName 2. cd $../cvs2svn-x.x.0 && ./cvs2git --options=cvs2git-example.options 3. $./cvs2git --blobfile=cvs2git-tmp/git-blob.dat \ --dumpfile=cvs2git-tmp/git-dump.dat \ --username=CVS_YOUR_USER_NAME \ /path_of_step(1)/cvsProject 注意:如果出现任何编码错误,请将以下内容添加到上述命令中:“--encoding=ascii --encoding=utf8 --encoding=utf16 --encoding=latin” 4. mkdir newGitRepo && cd newGitRepo 5. git init --bare 6. git fast-import --export-marks=/x.x.x/cvs2svn-2.5.0/cvs2git-tmp/git-marks.dat
哇,现在您已经完成了,现在可以将存储库推送到 Git。 参考资料:[link1][2] ,[link2][2]

请告诉我是否遇到任何问题。 - Mugeesh Husain

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