Practical SVN for PHP Developers


Published on

Published in: Technology
No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • 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> </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 </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> </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> </li></ul><ul><li>Add to your hooks/ directory </li></ul>Publishing RSS Feeds
    84. 84. Adding to your post-commit hook: path / to / python path / to / hooks / -- 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> </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.