如何在SVN中移动一个标签

6
这个问题可以重新表述为:
如何将特定文件的一个单独更改合并到现有标签中。
这是一个简单的问题,但我自己无法满意地解决。
这个概念来自于其他SCM工具,在这些工具中,你只需要将标签移动到不同的修订版本上,并将其“粘贴”到你所需的确切修订版本上。这些其他工具对标签的理解是本地化的,而SVN则将所有东西都归纳为复制分支。
以下是我在其他公告板和帖子上看到的答案,因此已经被考虑并拒绝了:
1.这不是SVN的正确使用方式 - 实际上,SVN被设计成通用的,并可以完成许多使用模式 - 这是寻找答案的任务。我理解挑战和可能永远找不到答案的可能性。也许我会换用其他工具。
2.为什么要使用类似SVN这样的工具,最好做这个和那个。 - 可以采用许多使用模式或SCM模型。在我的情况下: - 主干代表正在进行的开发,小补丁被应用于它。 - 生产是一个单一的标签 - 从开发到生产的周转非常短且积极,因此我们不能使用几个完整的生产版本。这意味着我不能每次为部署在生产环境中的每个小型子更改创建一个新标签。 - 因此,简而言之,“完整打包的生产发布在我的情况下不存在”。
这是我需要的用例场景。
好吧,我不会自以为是,并且会阅读提供的每一个解决方案,并根据需要重新考虑。

1
如果我理解正确,您想将对一个单一主干文件所做的更改合并到分支路径中?您希望这种方式与 SVN 中的标准合并有何不同? - vgru
1
所以你每次只有一个标签?从技术上讲,这没有问题,但这不是标签通常的使用方式。每次发布一个版本时,您可能希望使用版本号(如1.0)对其进行标记,然后如果您需要发布稍微更改的版本,请创建一个名为1.0.1的标签。然后,您可以拥有另一个名为“latest”或类似的标签,它始终具有最新的发布版本。 - Tyler
我有同样的问题。如何“移动”标签,即如果您已经通过将其复制到tags/1.5.0来标记头,则意识到需要更新一个文件,并将其包含在此标记版本中,该版本将成为发布版。您无法创建新标签,因为它必须是“1.5.0”之类的。我们需要标记一个文件的新版本,覆盖旧版本。这在SVN中似乎不可能。如果您尝试将新版本复制到相同的标记中,它会抱怨已经存在。我们无法将标记“checkout”到新目录中,因为存储库太大。 - John Little
5个回答

5

在Subversion中,标签和分支实际上就是目录。关于它们的概念并没有嵌入到Subversion中,而是存在于你的脑海中。

正如其他人所说,标签是仓库在某个时间点的快照,不应该更改。如果你计划更改标签,那么它应该是一个分支。

例如,

  • 我想要一个显示批准更改的标签:将其作为分支而不是标签。
  • 我想要显示最后一次构建使用的文件:同上。
  • 我想要显示已经审核过的代码:同上。

但这些不是分支!抱怨 声称。

好吧,仓库的建议结构只是建议。你可以在trunktagsbranches以外再添加另一个目录来存放这些可移动的标签

$repo/trunk
$repo/branches
$repo/tags
$repo/moveable_tags

现在,你可以把你更改的标签放在moveable_tags下面,而人们用于发布、快照等的标签则放在tags下面。
我曾经在一家公司修改过建议的存储库布局。我想从存储库中删除过时的分支和标签,但是管理层和开发人员反对。
我说,删除这些并不意味着将它们从存储库中删除。如果需要,我可以轻松地找回它们,但是通过移除它们,我可以消除这两个目录中许多不必要的混乱。然而,开发人员并不感到安全。当然,我可以找到它们,但是他们能吗?
相反,我在trunktagsbranches目录级别上添加了一个obsolete/tags和一个obsolete/branches目录。我只是将过时的标签和分支移动了,而不是删除它们。 tagsbranches没有杂乱无章,管理者和开发人员也更放心,因为他们知道如果需要这些过时的分支和标签,去哪里找。
假设您没有使用标记进行任何复杂操作。您使用标记作为快照,而您希望更改和更新的内容是分支。但是,有时可能需要更改标记。
此外,Subversion在处理此类问题时比大多数其他版本控制系统更好。这是因为标记包含其创建和更改的整个历史记录。在大多数其他版本控制系统中,如果有的话,该标记的历史记录是第二流公民。您可以看到标记。您可以看到哪些文件和版本位于该标记下,但是无法查看谁创建了该标记以及它如何更改。在Subversion下,标记包含它们的整个历史。
要更改标记,请执行以下操作:
  • 检查标记。
  • 进行更改。
  • 提交更改。
或者,更好的方法是使用svn cpsvn mvsvn delete针对存储库URL而不是针对工作目录。例如,我创建了一个发布2.0的标记。突然间,我们意识到我们忘记了一个非常重要的更改,需要随同这个发布一起出去。您可以这样做:
$ svn cp -r 23933 -m"This change in this file should have been included in the tag" \
    $repo/trunk/foo/src/foo.java $repo/tags/2.0/foo/src/foo.java

当你查看这个标签的历史时,现在你会看到。
 $svn log -v $repo/tags/2.0
 ------------------------------------------------------------------------
 r23945 | david | 2013-04-03 11:21:55 -0400 (Wed, 3 Apr 2013) | xxx lines
 Changed paths:
 M /tags/2.0/foo/src/foo.java (from /trunk/foo/src/foo.java:23933)

 This change in this file should have been included in the tag

 ------------------------------------------------------------------------
 r23932 | david | 2013-04-10 11:18:40 -0400 (Wed, 10 Apr 2013) | 1 line
 Changed paths:
 A /tags/2.0 (from /trunk:23921)

 Created release 2.0

我看到这个标签是从主干的修订版本23921一周前创建的。然后我看到文件foo.java是一周后从主干的修订版本23933更新的。


我认为这个答案可能是最接近所要求的,同时还使用了惯用的SVN操作。 - robert

4

在SVN中,标签和分支没有区别。所有的区别都在于团队遵循的如何使用标签和分支的策略。

因此,您可以像处理分支一样合并更改到标签中并提交新的修订版本。通常情况下,您不希望这样做,以便“标记”用于发布的文件的确切版本。但如果真的需要,您可以从这个规则中例外。

或者,您可以删除标签,然后使用正确的修订版本重新创建它。

SVN书籍中的几个链接:“标签”,“分支维护


ADDED: 因此,听起来这种重新标记不是您团队中罕见的、非典型的用例,而是一种常规做法。似乎您使用标签不仅是为了给文件的特定快照命名,而且希望该名称跟随文件的后续更新,忘记其先前的位置。此外,似乎您认为分支对您的工作流程不方便。

嗯,我认为在 SVN 中没有简单和清晰的方法来实现您想要的功能。我认为最好“拥抱”分支并学习如何有效地使用它们。


是的,我考虑了所有的情况:合并到标签中或重新创建标签。问题是,对于只有少数人将单个文件投入生产的情况来说,这太复杂了。我真的需要一个简单的操作,允许我单独选择一个文件,并将其合并到生产标签中。 - YoYo
1
我认为你可以直接使用 svn switch 命令切换到标签,从主干或其他地方获取文件并将其放入你的工作副本中,然后提交更改使用 svn commit 命令。然后再次使用 svn switch 命令切换回主干,以确保不会意外提交属于主干的新开发内容到标签中。 - Tyler

4
我已经找到了一种简单的方法来实现这个(即将文件标记移动)使用Tortoise SVN。
  1. 右键单击您检出的项目目录以及选择“Tortoise SVN -> Repo-browser”,浏览您的存储库
  2. 浏览到您要更改的文件,位于您的tags /目录中
  3. 右键单击文件并选择“checkout”。
  4. 在您的本地硬盘上选择一个临时目录并单击确定。
  5. 使用本地文件资源管理器覆盖此文件以更新版本
  6. 右键单击文件并选择“SVN checkin”。
工作完成。
使用CVS完成相同的事情很容易,只需进入所需目录并键入:“cvs tag -F tagname filename” 在我的看法中,SVN没有真正的标记,这使得使用起来非常痛苦。
我不确定为什么会被否决,它是如何解决问题的确切问题。

这正是我一直在寻找的缺失步骤。你只想简单地进行合并,但为了这样做,你必须首先检出到其他位置。另外,如果更改是标记后你已经检入的更改,则可以在第5步中执行适当的合并。 - usethe4ce

1

你对@Alexey Kukanov的回答的评论表明你真正想要的是一个分支,而不是一个标签。标签是一个单一、不变的时间点的历史记录。分支是代码的副本,随着时间的推移将会进行进一步的更改。你说的是后者。为每个你支持的发布创建“bugfix”或“production”分支,并直接在分支上提交更改[1]或从主干合并更改是标准做法。

在这种情况下,标签将用于创建分支的“副本”,以指示“确切地这段代码在这个特定的时间内处于生产状态”。因此,如果需要,您可以轻松地返回并进行比较。

[1] ... 然后根据需要将它们合并到主干


0

有时我也需要这样做。你可以检出标签中的 svn 文件,而不是分支(如 svn://blahblah/tags/mytag,而不是 svn://blahblah/branches/mybranch),然后提交更改过的文件,即可更新标签。


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