Branchingsvn

Branching

Introduction

Source control affords us several options for mapping our serverside structure however for clarity we are using a one to one mapping between the server and client folders. Thus this guide does not cover using one working directory and svn switching it between various branches and trunk. Due the limitations of the current version of SVN as regards merging we will be using a utility called SvnMerge that takes away much of the pain and manual process

Key Concepts

The key concepts here are;

  • Creating a branch from trunk (or another branch)
  • Merging up from the source (i.e. trunk) throughout the lifetime of the branch
  • Collapsing the branch back into the source

Server side folders

projects
        |-$project
                 |-trunk
                 |-tags
                 |-branches
                           |-$BranchName1
                           |-$BranchName2

Local side mapping

c:\code\$project
                 |-trunk
                 |-tags
                 |-branches
                           |-$BranchName1
                           |-$BranchName2

Note $ merely denotes a given arbitary name (such as MyProject or !MyChangesBranch).

The Branch lifecycle

Quick example

To quickly illustrate the process of creating, using, merging and collapsing a branch we'll use the PowerShell functions (available below). Please note below this example is a reference to manually doing this actions via a standard command prompt. It is also worth mentioning that SVN is case sensitive; be sure to always use correct casing for project and branch names.

  • First we wish to create a branch called !MyBranch off of the MyProject project trunk
PS > Create-Branch MyProject MyBranch
  • Note you can use '''Help-Branching''' for some quick reminders as to functions
  • Make some changes to the !MyBranch
  • Now you wish to Merge Up from the Trunk to stay in sync
PS > MergeUp-Branch MyProject MyBranch
  • At this point you have uncommited changes wih potential conflicts; resolve these if necessary then
PS > CommitUp-Branch MyProject MyBranch
  • Continue to repeat the last two steps throughout your development; you're less likely to face tricky conflicts if you do
  • If you need to merge down to the trunk
PS > MergeDown-Branch MyProject MyBranch
  • As with a merge up operation a similar merge down commit is required once any conflicts are resolved
PS > CommitDown-Branch MyProject MyBranch
  • When you've finished development and are ready to collapse the branch; first ensure you have Merged down any changes (as per last two steps) then
PS > Close-Branch MyProject MyBranch
Are you sure(y|n)? this will delete the specified branch (Close-Branch -? for more)
y

Branch Creation

Create via Powershell (See below)

Create-Branch MyProject MyBranch

Create via Command batch file (See below)

CreateBranch.bat MyProject MyBranch

Create Manually

rem Get latest reverting any uneeded changes
cd c:\code\MyProject\trunk\
svn revert . -R
svn up
 
rem : Create A Branch from Trunk On Server
 
svn copy https://svn.example.com/projects/MyProject/trunk https://svn.example.com/projects/MyProject/branches/MyBranch -m "Created MyBranch"
cd c:\code\MyProject\branches\
svn up MyBranch
 
rem Initialize merge up support
 
cd c:\code\MyProject\branches\MyBranch
svnmerge init
svn commit -F svnmerge-commit-message.txt 
del svnmerge-commit-message.txt 
 
rem Initialise merge down support
 
cd c:\code\MyProject\trunk\
svn revert . -R
svnmerge init https://svn.example.com/projects/MyProject/branches/MyBranch
svn commit -F svnmerge-commit-message.txt
del svnmerge-commit-message.txt
 
rem Get the new branch locally
 
cd c:\code\MyProject\branches\
svn up https://svn.example.com/projects/MyProject/branches/MyBranch MyBranch

Merging

Merging Up

Merging up Via PowerShell

MergeUp-Branch MyProject MyBranch
  • '''You must identify, fix and resolve merge conflicts here'''
CommitUp-Branch MyProject MyBranch

Merge up Manually

cd c:\code\MyProject\branches\MyBranch
svnmerge merge --bidirectional -S https://svn.example.com/projects/MyProject/trunk
  • '''You must identify, fix and resolve merge conflicts here'''
cd c:\code\MyProject\branches\MyBranch
svn commit -F svnmerge-commit-message.txt 
del svnmerge-commit-message.txt

Merging Down

  • If you have work that needs to go back into the source follow this process

Merge down via PowerShell

MergeDown-Branch MyProject MyBranch
  • '''You must identify, fix and resolve merge conflicts here'''
CommitDown-Branch MyProject MyBranch

Merge Down manually

cd c:\code\MyProject\trunk
svnmerge merge --bidirectional -S https://svn.example.com/projects/MyProject/branches/MyBranch
  • '''You must identify, fix and resolve merge conflicts here'''
cd c:\code\MyProject\trunk
svn commit -F svnmerge-commit-message.txt 
del svnmerge-commit-message.txt

Closing A Branch

Do a final merge up of the latest trunk changes to the branch. When that's done, the latest versions of branch and trunk will be absolutely identical except for your branch changes.

Close A Branch via PowerShell

Close-Branch MyProject MyBranch

Close A Branch Manually

cd c:\code\MyProject\branches\MyBranch
svnmerge uninit -S https://svn.example.com/projects/MyProject/trunk
svn commit -m "Removing trunk merge integration for MyBranch"
del svnmerge-commit-message.txt
cd c:\code\MyProject\trunk\
svnmerge uninit -S https://svn.example.com/projects/MyProject/branches/MyBranch
del svnmerge-commit-message.txt
svn remove https://svn.example.com/projects/MyProject/branches/MyBranch -m "MyBranch is now closed"
cd c:\code\MyProject\branches\
svn up MyBranch

Automation Scripts

Command Batch files

!CreateBranch.bat

  • '''Usage:''' [[code type="javascript"]]CreateBranch.bat %project %DesiredBranchName[[/code]]
  • '''Example:''' [[code type="javascript"]]CreateBranch.bat MyProject MyMyProjectBranch[[/code]]
cd c:\code\%1\trunk\
svn revert . -R
svn up
svn copy https://svn.example.com/projects/%1/trunk https://svn.example.com/projects/%1/branches/%2 -m "Created %2 merge from this point"
cd c:\code\%1\branches\
svn up %2
CD %2
svnmerge init
svn commit -F svnmerge-commit-message.txt 
del svnmerge-commit-message.txt
cd c:\code\%1\trunk\
svnmerge init https://svn.example.com/projects/%1/branches/%2
svn commit -F svnmerge-commit-message.txt
del svnmerge-commit-message.txt
echo Merging enabled via calling SvnMerge while in branch root folder 
echo for more information please read:
echo https://svn.example.com/cgi-bin/trac.cgi/wiki/BranchingGuidance#MergeUpChanges"

PowerShell Functions

  • Help-Branching
  • Create-Branch $projectName $branchName
  • MergeUp-Branch $projectName $branchName
  • CommitUp-Branch $projectName $branchName
  • MergeDown-Branch $projectName $branchName
  • CommitDown-Branch $projectName $branchName
  • Close-Branch $projectName $branchName

Adding functions to your PowerShell

  • See PowerShell page for more details on setting up PowerShell
  • Simply add these scripts to the end of your $profile

Function Script

########### Branching functions #############
 
#Help-Branching
function Help-Branching()
{
echo "Skinkers Branching Guidance" "Commands:" 
echo "Create-Branch [projectName] [branchName] - Branch from $projectName trunk in c:\code\"
echo "MergeUp-Branch [projectName] [branchName] - Updates a branch with latest from trunk"
echo "CommitUp-Branch [projectName] [branchName] - Commits latest changes from trunk"
echo "MergeDown-Branch [projectName] [branchName] - Updates a trunk with latest changes from branch"
echo "CommitDown-Branch [projectName] [branchName] - Commits latest changes from branch"
echo "Close-Branch [projectName] [branchName] - Deletes a trunk be sure to merge down first"
echo "Notes:"
echo "All merge commands require the user to ensure that all conflicts are resolved before commiting"
echo "Do not close a branch until you have merged down and committed"
}
 
#Create-Branch
function Create-Branch ([string] $projectName, [string] $branchName)
{
if(($projectName -eq "-?") -or ($projectName -match "help"))
{
echo "Usage:   Create-Branch [string]$projectName [string]$branchName" 
echo "Example: Create-Branch MyProject MyNewBranch" "For more details please read:"  
echo "https://svn.example.com/cgi-bin/trac.cgi/wiki/BranchingGuidance#branchcreation" 
}
elseif (([String]::IsNullOrEmpty($projectName)) -or ([String]::IsNullOrEmpty($branchName)))
{
 echo "You must provide a projectName and a branch name for this command; type Create-Branch help for more information "
}
else
{
$startLocation = Get-Location
cd c:\code\$projectName\trunk\
svn revert . -R
svn up
$projectRoot = "https://svn.example.com/projects/"
$commitMessage = "Created $branchName merge from this point"
svn copy $projectRoot$projectName/trunk $projectRoot$projectName/branches/$branchName -m $commitMessage
cd c:\code\$projectName\branches\
svn up $branchName
CD $branchName
svnmerge init
svn commit -F svnmerge-commit-message.txt 
del svnmerge-commit-message.txt
cd c:\code\$projectName\trunk\
svnmerge init https://svn.example.com/projects/$projectName/branches/$branchName
svn commit -F svnmerge-commit-message.txt
del svnmerge-commit-message.txt
 
echo "Merging enabled via SvnMerge or MergeUp-Branch $projectName $branchName" "for more information please read:" 
 
"https://svn.example.com/cgi-bin/trac.cgi/wiki/BranchingGuidance#MergeUpChanges"
cd $startLocation
}
}
 
# MergeUp-Branch
function MergeUp-Branch([string] $projectName, [string] $branchName)
{
if(($projectName -eq "-?") -or ($projectName -match "help"))
{
echo "" "Usage:   MergeUp-Branch [string]$projectName [string]$branchName" "Examples:" 
echo "MergeUp-Branch MyProject MyNewBranch" "Notes:" 
echo "Reverts all curent changes in branch, updates your branch then merges changes from trunk"
echo "For more details" "please read https://svn.example.com/cgi-bin/trac.cgi/wiki/BranchingGuidance#MergingUp" 
}
elseif (([String]::IsNullOrEmpty($projectName)) -or ([String]::IsNullOrEmpty($branchName)))
{
 echo "You must provide a projectName and a branch name for this command; type MergeUp-Branch help for more information "
}
else
{
cd c:\code\$projectName\branches\$branchName
svnmerge merge --bidirectional -S https://svn.example.com/projects/$projectName/trunk
echo "When you have resolved any conflicts commit the merge with CommitUp-Branch"
echo "Do not delete svnmerge-commit-message.txt"
}
}
 
#CommitUp-Branch
function CommitUp-Branch([string] $projectName, [string] $branchName)
{
if(($projectName -eq "-?") -or ($projectName -match "help"))
{
echo "" "Usage:   CommitDown-Branch [string]$projectName [string]$branchName" "Examples:" 
echo "CommitUp-Branch MyProject MyNewBranch" "Notes:" 
echo "Commits all merge changes and resolutions to branch" 
echo "For more details please read" "https://svn.example.com/cgi-bin/trac.cgi/wiki/BranchingGuidance#MergingUp" 
}
elseif (([String]::IsNullOrEmpty($projectName)) -or ([String]::IsNullOrEmpty($branchName)))
{
 echo "You must provide a projectName and a branch name for this command; type CommitUp-Branch help for more information "
}
else
{
cd c:\code\$projectName\branches\$branchName
svn commit -F svnmerge-commit-message.txt
del svnmerge-commit-message.txt
}
}
 
#MergeDown-Branch
function MergeDown-Branch([string] $projectName, [string] $branchName)
{
if(($projectName -eq "-?") -or ($projectName -match "help"))
{
echo "" "Usage:   MergeDown-Branch [string]$projectName [string]$branchName" "Examples:" 
echo "MergeDown-Branch MyProject MyNewBranch" "Notes:" 
echo "Reverts all curent changes in branch, updates your branch then merges changes from trunk" 
echo "For more details please read" "https://svn.example.com/cgi-bin/trac.cgi/wiki/BranchingGuidance#MergingDown" 
}
elseif (([String]::IsNullOrEmpty($projectName)) -or ([String]::IsNullOrEmpty($branchName)))
{
 echo "You must provide a projectName and a branch name for this command; type MergeDown-Branch help for more information "
}
else
{
cd c:\code\$projectName\trunk
svn revert . -R 
svn up
svnmerge merge --bidirectional -S https://svn.example.com/projects/$projectName/branches/$branchName
echo "When you have resolved any conflicts commit the merge with CommitDown-Branch"
echo "Do not delete svnmerge-commit-message.txt"
}
}
 
#CommitDown-Branch
function CommitDown-Branch([string] $projectName, [string] $branchName)
{
if(($projectName -eq "-?") -or ($projectName -match "help"))
{
echo "" "Usage:   CommitDown-Branch [string]$projectName [string]$branchName" "Examples:" 
echo "CommitDown-Branch MyProject MyNewBranch" "Notes:" 
echo "Commits all merge changes and resolutions to trunk" 
echo "For more details please read" "https://svn.example.com/cgi-bin/trac.cgi/wiki/BranchingGuidance#MergingDown" 
}
elseif (([String]::IsNullOrEmpty($projectName)) -or ([String]::IsNullOrEmpty($branchName)))
{
 echo "You must provide a projectName and a branch name for this command; type CommitDown-Branch help for more information 
 
"
}
else
{
cd c:\code\$projectName\trunk
svn commit -F svnmerge-commit-message.txt
del svnmerge-commit-message.txt
}
}
 
# Close-Branch
function Close-Branch ([string] $projectName, [string] $branchName)
{
if(($projectName -eq "-?") -or ($projectName -match "help"))
{
echo "" "Usage:   Close-Branch [string]$projectName [string]$branchName"
echo "Examples:" "Close-Branch MyProject MyNewBranch" "Notes:"
echo "Please read https://svn.example.com/cgi-bin/trac.cgi/wiki/BranchingGuidance#ClosingABranch" 
}
elseif (([String]::IsNullOrEmpty($projectName)) -or ([String]::IsNullOrEmpty($branchName)))
{
 echo "You must provide a projectName and a branch name for this command; type Close-Branch help for more information "
}
else
{
echo "Are you sure(y|n)? this will delete the specified branch (Close-Branch help for more)"
$confirm = [System.Console]::ReadLine()
if($confirm -match "y")
{
cd c:\code\$projectName\branches\$branchName
svnmerge uninit -S https://svn.example.com/projects/$projectName/trunk
svn commit -m "Removing trunk merge integration for $branchName"
del svnmerge-commit-message.txt
cd c:\code\$projectName\trunk\
svnmerge uninit -S https://svn.example.com/projects/$projectName/branches/$branchName
svn commit -m "Removing $branchName merge integration for trunk"
del svnmerge-commit-message.txt
svn remove https://svn.example.com/projects/$projectName/branches/$branchName -m "$branchName is now closed"
cd c:\code\$projectName\branches\
svn up $branchName
}
else
{
echo "Close cancelled; remember to merge down all required changes before closing a branch"
}
}
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License