A practical application of subversion for web development
There are loads of articles online about the technicalities of using subversion or git to manage versions of your code. What I am going to do instead is describe my workflow, and how I use subversion not just to manage my code base, but to also deploy code to my staging and production servers. I think this is one of the great powers of version control that often gets ignored when people talk about its advantages.
Repository set up
The first thing is to have a well managed repository with clear purposes for each tag and branch. Tags and branches have no predefined or default behaviour in subversion, they are simply directories in the repository and it’s up to us to give them meaning in the way we use them. So with that in mind, here is a screen shot of one off my repositories.
The core code is stored in the trunk, branches are used for new features and bug fixes. Tags is where we manage snapshots of code or releases. Each release has a specific function and it is the way that we use the tags repository that gives us the power to easily manage different servers with different versions of the codebase.
The testing, deploying and managing different servers with ftp problem
A not too uncommon set up is to have at least 2 and often 3 different versions of your codebase. One locally where you do all your work, new development, bug fixes and testing. A second will be on the live server where the code is served to the public, and often a third will be a staging or testing server with the same setup as the live server but with different features to the live server and different again to the local copy.
Trying to manage these 3 set ups with ftp is a headache. You need to know what changes are made to each file or set of files when you upload changes to one of the servers, and typically all these changes need to be uploaded from one place (the local copy). Keeping track of all this is a nightmare.
Making it easier
With a version control set up such as the one outlined here, you can have different snapshots of the code with different features in different tags and then have each server (staging and live) use that tag as it’s code base.
So for example the repository may have a directory structure such as this with each server having a local “working copy” of the code at a specific tag.
- rc-1.0 (live server, www.example.com)
- rc-1.1 (testing / staging server, staging.example.com)
This system allows for easy deployments of a specific code base to a specific server by switching the local working copy on a specific server to a specific tag. In subversion all you would need to do is checkout a tag from the repository as the public or htdocs folder contents for the website. Then each future change in the code can be simply applied with one subversion command:
sudo svn switch [repository_host]/[repository_path]/tags/[tag_name]
sudo svn switch https://svn.example.com/website-repository/tags/rc-1.1
You will see all the changed files and new files that have been added or deleted listed, and magically you have only the exact files and features relevant to this snapshot of your code base.
New features and bug fixes can be worked on independently on their own branch or the trunk depending on the situation and then merged into the trunk or specific tag when completed. Or depending on the work and situation create a new tag that can later be switched to on the specific server working copy. ie rc-1.1 is the testing tag, once the features are QA tested and approved the live server can switch to this tag and a new tag can be created for the next set of features (rc-1.2), the testing server is then switched to this tag and features relating to this tag are merged into it from relevant branches, the local working copy for the testing server is updated and these changes are automatically updated. Once this tag is ready to go live the live server local copy is switched to this tag and the cycle restarts.
The advantages of using version control locally means you can create each new feature or bug fix by copying the trunk (or another branch or tag) to a new branch. Check this branch out locally to your computer make changes and commit them as you need to. When the update is completed you merge the changes back into the trunk and create a new tag (or update an existing one).
This way you can work on many independent features by creating different branches and then switching to the relevant branch you want to work on locally. As long as you commit your changes to the correct branch you will never have to manually try and manage changed files. Each feature is independent and you can work on as many of them at once as you want and merge them into other features when they are ready. This system really allows for easy collaboration.
Some things to think about committing:
- Temporary directory but not its contents
- Same for cache and log files
- Db schémas and migration files (see below)
- Code files
- Not vendors – try to use something like composer[link] for managing third party libraries otherwise managing the code base for something like a wysiwyg editor is hard whenever you want to update it.
Managing database changes
By using a system for managing database migrations you can easily update the applications database along with the code base. As long as you be sure to commit database migration files with the relevant code commits to the repository you wont have all the headaches of trying to compare databases and make the needed schema changes manually.
This is an overview of my workflow, I’m not saying it’s the best way of working with version control but it works for me. I’ve been using it for a while now and its made a massive difference to the maintain-ability of my code and made managing multiple servers with different states of development much easier.
I’ve also ended up automating a lot of this by writing a phing script that build different versions of the code on specific servers and manages file permissions, running database migrations and switching the server local copy to a spcified tag.
- A web developer’s workflow
- Using Swift Mailer plugins with Laravel 4
- Using Selenium Server 2 and PHPUnit to automate browser acceptance testing
- Laravel 4 First Thoughts
- UK Data.gov Property Price Mash Up
- Problems embedding true type fonts with TCPDF
- Re-routing emails to a development email address with php and SwiftMailer
- php $_FILES array shorter than expected and max_file_uploads sillyness
- Find and replace html links with PHP