Thursday, December 18, 2008

Tortoise SVN - tag & merge tutorial

Since it's quite confusing how to branch/tag and then merge a branch with the production code - here's a short tutorial on the issue. Note that the strategy of tagging and merging presented below is probably not the only possible, however it works in practice.

I assume that a SVN repository is created, the SVN server works and Tortoise is installed on the client machine.

Step 1 - Import local files into the repository

Start from creating a local directory with application files in it.

  

You need to "put" the local directory into the SVN server. In SVN language this is called "import". Click the Application directory with the right mouse button and choose TortoiseSVN/Import from the shell context menu.

After you click "OK", the local directory is imported into the SVN. Note, that I use /trunk subdirectory to actually store files there. This is because we will create other subdirectories in the same repository and these subdirectories will contain tags of the code.

Step 2 - Checkout managed repository from SVN back to your local machine

Now you need a new, fresh location on your local filesystem dedicated to work as a local image of the repository. Create a fresh directory, let's call it ApplicationCode, right click on it and choose "SVN Checkout" from the context menu.

The Checkout operation retrieves the contents of the repository and creates a local image of it which can be then synchronized with the repository using the "Update" and "Commit" operations.

Local filesystem after the checkout operation looks like this:

Delete the /Application folder, it's no longer needed.

Step 3 - Continue working on the /trunk line of the code

This is what people find confusing.

Should I continue to develop application using the /trunk line? Or should I rather create a new /development line?

Well, there's no single answer to this question, however the advice is as follows: use the /trunk line to make any changes you want and whenever you make a release to clients - create a tag.

Let's then continue to work on the /trunk line for a while - create a new document "c.txt" in the /ApplicationCode directory and commit changes into the repository (right click on the /ApplicationCode and select "Commit" option).

Step 4 - Tag whenever you release your application to clients

A great day comes and you release your application to your clients. Click the /ApplicationCode with the right mouse button and select TortoiseSVN/Branch-tag option from the context menu. This invokes the "Copy (Branch/Tag)" window where you should give a name to the tag's directory.

Let's assume that the tag's name is "tag1" (this is where it turns out that putting files into /trunk subdirectory is important - both /trunk and /tag1 will be subdirectories of the same repository directory on the server).

Click "OK" and SVN will happily inform you that "your working copy remains on the previous path. If you want your next changes to be in the just created copy then you need to switch over to that copy path. Use the Switch command to do that."

Step 5 - Oops, a bug's been found. Go back to the Tag and fix the bug

As you continue your work on the /ApplicationCode directory and Update/Commit changes into the /trunk subdirectory in the SVN, a day comes when a bug is found in the code released to your clients. This is where you need to go back to the code, make changes and synchronize changes with the /trunk line.

As the message from the previous step says, you could use context menu's "TortoiseSVN/Switch" command to switch the code in the local /Application directory. However, this is not required!

Instead, I prefer to restore the image of the SVN's /tag1 into just another, fresh directory in the local filesystem. Let's then create /ApplicationCode_Tag1 directory in the local filesystem and checkout the /tag1 into it (just like we did in Step 2).

Now, let's fix the bug in the code retrieved from the /tag1: we'll modify the b.txt and create d.txt.

Commit changes from the /ApplicationCode_Tag1 local directory. Note that changes are stored only in the /tag1/ subdirectory in the SVN.

Step 6 - Merge the patched code with the /trunk line

This is the most fun part - we'll merge changes applied to the /tag1/ line of the code with the /trunk line of the code.

First, invoke the TortoiseSVN/Merge function from the context menu on the /ApplicationCode directory.

Note that the text in the lower groupbox correctly informs you that the result of the merge will be stored in the /ApplicationCode folder which contains an image of the /trunk folder. However, what you are supposed to do is to specify the From: and To: sources correctly.

Let's leave the To: untouched and click the "Show log" beside the "Revision" in the From: section.

Here you see that one of the revisions is printed with blue color - this is the number of revision which had been active when the tag has been made. Remember the number (1101 in my case), cancel the log window and put that number in the Revision textbox in the Merge window:

Do a "Dry run" where you can inspect changes which are about to be made to the /trunk subdirectory. In our example you'll learn that the b.txt is going to be updated and d.txt is going to be added. Click "Merge" and inspect the contents of the /ApplicationCode folder:

Happy SVNing!

8 comments:

Anonymous said...

One thing wonder me:
Cite:
"then continue to work on the /trunk line for a while - create a new document "c.txt" in the /ApplicationCode directory and commit changes into the repository (right click on the /ApplicationCode and select "Commit" option)."

New, shiny file just added to directory is not part of SVN repository. That mean: SVN commit option will be unavailable, until we press SVN -> Add!, and then commit.

Wiktor Zychla said...

Deto, you are true, however you probably think of a "commit" command invoked on this particular file, while I mean the "commit" invoked on a directory.

the "commit" command on a directory is always accessible and it shows a list of files where you check/uncheck files to be added to the repository and then, after you press "ok", Tortoise invokes a sequence of svn commands on the repository.

Rainer said...

Thanks for the tutorial!

Unfortunately, I'm stuck at Step 6. You said: First, invoke the TortoiseSVN/Merge function from the context menu on the /ApplicationCode directory.

When I do that, I don't get the screen you are showing. Instead, I get to choose between three "merge types". I tried them all:

Merge a range of revisions: File d.txt will not show up.

Reintegrate a branch: Error "Cannot reintegrate into a working copy that has local modifications."

Merge two different trees: Used from "tag1" to "trunk", got Error "Skipped missing target: ...d.txt"

Any ideas?

Kind regards,

Rainer

P.S.: I'm using TortoiseSVN 1.6.0, Build 15855 - 32 Bit, 2009/03/21 12:36:36

Wiktor Zychla said...

I've written the tutorial for Tortoise 1.4.4. I didn't try the new version.

If I were you, I would try to follow my tutorial on 1.4.4 and then, if it works correctly, try to find out how to accomplish the same task in 1.6.0.

Regards,
Wiktor

Rainer said...

I think I'm going to try that the other day, Wiktor. Thank you for the information about the (sub)version you've been using. With that information it's going to be a lot easier to finish your tutorial.

Rainer said...

Update: Figured out how to do Step 6 without going back to an earlier (sub)version. If someone has the same problem with Subversion 1.6.x, here's how it worked for me. Proceed with the tutorial up to this point:

First, invoke the TortoiseSVN/Merge function from the context menu on the /ApplicationCode directory.

So far, so good. But now:

- Choose "Reintegrate a branch"
- Click "Next"
- Put the "trunk" path into the "From URL:" combo box, not the "tag1" path
- Click "Next"
- Click "Test merge", if you want to be sure. (I guess that's a new name for "Dry run")
- Finally, click "Merge".

If everything went right, you should now see the last screenshot in this tutorial, just before "Happy SVNing!". (Well, almost: My file "d.txt" has an exclamation mark just like "b.txt", not a blue plus sign as in the tutorial.)

Wiktor Zychla said...

Great news! Thank you for your updated information on the issue.

Quentin said...

That's a great tutorial. Thank you!