TSVN SVN Vendor Branch Management

Vendor Branch Management for AspDotNetStorefront

A tutorial on how to organize your AspDotNetStorefront Subversion repository and manage integrating updates.

Vendor branch management is a method for us to manage customizations to source code that is maintained by an external organization. This method will organize our Subversion repository in a manner in which we can merge the changes from two different branches of vendor source code (our current base and a updated version) into our modified working copy.

The Subversion book makes short reference to working with a Vendor Branch using Subversion via the command line. In this tutorial we will be explorer how to implement the vendor branch for an AspDotNetStorefront implementation utilizing:

  • VisualSVN Server: Simplifies the installation of Subversion on windows, installs via msi, sets up a repository that is accessible via HTTPS, and can manage user, all via a windows GUI.
  • TortoiseSVN Client: A Subversion client, implemented as a windows shell extension. Uses overlay graphics on your windows folders and files that are part of a repository to illustrate the state of your working copies in comparison to the repository. TortoiseSVN is accessible via the right-click contextual menus as you are navigating windows explorer.
  • WinMerge: an Open Source differencing and merging tool for Windows to help us manage some vendor version cleanup when new updates are released.

 

For brevity we will leave the installation how-to of the tools out. Once all the tools are installed we will set up our repository.

Click to Toggle Step One - Create the Repository

Create the default directories in our repository. We typically follow the Subversion Best Practices when creating our repository layout with the addition of one top level extra directory.  So we will start by creating four directories in our repository:

  • branches
  • tags
  • trunk
  • vendor

The main directories to note here are vendor and trunk

Click to Toggle Step Two - Create the Vendor Branch

Create two subdirectories aspdotnetstorefront and current underneath our vendor directory. Illustrated here:

  • branches
  • tags
  • trunk
  • vendor
    • aspdotnetstorefront
      • current

The purpose of this folder is to hold the unmodified (by us) source code provided by our vendor as a subdirectory of a folder that represents the vendor / project we will be integrating in our trunk.

Click to Toggle Step Three - SVN Import the Vendor Source
  • Unzip our AspDotNetStorefront source code to a temporary directory. For our example we will use c:\vendortemp.
  • Right-click vendortemp, Select Tortoise SVN, SVN Import, then place the url of our repository with the path to our /vendor/aspdotnetstorefront/current
  • Add notes e.g. "import initial aspdnsf vendor branch v9.0.1.2"
  • Once the code is imported you may delete your c:\vendortemp folder.
Click to Toggle Step Four - SVN Copy (tag) the Current Vendor Version
  • Right-click on any folder in Windows Explorer, Select Tortoise SVN, then select Repo-Browser.
  • In the URL dialog, enter the URL and path to our vendor/aspdotnetstorefront folder.
  • Once there, right-click the current directory, select Copy To, and type the version number in place of current in the path provided. e.g /vendor/aspdotnetstorefront/9.0.1.2 in the notes "Tagging aspdnsf version 9.0.1.2"
Click to Toggle Step Five - SVN Copy New Vendor Drop to Your Trunk
  • Right-click on any folder in Windows Explorer, Select Tortoise SVN, then select Repo-Browser.
  • In the url dialog enther the url and path to our vendor/aspdotnetstorefront folder
  • Once there, right-click the current directory, Select Copy To, and now select a new path under your trunk to place your current aspdotnetstorefront e.g. trunk/storefront type your notes "importing aspdnsf in to trunk"
Click to Toggle Step Six - Work on the Trunk

With steps 1-5 completed, you are now set up to work on your project. SVN now knows the relationship between our vendor code and our project, you can see this illustrated by the SVN revision graph.  To get our new code and begin work we will simply:

  • Create a folder to checkout your working code to. In our case we use c:\dev\client-or-projectname\storefront
  • Right-click your new folder and select Svn Checkout, in the repository url specify the url of your trunk e.g. /trunk, ensure the checkout directory: is the correct directory e.g. (c:\dev\client-or-projectname\storefront), select okay

Tips to Ensure Future-Proofed Code

At this point you now have a working copy of your trunk in the c:\dev\client-or-projectname\storefront. You may start coding to your heart's content. You may make modifications as you need to any part of the source. When performing modifications there are some things you can do to make sure future updates and add-ons from the vendor integrate easier.

  • Honor the existing coding style: For every seasoned developer there is an urge to look at someone else's code and say, "WTF were they thinking?!" A truly experienced developer will attempt to identify with the existing style and replicate it as best as possible. AspDotNetStorefront is not the best example of Object Oriented Design. The only pattern it really resembles is that of procedural programming. The objects and classes are really not meant for inheritance or any sort of polymorphism but they are rather helper classes that group similar functionality with some global variables defined as properties on the class. It would be wise to follow this pattern to allow updates with ease.
  • Along similar lines of the first point: RESIST THE URGE TO REFACTOR unless absolutely necessary. I was once in the middle of a WTF moment, when I decided I would simply refactor a particular segment code (read as "checkout process"), completely, try merging updates to that (read as not a chance in H E double L). I actually find myself resisting the urge quite often. If you find yourself here and a refactor is the only way out, it may be wise to copy and branch the code and leave the original code in place with minimal changes. If done this way we can at least bring in future updates with ease and regenerate our code based on the changes to the original code.
  • Tag your own code with every feature you add or core bug you fix. When you tag your code try to come up with a meaningful tag name "Accessories". The reason here is that tagging is rather cheap in cost to the repository and it and a minimum will help us for at least two reasons:
    • It will create a feature use case list of items and updates for us to test in future end to end testing that we will do when we merge future updates.
    • It will give us an easily identifiable comparison point, that we can regenerate our changes from, in the event we had to copy and branch our own modification.

Creating a Vendor Branch

So after all of our coding, modifying and tagging, eventually a vendor change will come along. At this point we need to prepare our vendor code with the new code we received. The goal here is to bring our vendor/aspdotnetstorefront/current to appear exactly the same as the new code we received from them. The steps to do so are as follows.

Click to Toggle Step One - SVN Checkout to Temp Directory

Checkout the vendor/aspdotnetstorefront/current to a temporary directory on your local hard drive.

  • Create a temporary directory and subdirectory on your local machine e.g. c:\aspdnsf\current
  • Navigate via Windows Explorer to the aspdnsf directory and right-click current, Select SVN Checkout, in the url specify the url to your vendor/aspdotnetstorefront/current, verify that the Checkout Directory is our c:\aspdnsf\current and select okay.
Click to Toggle Step Two - Unpack Source to Temp Directory

Unpack the new and complete AspDotNetStorefront source code to a temporary directory in the same parent directory as the current we just checked out using a new temporary folder e.g. c:\aspdnsf\9.0.1.3

Click to Toggle Step Three - Delete Files Not in 9.0.1.3

Step Three: Delete the files in current that do not exist in 9.0.1.3. Here we will use a free tool to do the work for us -- WinMerge.

  • Open up WinMerge and Select File > Open, in the "Select Files and Folders" dialog box as the "Left" specify the path to the new version, e.g. c:\aspdnsf\9.0.1.3, and in the right specify the working copy we just checked out e.g. c:\aspdnsf\current, in the filter specify the "Exclude Source Control" filter , check the box for "Include Subfolders" and select okay.
  • Once the comparison is complete, Select View from the menu and deselect all the Show .. Items except for the Show Right Unique Items, and again from the View menu Select Tree View. You will now have a list of all the folders and files we want to delete from the current folder.
  • Using your keyboard press CTRL+A to select all and press delete.
Click to Toggle Step Four - Copy Files in New Version Over Top of Current Version

Copy all the files in the new version over the top of the current version. Now that we deleted all the files that will no longer exists in the new version of the vendor code we can simply copy and paste the files to bring our current version to an exact copy of our new vendor version.

Click to Toggle Step Five - SVN Commit ALL Changes

SVN Commit ALL of the changes.  The folder icon for the working copy of our current vendor code should show that is out of sync with the red exclamation point (!) icon. 

  • In Windows Explorer, right-click the working copy of the vendor current we just copied the new changes to e.g. c:\aspdnsf\current and select SVN Commit. In the commit dialog box make sure that "Show unversioned files" is checked as well as "Select / deselect all", Remember we want to commit everything. In the notes enter something to reflect that we are updating our vendor current to the new version e.g. "updating current vendor aspdnsf to 9.0.1.3" and commit the code.

We have now prepared our vendor branch so we can build a change set from a previous version of the vendor code to the latest version. Any time we receive new vendor code we will repeat the steps 1-5.

At this point we decide we would like to take advantage of the new vendor changes. Before we can begin we need to prepare our working copy to receive changes. The goal is to get your working copy so it is an exact mirror of what is in the repository and the code in the repository will build and pass any necessary tests. We will refer to this as "clean".

 

Prepare Your Working Copy to Receive the New Vendor Code

  • Step one: SVN Update our working copy
    • Navigate to your working copy e.g. c:\dev\client-or-projectname\storefront, Right-click the folder and select SVN Update.
  • Step two: Verify your working copy is in a clean state
    • If you received updates, build and test to make sure you get your code to a "clean" state. Also, if you were working on anything particular hopefully you would be code compete on that project. If not then make sure you are a good stopping point.
  • Step three: SVN Commit your clean working copy
    • When your code is clean, Right-click the working copy folder and select SVN Commit. Make your appropriate notes and Commit the code.

Now that are working copy is clean and in perfect sync with the repository we are now ready to perform our merge.

Perform the merge

  • Navigate to your working copy e.g. c:\dev\client-or-projectname\storefront, Right-click the folder and select TortoiseSVN > Merge
  • In the Merge Type dialog select Merge Two Different trees
  • In the From: specify the url of the tagged vendor branch version that is the same version we have in our working copy. e.g /vendor/aspdotnetstorefront/9.0.1.2
  • In the To: specify the url of our current vendor branch e.g. /vendor/aspdotnetstorefront/current
  • Verify the folder specified in the "Working Copy" is the correct location in our example it may be c:\dev\client-or-projectname\storefront and Select Next
    • What we are doing here is telling svn that the "from" and "to" are the related (parent - child) branches. SVN will use this to build a change set of the differences from the parent that are now in the child. We can use these differences and attempt to apply them to our working copy (the brother/cousin/nephew?)
  • In the Merge Options dialog box the default options should be fine. From here we test our merge so we may take a peek at the results
  • Ready to Merge? If you notice conflicts in your test they should not detour you from merging your code. TortoiseSVN has great merge tools and will prompt us when it cannot safely perform the merge itself

Resolving Merge Conflicts

There two different conflicts that can occur during a merge.

  1. File Conflicts
    • A file conflict occurs if two (or more) developers have changed the same few lines of a file.
  2. Tree Conflicts
    • A tree conflict occurs when a developer moved/renamed/deleted a file or folder, which another developer either also has moved/renamed/deleted or just modified.

Tree conflicts are probably the easiest to manage as you will really only have us a couple of options.

Click to Toggle Steps for Deletions / Renames

For any deletions/renames you made, you can:

  1. Chose to bring in Directory / file from the repository.
  2. Ignore the conflicting tree from the vendor.
    1. In the case of the Admin directory, I know we are all following the best practice here and have renamed our admin directory. In order to bring in vendor changes we will repeat the merge steps but start from our working copy's renamed admin directory and select the vendors previous version admin directory as the From and the vendor/current admin directory as to To. This will then merge the admin changes that we ignored in the original merge. Note: we could prep our vendor drop in advance and rename the admin directory before the initial import of the vendor branch. We will then need to remember to rename the admin directory in all new version of the vendor code we import.
      1. Deletions/renames the vendor made you can:
        1. Keep your current and ignore the vendor delete.
        2. Choose to have your changed file deleted.
      1. Use Local (your whole file)
      2. Use Repository (their whole file)
        1. Choosing to use either the local or repository is simply the overwrite method we are trying to avoid with this process.
      3. Resolve later (continue to the next conflict)
      4. Resolve all Later (complete the process and mark all conflicts in your working copy)
        1. Note: if you choose Resolve all Later this can create a snowball of change conflicts that might be avoided if we tackle changes as the come along.
      5. Edit Conflict (Opens a three way merge window and allows us to edit the issue)
        1. Dissecting this window we have three panes.
          1. Theirs (the file with the changes in the repository)
          2. Mine (the file with the changes I made)
          3. Merged (the output of the attempting merge.)
        2. b. In all three panes changes are highlighted. In this case the orange is noting the change to our common ancestor. The red is highlighting the conflict between theirs and ours.
        3. c. In the edit conflict window we have a three options to work from in order to solve our issues.
          1. Right-click either Theirs or Mine conflicting blocks to be prompted with these options
            1. Use this text block
            2. Use this whole file
            3. Use Text block from mine before theirs
            4. Use text block theirs before mine.
          2. Right-click the highlighted conflict in the merged window for these prompts:
            1. Use text block from theirs
            2. Use text block from mine
            3. Use Text block from mine before theirs
            4. Use text block theirs before mine.
          3. Start typing in the merged window to create new output on the fly.
            1. You can use this method in conjunction with any of the other options

In the event of a file conflict TortoiseSVN will interrupt the merge and prompt you with a window alerting you to the conflict and give you several options in dealing with it.

Now that you have successfully dealt with the conflict, we are allowed to mark it resolved.

We then rinse and repeat until we are finished!