0
Practical SVN  for PHP Developers Matthew Weier O'Phinney Project Lead Zend Framework Lorna Jane Mitchell Software Enginee...
What is Version Control?
<ul><li>What did  you  change from the previous revision? </li></ul><ul><li>What changes have  others  recorded since your...
Types of  Version Control
<ul><li>Each checkout is a fully functional repository </li></ul><ul><li>Anybody may accept patches from anyone else </li>...
<ul><li>One canonical repository  </li></ul><ul><li>All changes are submitted to the repository </li></ul><ul><li>All chan...
What is Subversion?
<ul><li>Non-Distributed Version Control System </li></ul><ul><li>Successor to CVS </li></ul><ul><li>Stores and versions: <...
Installing Subversion
Choose a Protocol
<ul><li>give repo access to local users </li></ul><ul><li>give users and/or groups read/write on the repo to grant access ...
<ul><li>give repo access to users with ssh credentials  </li></ul><ul><li>give users and/or groups read/write on the repo ...
<ul><li>make repo web-browseable and have apache handle credentials </li></ul><ul><li>basic or digest HTTP authentication ...
Installing on Linux
<ul><li>Debian/Ubuntu:  aptitude install subversion </li></ul><ul><li>Fedora/RedHat:  yum install subversion </li></ul>Dis...
<ul><li>download from http://subversion.tigris.org </li></ul><ul><li>check dependencies (install apache, mod_dav, etc., fi...
Setting up a repository
What  is  a repository ?
<ul><li>The place all changesets are stored </li></ul><ul><li>A black box; you may only interact with it using svn tools <...
Creating the repository
Use “svnadmin create”
Create initial content
Commit initial structure
Alternate way: import into the repo
About repository structure
<ul><li>Trunk  – the main code version </li></ul><ul><li>Branches  – copies of code which can be modified </li></ul><ul><l...
Using Subversion
Checkout: svn checkout (co)
.svn directory
Status: svn status (st)
<ul><li>' ' no modifications </li></ul><ul><li>'A' Added </li></ul><ul><li>'C' Conflicted </li></ul><ul><li>'D' Deleted </...
Add to repo: svn add
Commit to repo: svn commit (ci)
Changelog: svn log
Dealing with missing files
<ul><li>“ !” in the status listing </li></ul><ul><li>Usually because something was moved or deleted  without using the svn...
What and When to commit
<ul><li>hourly, semi-daily, daily checkins </li></ul><ul><li>code only, tests only, docs only </li></ul>Bad  practices
Each commit should include all code, tests, and docs related to a discrete behavior or set of functionality. The  Best Pra...
<ul><li>Easy to “cherry-pick” changesets between branches </li></ul><ul><li>Trivial to identify changesets to rollback </l...
Examples
Examples
<ul><li>PLAN your project; break it into distinct units of functionality </li></ul><ul><li>Use an issue tracker; issues sh...
Conflicts
<ul><li>svn  blame / annotate / praise </li></ul><ul><li>shows who last edited which line </li></ul>svn blame
Example
<ul><li>Two people change same line of same file </li></ul><ul><li>svn will ask user to choose </li></ul>Conflicts
<ul><li>index.php.r4  version from before either your changes or the commit that has conflicted </li></ul><ul><li>index.ph...
<ul><li>edit index.php until correct </li></ul><ul><li>may copy one of the &quot;extra&quot; files into place of this one ...
<ul><li>Good team communication </li></ul><ul><li>Update often </li></ul><ul><li>Commit first! </li></ul>Avoiding Conflicts
Branching and Tagging
Patterns
Feature Branches Graph by Eli White
<ul><li>Pros: </li></ul><ul><ul><li>Features may be developed in isolation </li></ul></ul><ul><ul><li>Trunk always contain...
Long-lived Branches Graph by Eli White
<ul><li>Pros: </li></ul><ul><ul><li>Production is always stable </li></ul></ul><ul><ul><li>Rollback by pointing to product...
Release Branches Graph by Eli White
<ul><li>Pros: </li></ul><ul><ul><li>Easy to isolate features by version (parallel development) </li></ul></ul><ul><ul><li>...
Merging
<ul><li>Moving changes between branches (including trunk) </li></ul><ul><li>Merge single changes </li></ul><ul><li>Merging...
<ul><li>Check out the target branch </li></ul><ul><li>From the target directory, run svn diff until the output illustrates...
<ul><li>Use “svn log” to identify discrete changesets you want to merge. </li></ul><ul><li>Use the “cherry-pick” flag of “...
Administering Repositories
Backing up your Repository
<ul><li>Copying files directly can lead to corruption in the copy </li></ul><ul><li>Use “svnadmin hotcopy” or  “svnadmin d...
Authentication
<ul><li>Dependent on how the OS does authentication: </li></ul><ul><ul><li>Local accounts </li></ul></ul><ul><ul><li>“ Vir...
<ul><li>Typically HTTP basic or digest authentication </li></ul><ul><ul><li>Use htpasswd to generate user/pass pairs </li>...
Example HTTP Auth configuration
Authorization
<ul><li>Typically conf/authz in your repo, or “access.conf” accessible to web server </li></ul><ul><li>INI-style file with...
<ul><li>ACLs: </li></ul><ul><ul><li>[user|group] = [r|rw] </li></ul></ul><ul><ul><li>“ *” as group/user means any user </l...
ACL File: example
<ul><li>Svnserve, file access, or svn+ssh: conf/authz in your repository </li></ul><ul><li>WebDAV: anywhere.  </li></ul><u...
ACL File in WebDAV: vhost setup
Hooks
<ul><li>Allow extending SVN's capabilities via userland scripts </li></ul><ul><li>“ Hook” into specific processes: </li></...
Running a linter REPOS = &quot;$1&quot; TXN = &quot;$2&quot; PHP = &quot;/path/to/php&quot; SVNLOOK = &quot;/path/to/svnlo...
*********************************** PHP error in: test.php echo $foobar *********************************** Sample linter ...
<ul><li>Run post-commit – prevents blocking issues </li></ul><ul><li>Send email notification when tests fail </li></ul><ul...
<ul><li>Email, Nabaztag, TwitterSVN </li></ul><ul><li>Email notifications post-commit </li></ul><ul><li>SVN::Notify: </li>...
Example notification:
<ul><li>svn2feed.py: http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/svn2feed.py </li></ul><ul><li>Add svn2feed.p...
Adding svn2feed.py to your  post-commit hook: path / to / python path / to / hooks / svn2feed.py  -- svn - path   / usr / ...
<ul><li>Trigger docbook build process, or PhpDocumentor </li></ul><ul><li>Run post-commit, so as not to block </li></ul><u...
<ul><li>PHP_CodeSniffer includes a script,   bin/scripts/phpcs-svn-pre-commit </li></ul><ul><ul><li>Edit the script to pro...
<ul><ul><ul><li>Transmitting file data .svn: Commit failed (details follow): </li></ul></ul></ul><ul><ul><ul><li>svn: 'pre...
<ul><ul><ul><li>http://pear.php.net/manual/en/package.php.php-codesniffer.svn-pre-commit.php </li></ul></ul></ul>For more ...
Deploying from SVN
<ul><li>What else needs to happen at deploy time? </li></ul><ul><li>Preserve uploads </li></ul><ul><li>Set permissions </l...
<ul><li>Checkout retains link to repo </li></ul><ul><li>Meta data present on server </li></ul><ul><li>Inconsistent state d...
<ul><li>Tag and export from svn – include some tag info </li></ul><ul><li>Use symlinks to enable seamless switching </li><...
Thank you.
Upcoming SlideShare
Loading in...5
×

Practical SVN for PHP Developers

21,255

Published on

Tutorial showing how to create and administer svn repositories, work with svn, branching and tagging strategies, and using svn hooks effectively.

Published in: Technology
1 Comment
26 Likes
Statistics
Notes
  • @guest75d934f1: feature branches and/or developer branches are where unstable commits should go. However, as @guestc4db8b notes, this is also where using a distributed VCS alongside SVN can be incredibly useful -- and I cover that in my 'Git + SVN: A Match Made in ?' presentation (also up here on slideshare). I will often create a local branch in git for experimentation that I know may be unstable, and then merge only the completed feature to my main branch -- which gets pushed to SVN.

    BTW, merges in SVN are not difficult at all, and that's one of the myths we were trying to dispel with this talk.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
21,255
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
593
Comments
1
Likes
26
Embeds 0
No embeds

No notes for slide
  • Transcript of "Practical SVN for PHP Developers"

    1. 1. Practical SVN for PHP Developers Matthew Weier O'Phinney Project Lead Zend Framework Lorna Jane Mitchell Software Engineer Ibuildings
    2. 2. What is Version Control?
    3. 3. <ul><li>What did you change from the previous revision? </li></ul><ul><li>What changes have others recorded since your last local update? </li></ul>Change Management
    4. 4. Types of Version Control
    5. 5. <ul><li>Each checkout is a fully functional repository </li></ul><ul><li>Anybody may accept patches from anyone else </li></ul><ul><li>Anybody may send patches to anyone else </li></ul><ul><li>Ideal for projects with parallel feature developement </li></ul>Distributed
    6. 6. <ul><li>One canonical repository </li></ul><ul><li>All changes are submitted to the repository </li></ul><ul><li>All changes are retrieved from the repository </li></ul><ul><li>Ideal when: </li></ul><ul><ul><li>a canonical version is required, </li></ul></ul><ul><ul><li>access to the repository should be controlled </li></ul></ul>Non-Distributed
    7. 7. What is Subversion?
    8. 8. <ul><li>Non-Distributed Version Control System </li></ul><ul><li>Successor to CVS </li></ul><ul><li>Stores and versions: </li></ul><ul><ul><li>source code </li></ul></ul><ul><ul><li>documentation </li></ul></ul><ul><ul><li>anything, really </li></ul></ul>Subversion is...
    9. 9. Installing Subversion
    10. 10. Choose a Protocol
    11. 11. <ul><li>give repo access to local users </li></ul><ul><li>give users and/or groups read/write on the repo to grant access </li></ul><ul><li>file:///home/lorna/svn-repos/main/trunk/ </li></ul>Local filesystem
    12. 12. <ul><li>give repo access to users with ssh credentials </li></ul><ul><li>give users and/or groups read/write on the repo to grant access </li></ul><ul><li>svn+ssh svn://rivendell/home/lorna/svn-repos/main/trunk </li></ul>svn+ssh
    13. 13. <ul><li>make repo web-browseable and have apache handle credentials </li></ul><ul><li>basic or digest HTTP authentication (e.g., .htpasswd) </li></ul><ul><li>mod_authz_svn - an Apache module to give finer access control </li></ul><ul><li>http://svn.example.com/main/trunk </li></ul>WebDAV via HTTP/S
    14. 14. Installing on Linux
    15. 15. <ul><li>Debian/Ubuntu: aptitude install subversion </li></ul><ul><li>Fedora/RedHat: yum install subversion </li></ul>Distribution packages
    16. 16. <ul><li>download from http://subversion.tigris.org </li></ul><ul><li>check dependencies (install apache, mod_dav, etc., first) </li></ul><ul><li>compile </li></ul>From source
    17. 17. Setting up a repository
    18. 18. What is a repository ?
    19. 19. <ul><li>The place all changesets are stored </li></ul><ul><li>A black box; you may only interact with it using svn tools </li></ul>A repository is...
    20. 20. Creating the repository
    21. 21. Use “svnadmin create”
    22. 22. Create initial content
    23. 23. Commit initial structure
    24. 24. Alternate way: import into the repo
    25. 25. About repository structure
    26. 26. <ul><li>Trunk – the main code version </li></ul><ul><li>Branches – copies of code which can be modified </li></ul><ul><li>Tags – copies of code which are never changed </li></ul><ul><li>All are “cheap” copies </li></ul>Repository Structure
    27. 27. Using Subversion
    28. 28. Checkout: svn checkout (co)
    29. 29. .svn directory
    30. 30. Status: svn status (st)
    31. 31. <ul><li>' ' no modifications </li></ul><ul><li>'A' Added </li></ul><ul><li>'C' Conflicted </li></ul><ul><li>'D' Deleted </li></ul><ul><li>'M' Modified </li></ul><ul><li>'?' item is not under version control </li></ul><ul><li>'!' item is missing (removed by non-svn command) or incomplete </li></ul><ul><li>'X' external resource managed by svn (svn:externals) </li></ul>Common status codes
    32. 32. Add to repo: svn add
    33. 33. Commit to repo: svn commit (ci)
    34. 34. Changelog: svn log
    35. 35. Dealing with missing files
    36. 36. <ul><li>“ !” in the status listing </li></ul><ul><li>Usually because something was moved or deleted without using the svn tools </li></ul><ul><li>Always use svn rm and svn mv </li></ul><ul><li>To fix: update (svn up) and try again </li></ul>Missing files - ! in the status
    37. 37. What and When to commit
    38. 38. <ul><li>hourly, semi-daily, daily checkins </li></ul><ul><li>code only, tests only, docs only </li></ul>Bad practices
    39. 39. Each commit should include all code, tests, and docs related to a discrete behavior or set of functionality. The Best Practice:
    40. 40. <ul><li>Easy to “cherry-pick” changesets between branches </li></ul><ul><li>Trivial to identify changesets to rollback </li></ul>Why?
    41. 41. Examples
    42. 42. Examples
    43. 43. <ul><li>PLAN your project; break it into distinct units of functionality </li></ul><ul><li>Use an issue tracker; issues should include expectations, actual results, and reproduce code (these become your tests!) </li></ul><ul><li>No unit of functionality should take more than 3-4 hours to implement; longer, and it likely should be broken into sub-tasks. </li></ul>How?
    44. 44. Conflicts
    45. 45. <ul><li>svn blame / annotate / praise </li></ul><ul><li>shows who last edited which line </li></ul>svn blame
    46. 46. Example
    47. 47. <ul><li>Two people change same line of same file </li></ul><ul><li>svn will ask user to choose </li></ul>Conflicts
    48. 48. <ul><li>index.php.r4 version from before either your changes or the commit that has conflicted </li></ul><ul><li>index.php.r6 current repo version </li></ul><ul><li>index.php.mine working copy before server showed conflict </li></ul><ul><li>index.php whole file with some markup to show just the conflict(s) in place </li></ul>Example: conflict adds files
    49. 49. <ul><li>edit index.php until correct </li></ul><ul><li>may copy one of the &quot;extra&quot; files into place of this one </li></ul><ul><li>let SVN know you're all sorted </li></ul>svn resolved
    50. 50. <ul><li>Good team communication </li></ul><ul><li>Update often </li></ul><ul><li>Commit first! </li></ul>Avoiding Conflicts
    51. 51. Branching and Tagging
    52. 52. Patterns
    53. 53. Feature Branches Graph by Eli White
    54. 54. <ul><li>Pros: </li></ul><ul><ul><li>Features may be developed in isolation </li></ul></ul><ul><ul><li>Trunk always contains “finished” features </li></ul></ul><ul><li>Cons: </li></ul><ul><ul><li>Features may be developed in isolation </li></ul></ul><ul><ul><li>Hard to cleanly merge at times if multiple features touch the same areas of code </li></ul></ul><ul><ul><li>Harder to rollback (trunk doesn't always have discrete featuresets) </li></ul></ul>Feature Branches
    55. 55. Long-lived Branches Graph by Eli White
    56. 56. <ul><li>Pros: </li></ul><ul><ul><li>Production is always stable </li></ul></ul><ul><ul><li>Rollback by pointing to production tags </li></ul></ul><ul><li>Cons: </li></ul><ul><ul><li>Long-lived feature development often lags trunk features </li></ul></ul><ul><ul><ul><li>Difficult to determine what to merge </li></ul></ul></ul><ul><ul><li>Difficult to do parallel feature development </li></ul></ul><ul><ul><li>More difficult to rollback specific features </li></ul></ul>Long-lived Branches
    57. 57. Release Branches Graph by Eli White
    58. 58. <ul><li>Pros: </li></ul><ul><ul><li>Easy to isolate features by version (parallel development) </li></ul></ul><ul><ul><li>Possibility of keeping multiple active versions of a project </li></ul></ul><ul><li>Cons: </li></ul><ul><ul><li>Harder to merge patches between branches (files may differ widely) </li></ul></ul>Release Branches
    59. 59. Merging
    60. 60. <ul><li>Moving changes between branches (including trunk) </li></ul><ul><li>Merge single changes </li></ul><ul><li>Merging as part of a branch lifecycle </li></ul>Merging
    61. 61. <ul><li>Check out the target branch </li></ul><ul><li>From the target directory, run svn diff until the output illustrates the operation you wanted </li></ul><ul><li>Replace &quot;diff&quot; with &quot;merge&quot; </li></ul><ul><li>Review changes to working copy and/or test </li></ul>How to merge
    62. 62. <ul><li>Use “svn log” to identify discrete changesets you want to merge. </li></ul><ul><li>Use the “cherry-pick” flag of “svn merge” (-c) to merge that single changeset. </li></ul><ul><li>Works well if you're following the best practices outlined earlier! </li></ul>How to merge: the easy way
    63. 63. Administering Repositories
    64. 64. Backing up your Repository
    65. 65. <ul><li>Copying files directly can lead to corruption in the copy </li></ul><ul><li>Use “svnadmin hotcopy” or “svnadmin dump” </li></ul>svnadmin hotcopy
    66. 66. Authentication
    67. 67. <ul><li>Dependent on how the OS does authentication: </li></ul><ul><ul><li>Local accounts </li></ul></ul><ul><ul><li>“ Virtual” accounts </li></ul></ul><ul><ul><li>etc. </li></ul></ul><ul><li>SSH public keys are a common solution </li></ul>svnserve or svn+ssh
    68. 68. <ul><li>Typically HTTP basic or digest authentication </li></ul><ul><ul><li>Use htpasswd to generate user/pass pairs </li></ul></ul><ul><ul><li>Can still allow anonymous access </li></ul></ul><ul><ul><li>Configure your server to require it </li></ul></ul>WebDAV (http/https)
    69. 69. Example HTTP Auth configuration
    70. 70. Authorization
    71. 71. <ul><li>Typically conf/authz in your repo, or “access.conf” accessible to web server </li></ul><ul><li>INI-style file with [sections] </li></ul><ul><ul><li>[groups] section to define users and groups </li></ul></ul><ul><ul><li>[/path] specifies path on repo </li></ul></ul><ul><ul><li>[repo:/path] specifies path on specific repo (if more than one repo defined) </li></ul></ul>ACL File
    72. 72. <ul><li>ACLs: </li></ul><ul><ul><li>[user|group] = [r|rw] </li></ul></ul><ul><ul><li>“ *” as group/user means any user </li></ul></ul><ul><ul><li>Groups are prefixed with “@” </li></ul></ul>ACL File
    73. 73. ACL File: example
    74. 74. <ul><li>Svnserve, file access, or svn+ssh: conf/authz in your repository </li></ul><ul><li>WebDAV: anywhere. </li></ul><ul><ul><li>Tell your vhost where to find it </li></ul></ul><ul><ul><li>Must setup authorization prior to authentication </li></ul></ul>ACL File: placement
    75. 75. ACL File in WebDAV: vhost setup
    76. 76. Hooks
    77. 77. <ul><li>Allow extending SVN's capabilities via userland scripts </li></ul><ul><li>“ Hook” into specific processes: </li></ul><ul><ul><li>pre/post-commit, start-commit </li></ul></ul><ul><ul><li>pre/post-revprop-change </li></ul></ul><ul><ul><li>pre/post-lock </li></ul></ul><ul><ul><li>pre/post-unlock </li></ul></ul>What are hooks?
    78. 78. Running a linter REPOS = &quot;$1&quot; TXN = &quot;$2&quot; PHP = &quot;/path/to/php&quot; SVNLOOK = &quot;/path/to/svnlook&quot; AWK = &quot;/path/to/awk&quot; GREP = &quot;/path/to/egrep&quot; SED = &quot;/path/to/sed&quot; CHANGED = `$SVNLOOK changed -t &quot;$TXN&quot; &quot;$REPOS&quot; | $AWK '{print $2}' | $GREP php$` for FILE in $CHANGED do MESSAGE = `$SVNLOOK cat -t &quot;$TXN&quot; &quot;$REPOS&quot; &quot;$FILE&quot; | $PHP -l` if [ $? - ne 0 ] then echo 1 >& 2 echo &quot;***********************************&quot; 1 >& 2 echo &quot;PHP error in: $FILE:&quot; 1 >& 2 echo `echo &quot;$MESSAGE&quot; | $SED &quot;s| -| $FILE|g&quot;` 1 >& 2 echo &quot;***********************************&quot; 1 >& 2 exit 1 fi done
    79. 79. *********************************** PHP error in: test.php echo $foobar *********************************** Sample linter output
    80. 80. <ul><li>Run post-commit – prevents blocking issues </li></ul><ul><li>Send email notification when tests fail </li></ul><ul><li>Two approaches: </li></ul><ul><ul><li>Run entire suite </li></ul></ul><ul><ul><li>Grep committed files for classes, and test just those classes </li></ul></ul><ul><li>Typically best to do this from a Continuous Integration server, and not via subversion hooks </li></ul>Running unit tests
    81. 81. <ul><li>Email, Nabaztag, TwitterSVN </li></ul><ul><li>Email notifications post-commit </li></ul><ul><li>SVN::Notify: </li></ul><ul><ul><li>http://search.cpan.org/~dwheeler/SVN-Notify-2.79/lib/SVN/Notify.pm </li></ul></ul><ul><ul><li>Can selectively determine which people/lists get notifications based on commit path </li></ul></ul><ul><ul><li>Plain text and/or HTML emails </li></ul></ul>Sending notifications
    82. 82. Example notification:
    83. 83. <ul><li>svn2feed.py: http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/svn2feed.py </li></ul><ul><li>Add svn2feed.py to your hooks/ directory </li></ul>Publishing RSS Feeds
    84. 84. Adding svn2feed.py to your post-commit hook: path / to / python path / to / hooks / svn2feed.py -- svn - path / usr / bin / -- max - items = 100 -- format = atom -- revision &quot;$REV&quot; – item - url &quot;http://localhost/svn/&quot; -- feed - url = &quot;http://localhost/rss/svn.rss&quot; -- feed - file &quot;path/to/rss/svn.rss&quot; &quot;$REPOS&quot; &
    85. 85. <ul><li>Trigger docbook build process, or PhpDocumentor </li></ul><ul><li>Run post-commit, so as not to block </li></ul><ul><li>Typically best done from a CI server, and not subversion hooks </li></ul>Generating documentation
    86. 86. <ul><li>PHP_CodeSniffer includes a script, bin/scripts/phpcs-svn-pre-commit </li></ul><ul><ul><li>Edit the script to provide the path to svnlook: </li></ul></ul><ul><ul><li>define('PHP_CODESNIFFER_SVNLOOK', '/usr/bin/svnlook'); </li></ul></ul><ul><li>Edit the pre-commit hook script to invoke the script: </li></ul><ul><ul><li>/path/to/bin/scripts/phpcs-svn-pre-commit &quot;$REPOS&quot; -t &quot;$TXN&quot; >&2 || exit 1 </li></ul></ul>Running PHP_CodeSniffer
    87. 87. <ul><ul><ul><li>Transmitting file data .svn: Commit failed (details follow): </li></ul></ul></ul><ul><ul><ul><li>svn: 'pre-commit' hook failed with error output: </li></ul></ul></ul><ul><ul><ul><li>FILE: temp.php </li></ul></ul></ul><ul><ul><ul><li>--------------------------------------------------------------- </li></ul></ul></ul><ul><ul><ul><li>FOUND 1 ERROR(S) AND 0 WARNING(S) AFFECTING 1 LINE(S) </li></ul></ul></ul><ul><ul><ul><li>--------------------------------------------------------------- </li></ul></ul></ul><ul><ul><ul><li>2 | ERROR | Missing file doc comment </li></ul></ul></ul><ul><ul><ul><li>-------------------------------------------------------------- </li></ul></ul></ul>PHP_CodeSniffer hook output
    88. 88. <ul><ul><ul><li>http://pear.php.net/manual/en/package.php.php-codesniffer.svn-pre-commit.php </li></ul></ul></ul>For more info on PHP_CodeSniffer:
    89. 89. Deploying from SVN
    90. 90. <ul><li>What else needs to happen at deploy time? </li></ul><ul><li>Preserve uploads </li></ul><ul><li>Set permissions </li></ul><ul><li>Database patches </li></ul>Deployment Considerations
    91. 91. <ul><li>Checkout retains link to repo </li></ul><ul><li>Meta data present on server </li></ul><ul><li>Inconsistent state during update </li></ul><ul><li>Export is clean copy, no dependencies </li></ul><ul><li>Other ways to keep track of version </li></ul>Checkout or Export
    92. 92. <ul><li>Tag and export from svn – include some tag info </li></ul><ul><li>Use symlinks to enable seamless switching </li></ul><ul><li>Wrap in a script </li></ul><ul><li>Have a rollback plan/script </li></ul><ul><li>Consider database strategies </li></ul>Best Practices
    93. 93. Thank you.
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×