291

I am creating my first project in Subversion. So far I have

 branches
 tags
 trunk

I think I immediately need to make branches singular and start over. Update branches is the norm.

I have been doing work in trunk and moving the contents to tags as follows.

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

My gut tells me this is totally wrong, and I should maintain some relationship between the files using svn copy. The files I create in this way will have no relationship to each other, and I am sure I will miss out on Subversion features. Am I correct?

Should I use svn copy for the individual files?

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"

Should I use svn copy on the entire directory?

svn copy cp -rf trunk tags/1.0
svn commit -m " create a first tagged version"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ojblass
  • 21,146
  • 22
  • 83
  • 132

9 Answers9

436

Use:

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

Shorthand:

cd /path/to/project
svn copy ^/trunk ^/tags/1.0 -m "Release 1.0"
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
victor hugo
  • 35,514
  • 12
  • 68
  • 79
  • 37
    I marked this as answer. Just one extra note. You can get an previous revision of the trunk and "tag" it as well. the command: svn copy -r 123 "http://svn.example.com/project/trunk" "http://svn.example.com/project/tags/1.0" -m "Tagging, but using older revision (123)." – granadaCoder Oct 18 '11 at 16:39
  • 7
    I get **svn: Local, non-commit operations do not take a log message or revision properties**, so I just remove the -m option. – Jonny May 02 '13 at 03:03
  • 4
    Just an FYI, make sure that your url matches your repository including http or https. – Norman H Jul 29 '13 at 12:48
  • i did: `svn cp trunk tags/1.0.0; svn ci tags/1.0.0 -m "Release 1.0.0"` – vault Nov 25 '14 at 10:37
  • 2
    Why the \ at the end of the first line? – Fractaliste Mar 26 '15 at 08:31
  • 1
    @Jonny I am unable to run the above command without the "-m" option. I am using terminal on mac. – Abdurrahman Mubeen Ali Nov 10 '16 at 04:03
  • 2
    another note from git user: after the command, it will only create the new tag on server. You have to "svn update" to pull the new tag to local, in order to "see" the new tag in your machine. For the paths, you can navigate to the corresponding branch folder and use "svn info" to get it. – Surely Jun 26 '18 at 03:10
  • svn: E160013: '/!svn/rvr/2156121/trunk' path not found – Tom Sep 13 '19 at 12:12
  • @Fractaliste the backslash character (`\\`) is for line continuation – Wolf Jan 05 '21 at 11:32
  • For users getting the **svn: E205009: Local, non-commit operations do not take a log message or revision properties** error, use double quotes v/s single ones when using the "-m" option. – Nabakamal Das Aug 16 '21 at 12:08
  • @Wolf As this question is not marked as "linux/shell only" and other environments use different line continuation characters, this might be confusing and misleading. Why not just put the command into a single line? – David Balažic Oct 11 '22 at 10:17
188

You are correct in that it's not "right" to add files to the tags folder.

You've correctly guessed that copy is the operation to use; it lets Subversion keep track of the history of these files, and also (I assume) store them much more efficiently.

In my experience, it's best to do copies ("snapshots") of entire projects, i.e. all files from the root check-out location. That way the snapshot can stand on its own, as a true representation of the entire project's state at a particular point in time.

This part of "the book" shows how the command is typically used.

unwind
  • 391,730
  • 64
  • 469
  • 606
14

As noted by @victor hugo, the "proper" way is to use svn copy. There is one caveat though. The "tag" created that way will not be a true tag, it will be an exact copy of the specified revision, but it will be a different revision itself. So if your build system makes use of svn revision somehow (e.g. incorporates the number obtained with 'svn info' into the version of the product you build), then you won't be able to build exactly the same product from a tag (the result will have the revision of the tag instead of that of the original code).

It looks like by design there is no way in svn to create a truly proper meta tag.

Alexander Amelkin
  • 759
  • 1
  • 9
  • 15
  • 4
    It is possible to use "Last Changed Rev": ```echo "{ 'svnRev': \"`svn info | awk '/Last Changed Rev:/{print $4}'`\" }" >svnver.txt``` ` – 18446744073709551615 Jan 24 '13 at 06:38
  • This way, two branches with (of course) different revision numbers still produce the same software version. – 18446744073709551615 Jan 24 '13 at 06:50
  • 1
    Yes, you're right about Last Changed Rev, but that doesn't change the fact that by design there are no real tags in Subversion. – Alexander Amelkin May 23 '13 at 10:16
  • @18446744073709551615: You can avoid using `awk` and obtain that information straight from svn using the `--show-item` option: `svn info --show-item last-changed-revision` – Luchostein Sep 22 '16 at 20:02
  • @AlexanderAmelkin the tag is only used for its property to create an atomic storage of time and place (revision + folder). You never need to checkout a tag for a working copy, you use the one-point history of the tag to get its real content. I hope my wording isn't confusing to you. I mostly use the photograph metaphor: the tag is the photo, the trunk or branch (portion) at the time the photo was taken is the content you are interested in. Since the photo itself is contained in the repo, it has its own time and place. – Wolf Jan 05 '21 at 11:52
12

Just use this:

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

(all on one line, of course.) You should always make a branch of the entire trunk folder and contents. It is of course possible to branch sub-parts of the trunk, but this will almost never be a good practice. You want the branch to behave exactly like the trunk does now, and for that to happen you have to branch the entire trunk.

See a better summary of SVN usage at my blog: SVN Essentials, and SVN Essentials 2

AgilePro
  • 5,588
  • 4
  • 33
  • 56
  • Can you elaborate how it should look like if i only checkoput from trunk and i'm inside with my script. – aholbreich Oct 09 '15 at 15:44
  • If you have checked out the trunk folder, then you need to use the http address of the repository. I have updated the answer to represent this since checking out the trunk folder is the recommended pattern. – AgilePro Oct 09 '15 at 21:59
  • How is this answer different from the accepted one? – Daniel W. Apr 30 '19 at 08:33
12

Could use Tortoise:

http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-branchtag.html

Gromer
  • 9,861
  • 4
  • 34
  • 55
  • 1
    I am going to build a larger system on top of this so I need to focus on the core functions provided. – ojblass May 12 '09 at 06:20
7

@victor hugo and @unwind are correct, and victor's solution is by far the simplest. However BEWARE of externals in your SVN project. If you reference external libraries, the external's revision reference (whether a tag, or HEAD, or number) will remain unchanged when you tag directories that have external references.

It is possible to create a script to handle this aspect of tagging, for a discussion on that topic, see this SO article: Tagging an SVN checkout with externals

Community
  • 1
  • 1
MOK9
  • 375
  • 4
  • 9
5

Another option to tag a Subversion repository is to add the tag to the svn:log property like this:

   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

I recently started thinking that this is the most "right" way to tag. This way you don't create extra revisions (as you do with "svn cp") and still can easily extract all tags by using grep on "svn log" output:

   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;
                  }'

Also, this way you may seamlessly delete tags if you need to. So the tags become a complete meta-information, and I like it.

Alexander Amelkin
  • 759
  • 1
  • 9
  • 15
0
svn copy http://URL/svn/trukSource http://URL/svn/tagDestination -m "Test tag code" 
  $error[0].Exception | Select-object Data

All you have to do change URL path. This command will create new dir "tagDestination". The second line will be let know you the full error details if any occur. Create svn env variable if not created. Can check (Cmd:- set, Powershell:- Get-ChildItem Env:) Default path is "C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe"

Ashu
  • 341
  • 2
  • 5
-5

Try this. It works for me:

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"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
iboubuntu
  • 1
  • 1
  • 1
    This is definitely a wrong way to go. The tag (Release1.0) should be a copy of the source directory (trunk), not an arbitrarily created directory. If you do it the way you did, you lose history of the source directory itself and only keep history of descendant nodes (files and directories). – Alexander Amelkin Mar 11 '15 at 16:30