处理重命名:svn vs. git vs. mercurial

Joh*_*lph 46 svn git version-control mercurial rename

每个VCS如何处理重命名?

我发现很多矛盾的信息表明git跟踪LOC(代码行)而不是文件,因此重命名对它没有任何意义.

ton*_*nfa 42

  • Git根本不跟踪重命名,但在合并期间使用启发式方法重新发现它们.
  • Mercurial轨道重命名(记录原始版本和原始文件)并在合并期间使用该信息.因此,您必须明确告诉hg重命名hg mv,或hg addremove --similarity用于自动发现.有一些关于在合并期间添加启发式的讨论.
  • Svn跟踪重命名,但我不知道它在合并期间处理它们有多好(从未实际测试过).

  • SVN不跟踪重命名.SVN中的重命名被记录为一个文件被删除而另一个被添加.计划在明年某个时候对SVN 1.8进行重命名跟踪,但这种情况的有效性还有待观察. (6认同)
  • SVN中的重命名跟踪计划为1.4,1.5和1.6.我怀疑将重命名跟踪附加到版本1.8只是说聪明的方式*还没有*. (4认同)
  • 当您尝试合并到已重命名的文件时,SVN会生成树冲突,以便用户可以决定如何正确处理它.旧版本只会输出一个"跳过"警告,说明合并目标不存在. (2认同)
  • @jammycakes:据我所知,SVN跟踪重命名.我已经看到它记录为一个文件被删除,另一个被*原始*复制*,而不仅仅是作为新文件添加. (2认同)

Jak*_*ski 23

混帐

Git的不同之处在于它不进行重命名跟踪,这意味着不需要通过使用SCM命令重命名(或运行自动检测脚本以在提交前标记重命名)来告知重命名,并且不保存存储库中的此类信息,但它确实重命名检测.这意味着它在合并期间使用基于文件名和文件内容相似性的启发式算法找到重命名,并且在通过-M选项请求时使用diff (或使用diff.renamesconfig选项配置).

这种方法的优点如下:

  • 重命名不需要明确标记(或检测):重命名可以来自补丁,也可以通过文件管理器或图形界面完成
  • 相似性检测算法可以改进,并且在提交时不会被冻结,如在检索之前检测重命名以标记它们并将该信息保存在存储库中的情况; 如果它们在历史中没有被冻结,那么处理重命名检测错误也更容易
  • 遵循Git ophilosophy,它是重要的内容; 看看git blame(以及像git gui blame这样的图形前端)可以跟踪跨越文件边界的代码块的移动,这比文件的重命名重命名更通用.
  • 同一机制负责在合并期间处理重命名; 使用重命名检测意味着它可以完成3次提交,最终合并是基于,并且没有必要仔细遵循历史记录,注意每个重命名 - 或文件的规范名称的非分布式概念

请注意,pathspec过滤对重命名检测不起作用; 如果你想在重命名后跟踪文件的历史记录,请使用" git log --follow <filename>"

  • 'git log --follow'是一个隐藏的宝石. (2认同)

jam*_*kes 10

In practice:

Git detects renames automatically. (Incidentally, I've heard claims that git can detect when you move a function from one file to another. My initial tests seem to indicate that this is not the case, however.)

With Mercurial, you have to explicitly tell it about renames, either by hg mv, or the --similarity option of hg addremove, or TortoiseHg's "guess renames" option, or certain tools e.g. VisualHg will flag the renames for you. If you want to use the Git approach with Mercurial, I've written an extension to detect renames at commit time, but it's at a very experimental stage at the moment.

Subversion doesn't handle renames at all. It records a rename as one file being removed and another file being added. This means, for instance, that if Alice changes a file and Bob renames it, you get a tree conflict. This happens whether you are doing full-blown branching and merging or simply svn update. Rename tracking is planned for Subversion 1.8, due out next year sometime.


div*_*eek 6

你听到的是正确的.

Git对文件的内容进行操作,而不是对文件本身进行操作,因此重命名在技术上对它没有意义.对于git,重命名看起来像文件A消失了,文件B出现的内容与A相同.但git实际上非常擅长确定文件实际被重命名的时间.

试一试:重命名一个文件,然后运行'git rm oldname'和'git add newname'告诉git进行更改,然后运行'git status'来查看git认为它正在做什么 - 你会看到它告诉它您已重命名该文件.不过,我不确定这意味着什么.查看带有'git show'的提交,你不会看到任何重命名的提及,只是从一个路径中删除了一堆行并添加到另一个路径.

或者,您也可以使用'git mv'命令重命名文件.它不会改变git看到操作的方式,它只是在一步中有效地执行'mv oldname newname','git rm oldname'和'git add newname'.

有关Mercurial的概述,请参阅tonfa的回答.

另一方面,SVN无法检测重命名,但必须使用'svn mv'命令告知它们.但是,当被告知时,它会将重命名视为"第一类"更改,因此在稍后查看更改日志时,您会看到更改是重命名.

不过,我建议不要建议选择基于此功能的SVN而不是git或mercurial.这些工具之间存在更大,更重要的差异.我首先要确定您是需要分布式版本控制系统(git还是mercurial)还是集中式版本控制系统(svn).