如何从中继正确创建SVN标签?


282

我正在Subversion中创建我的第一个项目。到目前为止,我有

 branches
 tags
 trunk

我想我需要立即使分支变得单一并重新开始。 更新分支是常态。

我一直在做中继工作,并将内容移动到标签,如下所示。

mkdir tags/1.0
cp -rf trunk/* tags/1.0
svn add tags/1.0
svn commit -m " create a first tagged version"

我的直觉告诉我这是完全错误的,我应该使用来维护文件之间的某种关系svn copy。我以这种方式创建的文件不会相互关联,并且我肯定会错过Subversion功能。我对么?

我应该对单个文件使用svn copy吗?

mkdir tags/1.0
svn add tags/1.0
svn copy trunk/file1 tags/1.0
svn copy trunk/file2 tags/1.0
svn copy trunk/file3 tags/1.0
svn commit -m " create a first tagged version"

我应该在整个目录上使用svn copy吗?

svn copy cp -rf trunk tags/1.0
svn commit -m " create a first tagged version"

10
不幸的是,在这种情况下,我没有做出所有选择。git非常不可思议。
ojblass

Answers:


186

您是正确的,因为将文件添加到标签文件夹并不正确。

您已经正确地猜到了这copy是要使用的操作;它可以让Subversion跟踪这些文件的历史记录,并且(我认为)可以更有效地存储它们。

以我的经验,最好对整个项目进行复制(“快照”),即从根检出位置复制所有文件。这样,快照可以独立存在,作为特定时间点整个项目状态的真实表示。

“这本书”的这一部分说明了通常如何使用该命令。


15
这本书的1.1版本已经过时了。这是一个更好的链接:svnbook.red-bean.com/nightly/en/svn.branchmerge.tags.html
Quinn Taylor

1
复制的文件不会花费任何额外的空间
Carlos

424

采用:

svn copy http://svn.example.com/project/trunk \
      http://svn.example.com/project/tags/1.0 -m "Release 1.0"

速记:

cd /path/to/project
svn copy ^/trunk ^/tags/1.0 -m "Release 1.0"

36
我将此标为答案。仅需多加一注。您可以获取主干的先前版本并对其进行“标记”。命令:svn copy -r 123“ svn.example.com/project/trunk ”“ svn.example.com/project/tags/1.0 ” -m“标记,但使用旧版本(123)。”
granadaCoder 2011年

7
我得到svn:本地非提交操作不使用日志消息或修订版属性,因此我只删除了-m选项。
强尼

4
仅供参考,请确保您的网址与您的存储库匹配,包括http或https。
Norman H

2
为什么在第一行的末尾有\?
Fractaliste

1
@Jonny如果没有“ -m”选项,我将无法运行以上命令。我在Mac上使用终端。
阿卜杜拉赫曼·穆本·阿里

14

如@victor hugo所述,“正确”的方法是使用svn复制。有一个警告。以这种方式创建的“标签”将不是真正的标签,它将是指定修订的精确副本,但它本身将是另一个修订。因此,如果您的构建系统以某种方式利用了svn修订版(例如,将通过“ svn info”获得的编号合并到您所构建的产品的版本中),那么您将无法从标记构建完全相同的产品(结果将具有标记的修订版本,而不是原始代码的修订版本。

看起来,从设计上来说,svn中无法创建真正正确的元标记。


4
可以使用“ Last Changed Rev”:echo "{ 'svnRev': \"`svn info | awk '/Last Changed Rev:/{print $4}'`\" }" >svnver.txt`
18446744073709551615 2013年

这样,具有(当然)不同修订版本的两个分支仍会产生相同的软件版本。
18446744073709551615 2013年

1
是的,您对“ Last Changed Rev”的看法是正确的,但这并没有改变这样一个事实,即在设计上Subversion中没有真正的标签。
亚历山大·阿梅尔金

@ 18446744073709551615:您可以避免使用awk以下--show-item选项,直接从svn获取信息:svn info --show-item last-changed-revision
Luchostein 2016年

12

只需使用此:

svn  copy  http://svn.example.com/project/trunk  
           http://svn.example.com/project/branches/release-1
           -m  "branch for release 1.0"

(当然,全部都在一行上。)您应该始终对整个中继文件夹和内容进行分支。当然可以分支主干的子部分,但这几乎绝不是一个好习惯。您希望分支的行为完全像现在的主干一样,为此,您必须分支整个主干。

在我的博客上查看SVN使用情况的更好摘要: SVN EssentialsSVN Essentials 2


您能详细说明一下,如果我仅从主干进行checkoput并且我在脚本中时,它应该是什么样子。
aholbreich 2015年

如果您已签出主干文件夹,则需要使用存储库的http地址。我已经更新了答案来表示这一点,因为推荐使用中继文件夹。
AgilePro 2015年

这个答案与公认的答案有何不同?
Daniel W.


7

@victor hugo和@unwind是正确的,而victor的解决方案是最简单的。但是,请注意SVN项目中的外部组件。如果引用外部库,则在标记具有外部引用的目录时,外部的修订参考(无论是标记,HEAD还是编号)都将保持不变。

可以创建一个脚本来处理标记的这一方面,有关该主题的讨论,请参见此SO文章:用外部对象标记SVN签出


5

标记Subversion存储库的另一种方法是将标记添加到svn:log属性,如下所示:

   echo "TAG: your_tag_text" > newlog
   svn propget $REPO --revprop -r $tagged_revision >> newlog
   svn propset $REPO --revprop -r $tagged_revision -F newlog
   rm newlog

我最近开始认为这是最“正确”的标记方式。这样,您无需创建额外的修订版本(就像对“ svn cp”所做的那样),并且仍然可以通过在“ svn log”输出中使用grep轻松提取所有标签:

   svn log | awk '/----/ {
                      expect_rev=1;
                      expect_tag=0;
                  }
                  /^r[[:digit:]]+/ {
                      if(expect_rev) {
                          rev=$1;
                          expect_tag=1;
                          expect_rev=0;
                      }
                  }
                  /^TAG:/ {
                      if(expect_tag) {
                          print "Revision "rev", Tag: "$2;
                      }
                      expect_tag=0;
                  }'

同样,如果需要,您可以通过这种方式无缝删除标签。因此,标签成为完整的元信息,我喜欢它。


0
svn copy http://URL/svn/trukSource http://URL/svn/tagDestination -m "Test tag code" 
  $error[0].Exception | Select-object Data

您只需要做的就是更改URL路径。此命令将创建新目录“ tagDestination”。如果发生任何错误,第二行将让您知道完整的错误详细信息。如果未创建,请创建svn env变量。可以检查(Cmd:-设置,Powershell:-Get-ChildItem Env :)默认路径为“ C:\ Program Files \ TortoiseSVN \ bin \ TortoiseProc.exe”


-4

尝试这个。这个对我有用:

mkdir <repos>/tags/Release1.0
svn commit <repos>/tags/Release1.0 
svn copy <repos>/trunk/* <repos>/tag/Release1.0
svn commit <repos/tags/Release1.0 -m "Tagging Release1.0"

1
这绝对是错误的方法。标记(Release1.0)应该是源目录(trunk)的副本,而不是任意创建的目录。如果以这种方式进行操作,则将丢失源目录本身的历史记录,而仅保留后代节点(文件和目录)的历史记录。
Alexander Amelkin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.