SHARE
TWEET

Untitled

xdxdxd123 May 22nd, 2017 702 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. What readers are saying about
  2. Pragmatic Version Control using Subversion
  3. I expected a lot, but you surprised me with even more. Hav-
  4. ing used CVS for years I hesitated to try Subversion until
  5. now, although I knew it would solve many of the shortcom-
  6. ings of CVS. After reading your book, my excuses to stay
  7. with CVS disappeared. Oh, and coming from the Pragmatic
  8. Bookshelf this book is fun to read too. Thanks Mike.
  9. Steffen Gemkow
  10. Managing Director, ObjectFab GmbH
  11. I’m a long-time user of CVS and I’ve been skeptical of Sub-
  12. version, wondering if it would ever be “ready for prime time.”
  13. Until now. Thanks to Mike Mason for writing a clear, con-
  14. cise, gentle introduction to this new tool. After reading this
  15. book, I’m actually excited about the possibilities for version
  16. control that Subversion brings to the table.
  17. David Rupp
  18. Senior Software Engineer, Great-West Life & Annuity
  19. This was exactly the Subversion book I was waiting for. As
  20. a long-time Perforce and CVS user and administrator, and
  21. in my role as an agile tools coach, I wanted a compact book
  22. that told me just what I needed to know. This is it.
  23. Within a couple of hours I was up and running against
  24. remote Subversion servers, and setting up my own local
  25. servers too. Mike uses a lot of command-line examples to
  26. guide the reader, and as a Windows user I was worried at
  27. first. My fears were unfounded though—Mike’s examples
  28. were so clear that I think I’ll stick to using the command line
  29. from now on! I thoroughly recommend this book to anyone
  30. getting started using or administering Subversion.
  31. Mike Roberts
  32. Project co-Lead, CruiseControl.NET
  33. Pragmatic Version Control
  34. using Subversion, 2nd Edition
  35. Mike Mason
  36. The Pragmatic Bookshelf
  37. Raleigh, North Carolina Dallas, Texas
  38. ?? ?????
  39. ?
  40. ?
  41. ?
  42. ?
  43. ?
  44. ?
  45. Many of the designations used by manufacturers and sellers to distinguish
  46. their products are claimed as trademarks. Where those designations appear
  47. in this book, and The Pragmatic Programmers, LLC was aware of a trademark
  48. claim, the designations have been printed in initial capital letters or in all
  49. capitals. The Pragmatic Starter Kit, The Pragmatic Programmer, Pragmatic
  50. Programming, Pragmatic Bookshelf and the linking g device are trademarks
  51. of The Pragmatic Programmers, LLC.
  52. Every precaution was taken in the preparation of this book. However, the
  53. publisher assumes no responsibility for errors or omissions, or for damages
  54. that may result from the use of information (including program listings) con-
  55. tained herein.
  56. Our Pragmatic courses, workshops, and other products can help you and
  57. your team create better software and have more fun. For more information,
  58. as well as the latest Pragmatic titles, please visit us at
  59. http://www.pragmaticprogrammer.com
  60. Copyright © 2006 The Pragmatic Programmers LLC.
  61. All rights reserved.
  62. No part of this publication may be reproduced, stored in a retrieval system,
  63. or transmitted, in any form, or by any means, electronic, mechanical, photo-
  64. copying, recording, or otherwise, without the prior consent of the publisher.
  65. Printed in the United States of America.
  66. ISBN 0-9776166-5-7
  67. Printed on acid-free paper with 85% recycled, 30% post-consumer content.
  68. First printing, May 2006
  69. Version: 2006-5-12
  70. Contents
  71. Preface viii
  72. 1 Introduction 1
  73. 1.1 Version Control in Action . . . . . . . . . . . . . 2
  74. 1.2 Road Map . . . . . . . . . . . . . . . . . . . . . . 6
  75. 1.3 Why Choose Subversion . . . . . . . . . . . . . . 6
  76. 2 What is Version Control? 9
  77. 2.1 The Repository . . . . . . . . . . . . . . . . . . . 9
  78. 2.2 What Should We Store? . . . . . . . . . . . . . . 11
  79. 2.3 Working Copies and Manipulating Files . . . . . 12
  80. 2.4 Projects, Directories, and Files . . . . . . . . . . 15
  81. 2.5 Where Do Versions Come In? . . . . . . . . . . . 16
  82. 2.6 Tags . . . . . . . . . . . . . . . . . . . . . . . . . 18
  83. 2.7 Branches . . . . . . . . . . . . . . . . . . . . . . 19
  84. 2.8 Merging . . . . . . . . . . . . . . . . . . . . . . . 22
  85. 2.9 Locking Options . . . . . . . . . . . . . . . . . . 23
  86. 2.10 Configuration Management (CM) . . . . . . . . . 26
  87. 3 Getting Started with Subversion 28
  88. 3.1 Installing Subversion . . . . . . . . . . . . . . . 28
  89. 3.2 Creating a Repository . . . . . . . . . . . . . . . 33
  90. 3.3 Creating a Simple Project . . . . . . . . . . . . . 34
  91. 3.4 Starting to Work with a Project . . . . . . . . . . 37
  92. 3.5 Making Changes . . . . . . . . . . . . . . . . . . 39
  93. 3.6 Updating the Repository . . . . . . . . . . . . . . 41
  94. 3.7 When Worlds Collide . . . . . . . . . . . . . . . . 44
  95. 3.8 Conflict Resolution . . . . . . . . . . . . . . . . . 47
  96. CONTENTS vi
  97. 4 How To... 52
  98. 4.1 Our Basic Philosophy . . . . . . . . . . . . . . . 53
  99. 4.2 Important Steps When Using Version Control . 53
  100. 5 Accessing a Repository 55
  101. 5.1 Network Protocols . . . . . . . . . . . . . . . . . 55
  102. 5.2 Choosing a Networking Option . . . . . . . . . . 60
  103. 6 Common Subversion Commands 62
  104. 6.1 Checking Things Out . . . . . . . . . . . . . . . 62
  105. 6.2 Keeping Up-to-Date . . . . . . . . . . . . . . . . 64
  106. 6.3 Adding Files and Directories . . . . . . . . . . . 66
  107. 6.4 Properties . . . . . . . . . . . . . . . . . . . . . . 66
  108. 6.5 Copying and Moving Files and Directories . . . 75
  109. 6.6 Seeing What Has Changed . . . . . . . . . . . . 80
  110. 6.7 Handling Merge Conflicts . . . . . . . . . . . . . 86
  111. 6.8 Committing Changes . . . . . . . . . . . . . . . 91
  112. 6.9 Examining Change History . . . . . . . . . . . . 91
  113. 6.10 Removing a Change . . . . . . . . . . . . . . . . 95
  114. 7 File Locking and Binary Files 99
  115. 7.1 File Locking Overview . . . . . . . . . . . . . . . 99
  116. 7.2 File Locking in Practice . . . . . . . . . . . . . . 100
  117. 7.3 When to use Locking . . . . . . . . . . . . . . . . 106
  118. 8 Organizing Your Repository 107
  119. 8.1 A Simple Project . . . . . . . . . . . . . . . . . . 107
  120. 8.2 Multiple Projects . . . . . . . . . . . . . . . . . . 108
  121. 8.3 Multiple Repositories . . . . . . . . . . . . . . . 109
  122. 9 Using Tags and Branches 111
  123. 9.1 Tags and Branches . . . . . . . . . . . . . . . . . 112
  124. 9.2 Creating a Release Branch . . . . . . . . . . . . 115
  125. 9.3 Working in a Release Branch . . . . . . . . . . . 117
  126. 9.4 Generating a Release . . . . . . . . . . . . . . . 119
  127. 9.5 Fixing Bugs in a Release Branch . . . . . . . . . 121
  128. 9.6 Developer Experimental Branches . . . . . . . . 124
  129. 9.7 Working with Experimental Code . . . . . . . . 126
  130. 9.8 Merging the Experimental Branch . . . . . . . . 126
  131. CONTENTS vii
  132. 10 Creating a Project 128
  133. 10.1 Creating the Initial Project . . . . . . . . . . . . 129
  134. 10.2 Structure within the Project . . . . . . . . . . . 131
  135. 10.3 Sharing Code between Projects . . . . . . . . . . 135
  136. 11 Third-Party Code 141
  137. 11.1 Binary Libraries . . . . . . . . . . . . . . . . . . 141
  138. 11.2 Libraries with Source Code . . . . . . . . . . . . 144
  139. 11.3 Keyword Expansion during Imports . . . . . . . 150
  140. A Install, Network, Secure, and Administer 151
  141. A.1 Installing Subversion . . . . . . . . . . . . . . . 151
  142. A.2 Networking with svnserve . . . . . . . . . . . . . 153
  143. A.3 Networking with svn+ssh . . . . . . . . . . . . . 154
  144. A.4 Networking with Apache . . . . . . . . . . . . . . 157
  145. A.5 Securing Subversion . . . . . . . . . . . . . . . . 163
  146. A.6 Backing Up Your Repository . . . . . . . . . . . 170
  147. B Migrating to Subversion 174
  148. B.1 Getting cvs2svn . . . . . . . . . . . . . . . . . . . 175
  149. B.2 Choosing How Much to Convert . . . . . . . . . 175
  150. B.3 Converting Your Repository . . . . . . . . . . . . 176
  151. C Third-Party Subversion Tools 178
  152. C.1 TortoiseSVN . . . . . . . . . . . . . . . . . . . . . 178
  153. C.2 IDE Integration . . . . . . . . . . . . . . . . . . . 185
  154. C.3 Other Tools . . . . . . . . . . . . . . . . . . . . . 186
  155. D Advanced Topics 188
  156. D.1 Programmatic Access to Subversion . . . . . . . 188
  157. D.2 Advanced Repository Management . . . . . . . 193
  158. E Command Summary and Recipes 197
  159. E.1 Subversion Command Summary . . . . . . . . . 197
  160. E.2 Recipes . . . . . . . . . . . . . . . . . . . . . . . 208
  161. F Other Resources 214
  162. F.1 Online Resources . . . . . . . . . . . . . . . . . . 214
  163. F.2 Bibliography . . . . . . . . . . . . . . . . . . . . 215
  164. Preface
  165. I was pretty excited when I heard about the Pragmatic Starter
  166. Kit—finally some guidance on the basic stuff all projects need
  167. to get right. The opportunity to produce a Subversion edition
  168. of Pragmatic Version Control was one I couldn’t miss. Sub-
  169. version had previously saved me (and my team) from version
  170. control hell, and I wanted to do my part to help promote a
  171. great new version control system.
  172. Version control adds an immense amount to a project. It gives
  173. you a safety net, helps your team collaborate effectively, lets
  174. you organize your builds and QA, and even allows you to do
  175. some detective work if things go wrong. I hope this new edition
  176. of Pragmatic Version Control will help you and your team get
  177. started and succeed with Subversion.
  178. Acknowledgments
  179. I’d like to thank Dave and Andy for taking a chance on my
  180. writing the book and to thank Dave for being such an excellent
  181. editor. I wasn’t really sure what I was getting myself into, and
  182. Dave’s advice and guidance were invaluable.
  183. The book received plenty of scrutiny by reviewers; I’d like to
  184. thank Brad Appleton, Branko
  185. ˇ
  186. Cibej, Martin Fowler, Steffen
  187. Gemkow, Robert Rasmussen, Mike Roberts, and David Rupp
  188. for their well-thought-out comments and suggestions. I’m
  189. frankly amazed by the quality of feedback I got—great sugges-
  190. tions, highly technical comments and plenty of people think-
  191. ing about the “bigger picture.”
  192. Everyone at ThoughtWorks has been really supportive of my
  193. book writing efforts, including several people who took the
  194. time to look through early drafts of the book, and I’d like to
  195. P REFACE ix
  196. thank all those who gave me advice and guidance. I’d particu-
  197. larly like to thank the Calgary office for welcoming me into the
  198. fold this year and for enabling me to get stuff finished when
  199. the crunch point came.
  200. Finally I’d like to thank Martin, Mike, and Michelle for making
  201. me believe I could really write the book and for their encour-
  202. agement along the way.
  203. December 2004
  204. Acknowledgments for the Second Edition
  205. Subversion has come a long way since the first edition of this
  206. book. It has new features, performance and stability improve-
  207. ments, and most importantly has excellent integration with
  208. many leading tools and IDEs. Subversion is now probably
  209. the number one version control tool in use on ThoughtWorks
  210. projects and is a serious competitor to every commercial tool
  211. on the market.
  212. I’d like to thank everyone who has given me support and feed-
  213. back since the publication of the original book. It’s very grat-
  214. ifying to know people have used the book, enjoyed reading it,
  215. and that Subversion has brought them success. Please keep
  216. the feedback coming, it’s invaluable.
  217. The following people generously contributed time reading the
  218. updated manuscript, and provided fantastic feedback: Steve
  219. Berczuk, Nick Coyne, David Rupp and Nate Schutta. Thank
  220. you all for your time, effort, and great ideas.
  221. I’d like to thank Dave and Andy for the opportunity to update
  222. the book to cover new features in Subversion, and in partic-
  223. ular I’d like to thank Andy for taking on the editor’s job this
  224. time around. As I’ve told many friends and colleagues, a good
  225. editor is a crucial part of the writing process, and I feel very
  226. lucky to have worked with both Andy and Dave.
  227. Mike Mason
  228. May 2006
  229. mike@mikemason.ca
  230. P REFACE x
  231. Typographic Conventions
  232. italic font Italics indicate a term that is being defined, or
  233. borrowed from another language.
  234. files Files (and directories ) are indicated like this.
  235. commands Commands (and options such as -h ) are shown
  236. like this.
  237. output Output (as well as things you might need to type)
  238. is indicated like this. If commands are too long
  239. for a single line they’re split onto multiple lines
  240. using a \ (backward slash).
  241. CVS Hint: This kind of text indicates a hint for users famil-
  242. iar with CVS.
  243. This warning sign indicates this material is more
  244. advanced and can be skipped on your first read-
  245. ing.
  246. “Joe the developer,” our cartoon friend, asks a
  247. related question that you may find useful.
  248. Chapter 1
  249. Introduction
  250. This book tells you how to improve the effectiveness of your
  251. software development process using version control.
  252. Version control, sometimes called source code control, is the
  253. first leg of our project support tripod. We view the use of
  254. version control as mandatory on all projects.
  255. Version control offers many advantages to both teams and
  256. individuals:
  257. • It gives the team a project-wide undo button; nothing is
  258. final, and mistakes are easily rolled back. Imagine you’re
  259. using the world’s most sophisticated word processor. It
  260. has every function imaginable, except one. For some rea-
  261. son, they forgot to add support for a DELETE key. Think
  262. how carefully and slowly you’d have to type, particularly
  263. as you got near the end of a large document. One mis-
  264. take, and you’d have to start again. It’s the same with
  265. version control; having the ability to go back an hour, a
  266. day, or a week frees your team to work quickly, confident
  267. that they have a way of fixing mistakes.
  268. • It allows multiple developers to work on the same code
  269. base in a controlled manner. The team no longer loses
  270. changes when someone overwrites the edits made by
  271. another team member.
  272. • The version control system keeps a record of the changes
  273. made over time. If you come across some “surprising
  274. code,” it’s easy to find out who made the change, when,
  275. and (with any luck) why.
  276. V ERSION C ONTROL IN A CTION 2
  277. • A version control system allows you to support multiple
  278. releases of your software at the same time as you con-
  279. tinue with the main line of development. With a version
  280. control system, there’s no longer a need for the team to
  281. stop work during a code freeze just before release.
  282. • Version control is a project-wide time machine, allowing
  283. you to dial in a date and see exactly what the project
  284. looked like on that date. This is useful for research,
  285. but it is essential for regenerating prior releases for cus-
  286. tomers with problems.
  287. This book focuses on version control from a project perspec-
  288. tive. Rather than simply list the commands available in a
  289. version control system, we explain the tasks you need to per-
  290. form well in a successful project and then show how a version
  291. control system can help.
  292. Let’s start with a small story....
  293. 1.1 Version Control in Action
  294. Fred rolls into the office eager to continue working on the new
  295. Orinoco book ordering system. (Why Orinoco? Fred’s com-
  296. pany uses the names of rivers for all internal projects.) After
  297. getting his first cup of coffee, Fred updates his local copy of
  298. the project’s source code with the latest versions from the cen-
  299. tral version control system. In the log that lists the updated
  300. files, he notices that Wilma has changed code in the basic
  301. Orders class. Fred gets worried that this change might affect
  302. his work, but today Wilma is off at the client’s site, installing
  303. the latest release, so he can’t ask her directly. Instead, Fred
  304. asks the version control system to display the notes associ-
  305. ated with the change to Orders . Wilma’s comment does little
  306. to reassure him:
  307. Added new deliveryPreferences field to the Orders class
  308. To find out what’s going on, he goes back to the version con-
  309. trol system and asks to see the actual changes made to the
  310. source file. He sees that Wilma has added a couple of instance
  311. variables, but they are set to default values, and nothing
  312. seems to change them. This might be a problem in the future,
  313. but it is nothing that will stop him today, so Fred continues
  314. working.
  315. V ERSION C ONTROL IN A CTION 3
  316. As he works on his code, Fred adds a new class and a cou-
  317. ple of test classes to the system. Fred adds the names of the
  318. files he creates to the version control system as he creates
  319. them; the files themselves won’t be added until he commits
  320. his changes, but adding their names now means he won’t for-
  321. get to add them later.
  322. A couple of hours into the day, Fred has completed the first
  323. part of some new functionality. It passes its tests, and it won’t
  324. affect anything in the rest of the system, so he decides to
  325. check it all into the version control system, making it available
  326. to the rest of the team. Over the years, Fred has found that
  327. checking code in and out frequently works best for him: it’s
  328. a lot easier to reconcile the occasional conflict if you have to
  329. worry about only a couple of files rather than a week’s worth
  330. of changes from the whole team.
  331. Why You Should Never Answer the Phone
  332. Just as Fred is about to start the next round of coding, his
  333. phone rings. It’s Wilma, calling from the client’s site. It looks
  334. like there’s a bug in the release she is installing: printed
  335. invoices are not calculating sales tax on shipping amounts.
  336. The client is going ballistic, and they need a fix now.
  337. ...Unless You Use Version Control
  338. Fred double-checks the name of the release with Wilma and
  339. then tells the version control system to check out all the files
  340. in that version of the software. He puts it in a temporary
  341. directory on his PC, as he intends to delete it after he finishes
  342. the work. He now has two copies of the system’s source code
  343. on his computer: the trunk (the main line of development)
  344. and the version released to the client. Because he is about to
  345. fix a bug, he tells the version control system to tag his source
  346. code with a label. (He’ll add another tag when he has fixed
  347. the bug.) These tags act as flags you leave behind to mark
  348. significant points in the development. By using consistently
  349. named tags before and after he makes the change, other folks
  350. in his team will be able to see exactly what changed should
  351. they look at it later.
  352. V ERSION C ONTROL IN A CTION 4
  353. In order to isolate the problem, Fred first writes a test. Sure
  354. enough, it looks like no one ever checked the sales tax cal-
  355. culation when shipping was involved, because his test imme-
  356. diately shows the problem. (Fred makes a note to raise this
  357. during this iteration’s review meeting; this is something that
  358. should never have gone out the door.) Sighing, Fred adds
  359. the line of code that adds shipping to the taxable total, com-
  360. piles, and checks that his test passes. He reruns the whole
  361. test suite as a quick sanity test and checks the fixed code
  362. back into the central version control system. Finally, he tags
  363. the release branch indicating that the bug is fixed. He sends
  364. a note off to QA, who is responsible for shipping emergency
  365. releases to the client. Using his tag, they’ll be able to instruct
  366. the build system to produce a delivery disk that includes his
  367. fix. Fred then phones Wilma and tells her the fix is in the
  368. hands of QA and should be with her soon.
  369. Having finished with this little distraction, Fred removes the
  370. source for the released code from his local machine: there’s
  371. no point in cluttering things up, and the changes he has made
  372. are safely tucked back into the central server. He then gets to
  373. wondering: is the sales tax bug he found in the released code
  374. also present in the current development version? The quick-
  375. est way to check is to add the test he wrote in the released ver-
  376. sion to the development test suite. He tells the version control
  377. system to merge that particular change in the release branch
  378. into the appropriate file in the development copy. The merge
  379. process takes whatever changes were made to the release
  380. files and makes the same changes to the development ver-
  381. sion. When he runs the tests, his new test fails: the bug
  382. is indeed present. He then moves his fix from the release
  383. branch into the development version. (He doesn’t need the
  384. release branch’s code on his machine to do any of this; all
  385. the changes are being fetched from the central version control
  386. system.) Once he has the tests all running again, he commits
  387. this change into the version control system. That’s one less
  388. bug that’ll bite the team next time.
  389. Crisis over, Fred gets back to working on his own tasks for the
  390. day. He spends a happy afternoon writing tests and code and
  391. toward the end of the day decides he is done. While he has
  392. been working, other folks in his team have also been making
  393. V ERSION C ONTROL IN A CTION 5
  394. changes, so he uses the version control system to take their
  395. work and apply it to his local copy of the source. He runs
  396. the tests one last time and then checks his changes back in,
  397. ready to start work the next day.
  398. Tomorrow...
  399. Unfortunately, the next day brings its own surprises. Over-
  400. night Fred’s central heating finally gives up the ghost. As Fred
  401. lives in Minnesota, and as it’s February, this isn’t something
  402. to be taken lightly. Fred calls into work to say he’ll be out
  403. most of the day waiting for the repair folks to arrive.
  404. However, that doesn’t mean he has to stop working. Accessing
  405. his office network using a secure connection over the public
  406. Internet, Fred checks out the latest development code onto
  407. his laptop. Because he checked in before he went home the
  408. previous night, everything is there and up-to-date. He con-
  409. tinues to work at home, wrapped in a blanket and sitting by
  410. the fire. Before he stops for the day, he checks his changes in
  411. from the laptop so they’ll be available to him at work the next
  412. day. Life is good (except for the heating repair bill).
  413. Storybook Projects
  414. The correct use of version control on Fred and Wilma’s project
  415. was pretty unobtrusive, but it gave them control and helped
  416. them communicate, even when Wilma was miles away. Fred
  417. could research changes made to code and apply a bug fix to
  418. multiple releases of their application. Their version control
  419. system supports offline work, so Fred gained a degree of loca-
  420. tion independence: he could work from home during his heat-
  421. ing problems. Because they had version control in place (and
  422. they knew how to use it), Fred and Wilma dealt with a number
  423. of project emergencies without experiencing the panic that so
  424. often characterizes our response to the unexpected.
  425. Using version control gave Fred and Wilma the control and
  426. the flexibility to deal with the vagaries of the real world. That’s
  427. what this book is all about.
  428. R OAD M AP 6
  429. 1.2 Road Map
  430. Chapter 2 introduces the concepts and terminology of version
  431. control systems. Many version control systems are available
  432. from which to choose. In this book we’re going to focus on
  433. Subversion, an open-source tool available for free over the
  434. internet. Subversion is the successor to CVS, which is itself
  435. one of the most popular version control systems available.
  436. Chapter 3, Getting Started with Subversion, is a tutorial intro-
  437. duction to using Subversion. The remainder of the book is a
  438. set of recipes for using Subversion in projects, divided into six
  439. main chapters. Each chapter contains a number of recipes:
  440. • Connecting to Subversion in different ways
  441. • Using common Subversion commands
  442. • Organizing files inside Subversion
  443. • Using tags and branches to handle releases and experi-
  444. mental code
  445. • Creating a project
  446. • Handling third-party code
  447. We end with a set of appendixes providing reference informa-
  448. tion and more in-depth discussion on using Subversion:
  449. • Networking, securing, and backing up your repository
  450. • Migrating to Subversion
  451. • Using Third-party Subversion tools
  452. • Summary of recipes and Subversion commands
  453. • Using other resources available on the Internet
  454. 1.3 Why Choose Subversion
  455. Whilst this book is about version control in general, we’re
  456. choosing to focus on Subversion as our tool of choice. Since a
  457. significant number of different version control tools are avail-
  458. able, it’s probably worth mentioning why you’d want to pick
  459. Subversion.
  460. W HY C HOOSE S UBVERSION 7
  461. The Subversion project was started by a team of developers
  462. who had extensive experience with CVS (some of them had
  463. literally written books on the subject) but who had decided
  464. the time had come to replace the aging system. The Subver-
  465. sion developers were painfully aware of CVS’s shortcomings
  466. and made sure they designed a high-performance, modern
  467. version control system. Their goal was not to create a rad-
  468. ical new paradigm in version control—the CVS development
  469. model had proven highly successful—but to replace CVS with
  470. a new system that fixed all of CVS’s wrinkles.
  471. This might not sound like Subversion is anything ground-
  472. breaking, but bear in mind that CVS is already miles ahead
  473. of many other version control tools. Subversion’s feature set
  474. puts it at the forefront of what’s available today.
  475. Versioning for Files, Directories, and Metadata
  476. Directories, as well as files, are versionable objects in Subver-
  477. sion. This means that moving or renaming a directory is a
  478. first-class operation—files within the directory automatically
  479. move with it, and history is preserved correctly.
  480. Files and directories can also have metadata associated with
  481. them using Subversion properties. Properties can be textual
  482. or binary and are versioned in the same way as file con-
  483. tents, changing over time, being merged with newer revisions,
  484. etc. Properties are used extensively to control how Subversion
  485. handles files, keyword expansion, stuff you’d like it to ignore,
  486. and so on. The great thing about properties is that any Sub-
  487. version client can access them, allowing third-party tools to
  488. integrate much more elegantly with your repository.
  489. Atomic Commits and Changesets
  490. Subversion uses a database transaction analogy when a user
  491. commits a change to the repository, making sure that either
  492. the entire change is successfully committed or it’s aborted
  493. and rolled back. It’s also impossible to see half a change
  494. whilst someone is making a commit—you’ll see the state of
  495. the repository either before the change or after. This behavior
  496. is known as atomic commit and is useful because every devel-
  497. oper will always have a consistent view of the repository. If
  498. W HY C HOOSE S UBVERSION 8
  499. your network connection goes down whilst you’re committing
  500. a change, you won’t leave half your changes in the repository,
  501. and the change will be rolled back cleanly.
  502. As part of the atomic commit process, Subversion groups all
  503. of your changes into a revision (sometimes called a changeset) revision
  504. and assigns a revision number to the change. By grouping
  505. revision number
  506. changes to multiple files into a single logical unit, developers
  507. are able to better organize and track their changes.
  508. Excellent Networking Support
  509. Subversion has a highly efficient network protocol and stores
  510. pristine copies of your working files locally, allowing a user to
  511. see what changes they’ve made without even contacting the
  512. server. Subversion provides a variety of networking options,
  513. including the ability to leverage Secure Shell (SSH) and the
  514. Apache web server to make repositories available over a public
  515. network.
  516. Cheap Branching, Tagging, and Merging
  517. In many version control systems, creating a branch is a big
  518. deal. In CVS, for example, branching or labeling code requires
  519. the server to access and modify every file in the repository!
  520. Subversion uses an efficient database model to branch and
  521. merge files, making these operations quick and painless.
  522. True Cross-Platform Support
  523. Subversion is available for a wide variety of platforms, and,
  524. most important, the server will run well on Windows. This
  525. significantly lowers the barrier to entry for teams that don’t
  526. have a Unix server available and makes it much easier to get
  527. started—you can set up a server on a spare Windows box (or
  528. even one that’s in use!) and migrate to another machine once
  529. Subversion has proven itself.
  530. Chapter 2
  531. What is Version Control?
  532. A version control system is a place to store all the various revi-
  533. sions of the stuff you write while developing an application.
  534. They’re basically very simple. Unfortunately, over the years,
  535. people have started using different terms for the various com-
  536. ponents of version control. And this can lead to confusion. So
  537. let’s start by defining some of the terms we’ll be using.
  538. 2.1 The Repository
  539. You may have noticed that we wimped out; we said that “a
  540. version control system is a place to store...the stuff you write,”
  541. but we never said exactly where all this stuff is stored. In fact,
  542. it all goes in the repository. repository
  543. In almost all version control systems, the repository is a cen-
  544. tral place that holds the master copy of all versions of your
  545. project’s files. Some version control systems use a database
  546. as the repository, some use regular files, and some use a com-
  547. bination of the two. Either way, the repository is clearly a piv-
  548. otal component of your version control strategy. You need it
  549. sitting on a safe, secure, and reliable machine. And it should
  550. go without saying that it needs to get backed up regularly.
  551. In the old days, the repository and all its users had to share
  552. a machine (or at least share a filesystem). This turns out to
  553. be fairly limiting; it was hard to have developers working at
  554. different sites or working on different kinds of machines or
  555. operating systems. As a result, most version control systems
  556. today support networked operation; as a developer you can
  557. T HE R EPOSITORY 10
  558. Different Flavors of Networked Access
  559. The writers of version control systems sometimes have
  560. different definitions of what networked means. For
  561. some, it means accessing the files in a repository over
  562. shared network drives (such as Windows shares or NFS
  563. mounts). For others it means having a client-server
  564. architecture, where clients interact with server repos-
  565. itories over a network. Both can work (although the
  566. former is hard to design correctly if the underlying file-
  567. sharing mechanism doesn’t support locking reliably).
  568. However, you may find that deployment and security
  569. issues dictate which systems you can use.
  570. If a version control system needs access to shared
  571. drives, and you need to access it from outside your
  572. internal network, then you’ll need to make sure your
  573. organization allows you to access the data this way.
  574. Virtual Private Network (VPN) packages allow this kind
  575. of secure access, but not all companies run VPNs.
  576. Subversion uses the client-server model for remote
  577. access.
  578. access the repository over a network, with the repository act-
  579. ing as a server and the version control tools acting as clients.
  580. This is tremendously enabling. It doesn’t matter where the
  581. developers are; as long as they can connect over a network
  582. to the repository, they can access all the project’s code and
  583. its history. And they can do it securely; you can even use
  584. the Internet to access your repository without sharing your
  585. precious source code with a nosy competitor.
  586. This does lead to an interesting question, though. What hap-
  587. pens if you need to do development but you don’t have a
  588. network connection to your repository? The simple answer
  589. is, “it depends.” Some version control systems are designed
  590. solely for use while connected to the repository; it is assumed
  591. that you’ll always be online and that you won’t be able to
  592. change source code without first contacting the central repos-
  593. itory. Other systems are more lenient. The Subversion sys-
  594. tem, which we use for our examples in this book, is one of
  595. W HAT S HOULD W E S TORE ? 11
  596. the latter. We can edit away on our laptops at 35,000 feet
  597. and then resynchronize the changes when we get to our hotel
  598. rooms. This online/offline issue is a crucial one when choos-
  599. ing a version control system; make sure that whatever prod-
  600. uct you choose supports your style of working.
  601. Some version control systems support the notion of multiple
  602. repositories instead of a single central repository. Developers
  603. can swap sets of changes between the separate repositories.
  604. These are often called decentralized version control systems
  605. and are popular when large numbers of developers need to
  606. operate semiautonomously, most famously for developing the
  607. Linux kernel. Examples of decentralized version control sys-
  608. tems include BitKeeper, Arch, and SVK. These systems have
  609. a very different style of development, and we won’t discuss
  610. them further in this book.
  611. 2.2 What Should We Store?
  612. All the things in your project are stored in the repository. But
  613. what exactly are the things we’re talking about?
  614. Well, you obviously need program source files to build your
  615. project: the Java, C#, Ruby, or whatever language you’re
  616. using to write your application. In fact, some folks think that
  617. this source code is such an important component of version
  618. control that they use the term source code control systems.
  619. The source code is certainly important, but many people make
  620. the mistake of forgetting all the other things that need to be
  621. stored under version control. For example, if you’re a Java
  622. programmer, you may use the Ant tool to compile your source.
  623. Ant uses a script, normally called build.xml , to control what
  624. it does. This script is part of the build process; without it
  625. you can’t build the application, so it should be stored in the
  626. version control system.
  627. Similarly, many projects use metadata to drive their config-
  628. uration. This metadata should be in the repository too. So
  629. should any scripts you use to create a release CD, test data
  630. used by QA, and so on.
  631. W ORKING C OPIES AND M ANIPULATING F ILES 12
  632. In fact, there’s an easy test when it comes to deciding what
  633. goes in and what stays out. Simply ask yourself “if we didn’t
  634. have an up-to-date version of x, could we build, test, and
  635. deliver our application?” If the answer is “no,” then x should
  636. be in the repository.
  637. As well as all the files that go toward creating the released
  638. software, you should also store your noncode project artifacts
  639. under version control (anything you’ll need to make sense
  640. of things later), including the project’s documentation (both
  641. internal and external). It might also include the text of signif-
  642. icant e-mails, minutes of meetings, information you find on
  643. the web—anything that contributes to the project.
  644. 2.3 Working Copies and Manipulating Files
  645. The repository stores all the files in our project, but that
  646. doesn’t help us much if we need to add some magic new fea-
  647. ture into our application; we need the files where we can get
  648. to them. This place is called our local working copy. working copy
  649. The working copy is a local copy of all of the things that we
  650. need from the repository to work on our part of the project.
  651. For small- to medium-sized projects, the working copy will
  652. probably simply be a copy of all the code and other artifacts
  653. in the project. For larger projects, you may arrange things so
  654. that developers can work with just a subset of the project’s
  655. code, saving them time when building and helping to isolate
  656. subsystems of the system. You might also hear the working
  657. copy called the working directory or simply the workspace.
  658. In order to populate our working copy initially, we need to get
  659. things out of the repository. Different version control systems
  660. have different names for this process, but the most common
  661. (and the one used by Subversion) is checking out. When you checking out
  662. check out from the repository, you extract local copies of files
  663. into your working copy. Even if you do your work on the same
  664. computer that stores the repository, you’ll still need to check
  665. files out before using them; the repository should be treated
  666. as a black box. The checkout process ensures that you get
  667. up-to-date copies of the files you request and that these files
  668. are copied into a directory structure that mirrors that of the
  669. repository.
  670. W ORKING C OPIES AND M ANIPULATING F ILES 13
  671. Joe Asks...
  672. What about Generated Artifacts?
  673. If we store all the things needed to build the project,
  674. does that mean we should also be storing all the gen-
  675. erated files? For example, we might run JavaDoc to
  676. generate the API documentation for our source tree.
  677. Should that documentation be stored in the version
  678. control system’s repository?
  679. The simple answer is “no.” If a generated file can
  680. be reconstituted from other files, then storing it is sim-
  681. ply duplication. Why is this duplication bad? It isn’t
  682. because we’re worried about wasting disk space. It’s
  683. because we don’t want things to get out of step. If we
  684. store the source and the documentation, and then
  685. change the source, the documentation is now out-
  686. dated. If we forget to update it and check it back
  687. in, we’ve now got misleading documentation in our
  688. repository. So in this case, we’d want to keep a single
  689. source of the information, the source code. The same
  690. rules apply to most generated artifacts.
  691. Pragmatically, some artifacts are difficult to regener-
  692. ate. For example, you may have only a single license
  693. for a tool that generates a file needed by all the
  694. developers, or a particular artifact may take hours to
  695. create. In these cases, it makes sense to store the
  696. generated artifacts in the repository. The developer
  697. with the tool’s license can create the file, or a fast
  698. machine somewhere can create the expensive arti-
  699. fact. These can be checked in, and all other devel-
  700. opers can then work from these generated files.
  701. W ORKING C OPIES AND M ANIPULATING F ILES 14
  702. ?????
  703. ?
  704. ?
  705. ?
  706. ?
  707. ?
  708. ??
  709. ?
  710. ?
  711. ?
  712. ??
  713. ?
  714. ?? ?
  715. ??
  716. ! "
  717. #
  718. $
  719. ??
  720. ?
  721. ?
  722. ?
  723. ??
  724. ?
  725. ?? ?
  726. %
  727. &'
  728. %
  729. () *
  730. +
  731. ,
  732. *- . /
  733. +
  734. '
  735. %
  736. )
  737. 0
  738. 0
  739. 1
  740. +
  741. 2
  742. 34
  743. 2
  744. 567
  745. 8
  746. 9
  747. 7 : ;<
  748. 8
  749. 4
  750. =>
  751. ?
  752. ?
  753. @
  754. A
  755. B
  756. ?
  757. ?C
  758. ?
  759. ?
  760. D
  761. E F
  762. Figure 2.1: The Repository and Working Copies
  763. It’s also possible to export files from the repository, which is export
  764. slightly different from checking out. When you do an export,
  765. you won’t end up with a working copy; you’ll just get a snap-
  766. shot of files from the repository. This is useful in certain situ-
  767. ations such as packaging code for distribution.
  768. As you work on a project, you’ll make changes to the project’s
  769. code in your working copy. Every now and then you’ll reach
  770. a point where you’ll want to save your changes back to the
  771. repository. This process is called committing your changes committing
  772. back into the repository.
  773. Of course, all the time you’re making changes, so are other
  774. members of your team. Just like you, they’ll be committing
  775. their changes to the repository. However, these changes do
  776. not affect your local working copy; it doesn’t suddenly change
  777. just because someone else saved changes into the repository.
  778. Instead, you have to instruct the version control system to
  779. update your working copy. During the update, you’ll receive update
  780. the latest set of files from the repository. And when your col-
  781. leagues do an update, they’ll receive your latest changes too.
  782. (Just to confuse things, however, some folks also use the term
  783. check out to refer to updating, because they are checking out
  784. the latest changes. Because this is a common idiom, we’ll also
  785. use this at times in this book.) These various interactions are
  786. shown in Figure 2.1 .
  787. P ROJECTS , D IRECTORIES , AND F ILES 15
  788. Of course there’s a potential problem here: what happens if
  789. you and a colleague both want to make changes to the same
  790. source file at the same time? It depends on the version control
  791. system you’re using, but all have ways of dealing with the
  792. situation. We talk about this more in Section 2.9, Locking
  793. Options, on page 23.
  794. 2.4 Projects, Directories, and Files
  795. So far we’ve talked about storing things, but we haven’t talked
  796. about how those things are organized.
  797. At the lowest level, most version control systems deal with
  798. individual files. 1 Each file in your project is stored by name
  799. in the repository; if you add a file called Panel.java to the
  800. repository, then other members of your team can check out
  801. Panel.java into their own working copies.
  802. However, that’s pretty low-level. A typical project might have
  803. hundreds or thousands of files, and a typical company might
  804. have dozens of projects. Fortunately, almost all version con-
  805. trol systems allow you to structure the repository. At the top
  806. level, they typically divide your work into projects. Within
  807. each project, they let you work in terms of modules (and
  808. often submodules). For example, perhaps you are working
  809. on Orinoco, a large web-based book ordering application. All
  810. the files needed to build the application might be stored in the
  811. repository under the Orinoco project name. If you wanted to,
  812. you could check it all out onto your local disk.
  813. The Orinoco project itself might be broken down into a num-
  814. ber of largely independent modules. For example, there might
  815. be a team working on credit card processing and another
  816. working on order fulfillment. With any luck, the folks in
  817. the credit card subproject won’t need to have all the project’s
  818. source to do their job; their code should be nicely partitioned.
  819. So when they check out, they really want to see only the parts
  820. of the project that they’re working on.
  821. 1 Some IDE-like environments perform versioning at the method level, but
  822. they’re fairly uncommon.
  823. W HERE D O V ERSIONS C OME I N ? 16
  824. Subversion organizes the repository into directories. A project
  825. might correspond to a top-level directory, with modules and
  826. submodules arranged as directories within your project. This
  827. might be enough for simple projects, but for more complex
  828. code sharing Subversion supports the notion of externals. An externals
  829. externals definition allows you to include another Subversion
  830. repository location in any directory in your project.
  831. CVS Hint: Subversion’s directory-based organization corresponds,
  832. roughly speaking, to CVS modules, with externals corresponding to
  833. alias modules. Organizing stuff by directory turns out to be just as pow-
  834. erful and a lot easier for people to understand.
  835. Subversion’s “everything is a directory” approach is discussed
  836. in more depth in Chapter 8, Organizing Your Repository, on
  837. page 107.
  838. 2.5 Where Do Versions Come In?
  839. This book is all about version control systems, but so far all
  840. we’ve talked about is storing and retrieving files in a reposi-
  841. tory. Where do versions come in?
  842. Behind the scenes, a version control system’s repository is a
  843. fairly clever beast. It doesn’t just store the current copy of
  844. each of the files in its care. Instead it stores every version
  845. that has ever been checked in. If you check out a file, edit it,
  846. and then check it back in, the repository will hold both the
  847. original version and the version that contains your changes.
  848. In reality, most version control systems store the differences
  849. between versions of a file, rather than complete copies of each
  850. revision. Subversion stores the full text for the newest revision
  851. of a file, as well as cleverly picking historical revisions to store
  852. in full, so that it can retrieve any version of a file quickly.
  853. This helps minimize disk space requirements while keeping
  854. updates and checkouts fast.
  855. There are two common numbering schemes for version control
  856. systems: file-specific numbering and repository-wide number-
  857. ing. In a file-specific numbering scheme, the first revision of
  858. a file is named 1.1. When a change is checked in, the file is
  859. given the number 1.2, and so on. If you have version 1.2 of
  860. Node.cs and version 1.6 of Graph.cs , committing a change to
  861. W HERE D O V ERSIONS C OME I N ? 17
  862. Node.cs will make it revision 1.3. Graph.cs remains unchanged
  863. and at revision 1.6.
  864. In the repository-wide numbering scheme, the entire reposi-
  865. tory starts at revision 0, and checking in a change increases
  866. the repository revision number to 1, then 2, and so on. In
  867. this scheme, it’s more correct to talk about “ Panel.java at revi-
  868. sion 7” than to talk about “revision 7 of Panel.java .” Subver-
  869. sion uses this second numbering scheme, which turns out
  870. to be extremely useful for referring to changes once they’ve
  871. been committed. Section 9.5, Simple Bug Fixes, on page 121
  872. explains how to use revision numbers for merging bug fixes
  873. across branches.
  874. CVS Hint: CVS uses a file-specific numbering scheme, so people
  875. often look at the revision number of a file to try to gauge how much
  876. activity is occurring in the file or how much has changedover a period
  877. of time. Subversion’s repository-wide revision numbers make it impos-
  878. sible to do the same thing—you’ll have to use Subversion’s log com-
  879. mand to examine the history to look for changes.
  880. Subversion’s repository revision numbers act as a kind of
  881. marker pen, drawing a line through all the files in your repos-
  882. itory each time a commit is made. Figure 2.2 on the following
  883. page shows three files: Trains.java , Graph.java , and Node.java .
  884. First we commit a change to Graph.java (shown in the diagram
  885. as Graph.java ’s circle changing to a star), taking the reposi-
  886. tory to revision 2. If we then change Trains.java and Node.java ,
  887. we’ll bring the repository to revision 3. The key point is that
  888. Graph.java is at revision 3 as well, even though its content has
  889. not changed since revision 2.
  890. Subversion revision numbers aren’t much use for figuring out
  891. how much has changed in a particular file or group of files, 2
  892. so don’t try to use them for that purpose. People accustomed
  893. to the file-specific numbering scheme are often confused that
  894. the repository has jumped a bunch of revisions without their
  895. 2 Using version numbers, no matter how they’re assigned, to try to track
  896. “how much change is happening” is pretty futile—a single change could affect
  897. every line in a file. You’re probably better off looking at the changes directly,
  898. using your version control system’s history browsing features, if you want to
  899. find out how much has changed.
  900. T AGS 18
  901. G
  902. H
  903. IJK
  904. L
  905. M
  906. INI
  907. O
  908. H
  909. I
  910. P
  911. QR
  912. L
  913. M
  914. IN I
  915. ST UV
  916. L
  917. M
  918. IN I
  919. W
  920. XY
  921. Z
  922. [
  923. Z
  924. \]^
  925. W
  926. X Y
  927. Z
  928. [
  929. Z
  930. \]_
  931. W
  932. X Y
  933. Z
  934. [
  935. Z
  936. \]`
  937. aa a
  938. bbb
  939. cc c
  940. de
  941. f
  942. g
  943. h
  944. i jkk
  945. f
  946. g
  947. d e
  948. f
  949. g
  950. h
  951. ij kk
  952. f
  953. g
  954. Figure 2.2: Revision Numbers in the Repository
  955. checking in anything. This makes sense when you realize the
  956. number applies to everyone’s checkins, not just your own.
  957. This system of storing revisions is remarkably powerful. Using
  958. it, the version control system can do things such as
  959. • Retrieve a specific revision of a file.
  960. • Check out all of the source code of a system exactly as it
  961. appeared two months ago.
  962. • Tell you what changed in a particular file between revi-
  963. sions 7 and 9.
  964. You can also use the revision system to undo mistakes. If
  965. you get to the end of the week and discover you’ve been going
  966. down a blind alley, you can back out all the changes you’ve
  967. made, reverting to the code as it was on Monday morning.
  968. 2.6 Tags
  969. All these revision numbers are great, but as people we seem to
  970. be better at remembering names such as PreRelease2 rather
  971. than numbers such as r347.
  972. Tags to the rescue. Version control systems let you assign Tags
  973. names to a group of files (or directories or an entire project) at
  974. a particular point in time. If you assigned the tag PreRelease2
  975. to our group of three files, you could subsequently check them
  976. out using that same tag.
  977. B RANCHES 19
  978. lm no
  979. p
  980. qrs tt
  981. u
  982. p
  983. lmn o
  984. p
  985. qrst t
  986. u
  987. p
  988. v
  989. w
  990. x yz
  991. v
  992. {
  993. |}
  994. Figure 2.3: A Simple Trunk
  995. Tags are a great way of keeping track of significant events in
  996. the life of your project’s code. We’ll be using tags extensively
  997. later in this book. You can read about tags and branches
  998. (the topic of the next section) in Chapter 9, Using Tags and
  999. Branches, on page 111.
  1000. 2.7 Branches
  1001. In the normal course of development, most folks are working
  1002. on a common code base (although they’ll likely be working on
  1003. different parts of it). Developers will be checking out code,
  1004. making changes in their working copies, then checking the
  1005. changes back in, and everyone will share this work. This
  1006. main body of code is called the trunk. We show this in Fig- trunk
  1007. ure 2.3 . In this figure (and in the ones that follow) time flows
  1008. from left to right. The thicker horizontal line represents the
  1009. progression of code through time; it is the main line of the
  1010. development. Individual developers check in and check out
  1011. code from the trunk into their individual working copies.
  1012. But consider the time when a new release is about to be
  1013. shipped. One small subteam of developers may be preparing
  1014. the software for that release, fixing last-minute bugs, working
  1015. with the release engineers, and helping the QA team. During
  1016. this vital period, they need stability; it would set back their
  1017. efforts if other developers were also editing the code, adding
  1018. features intended for the next release.
  1019. B RANCHES 20
  1020. One option is to freeze new development while the release is
  1021. being generated, but this means the rest of the team is effec-
  1022. tively sitting idle.
  1023. Another option would be to copy the source software out onto
  1024. a spare machine and then have the release team just use this
  1025. machine. But if we do that, what happens to the changes they
  1026. make after the copy? How do we keep track of them? If they
  1027. find bugs in the release code that are also in the trunk, how
  1028. can we efficiently and reliably merge these fixes back in? And
  1029. once they’ve released the software, how do we fix bugs that
  1030. customers report; how can we guarantee to find the source
  1031. code in the same state as when we shipped the release?
  1032. A far better option is to use the branching capabilities built branching
  1033. into version control systems.
  1034. Branching is a bit like the hackneyed device in science fic-
  1035. tion stories where some event causes time to split. From that
  1036. point forward there are two parallel futures. Some other event
  1037. occurs, and one of these futures splits too. Soon you’re deal-
  1038. ing with a whole bunch of alternative universes (a great device
  1039. for resolving the story when you run out of plot ideas).
  1040. Branching in a version control system also allows you to cre-
  1041. ate multiple parallel futures, but rather than being populated
  1042. by aliens and space cowboys, they contain source code and
  1043. version information.
  1044. Take the case of the team about to release a new version of
  1045. the product. So far, the entire team has been working in the
  1046. trunk, the common thread of code shown in Figure 2.3 on
  1047. the page before. But the release subteam wants to isolate
  1048. themselves from the trunk. To do this, they create a branch in
  1049. the repository. From now until their work is done, the release
  1050. subteam will check out from and check into this branch. Even
  1051. after the application is released, this branch will stay active;
  1052. if customers report bugs, the team will fix them in this release
  1053. branch. This is shown in Figure 2.4 on the following page.
  1054. A branch is almost like having a totally separate repository:
  1055. people using that branch see the source code it contains and
  1056. operate independently of people working on other branches
  1057. or the trunk. Each branch has its own history and tracks
  1058. changes independently of the trunk (although obviously if you
  1059. B RANCHES 21
  1060. ~
  1061. 
  1062. €
  1063. ‚
  1064. €
  1065. 
  1066. €
  1067. ƒ
  1068. €  „ €
  1069. 
  1070. † ‡ˆ
  1071. ‰
  1072. 
  1073. €Š 
  1074. 
  1075. €
  1076. ‹
  1077. Œ
  1078. 
  1079. 
  1080. €
  1081. ƒ
  1082. €  „ €
  1083. €
  1084. ƒ
  1085. €  „€Ž 
  1086. ‹
  1087. ‘
  1088. ’€„
  1089. ~Π
  1090. ‚
  1091. ‘
  1092. †
  1093. 
  1094. €
  1095. Π
  1096. 
  1097. Œ
  1098. ‘
  1099. †
  1100. 
  1101. “ € ”€
  1102. ƒ
  1103. ŒŠ • €†
  1104. ‚
  1105. –
  1106. 
  1107. 
  1108. †—
  1109. Ž
  1110. 
  1111. †‡ ˆ
  1112. Figure 2.4: Trunk with a Release Branch
  1113. look back past the point where the branch was made you’ll see
  1114. that the branch and the trunk become one).
  1115. This is exactly what you want when you’re creating releases.
  1116. The team working on the release will have a stable code base
  1117. to polish and ship. In the meantime, the main group of devel-
  1118. opers can continue making changes to the main line of code;
  1119. there’s no need for a code freeze while the release takes place.
  1120. And when customers report problems in the release, the team
  1121. will have access to the code in the release branch so they can
  1122. fix the bugs and ship updated releases without including any
  1123. of the newly developed code from the trunk.
  1124. Branches are stored as named directories within Subversion;
  1125. you create a branch simply by copying the trunk to a new
  1126. location. Subversion’s internals use lazy copies to make this lazy copies
  1127. copying process efficient, and these lazy copies are the basis
  1128. of Subversion’s tagging support too. Whenever you copy a file
  1129. or directory, Subversion simply stores a link to the original.
  1130. When you make a change to the copy, Subversion records
  1131. those changes as differences against the original. Using lazy
  1132. copies Subversion can very quickly copy large trees of files
  1133. using almost zero space, ideal for branches and tags.
  1134. You can create branches off other branches, but typically you
  1135. won’t want to; we’ve come across many developers who have
  1136. been put off branching for life because of some bad experi-
  1137. ences with overly complicated branching in a project.
  1138. M ERGING 22
  1139. You should avoid excessive branching. Even though branches
  1140. might seem like a cheap way to hedge your bets during devel-
  1141. opment, they have significant costs when you need to merge
  1142. changes between branches. Not only do you need to merge dif-
  1143. ferent lines of development, you have to make sure you don’t
  1144. lose any changes in the process. Bear in mind that the need to
  1145. create multiple branches, especially for parallel lines of devel-
  1146. opment rather than releases, may be a sign that something is
  1147. going wrong.
  1148. In this book we’ll describe a simple scheme that does every-
  1149. thing you’ll need but that avoids unnecessary complexity.
  1150. 2.8 Merging
  1151. Back to the science fiction story with the multiple alternate
  1152. futures. In order to spice up the plot, writers often allow their
  1153. characters to travel between these different universes using
  1154. wormholes, polyphase deconfabulating oscillotrons, or just a
  1155. good strong cup of piping-hot tea.
  1156. You can also travel between alternate futures in a version
  1157. control system (the cup of tea is optional). Although each
  1158. checked-out version comes from a particular branch and gets
  1159. checked back into that same branch, it’s easy to have multi-
  1160. ple branches checked out on a single developer’s machine (in
  1161. different directories or folders on the hard drive, of course).
  1162. That way a developer can be working on both the trunk and
  1163. on (say) bug fixes in a release branch at the same time.
  1164. Even better, version control systems support merging. Say merging
  1165. you fix a bug in the release branch and realize that the same
  1166. bug will be present in the trunk code. You can tell the ver-
  1167. sion control system to work out the changes you made on the
  1168. release branch to fix the bug and then to apply those changes
  1169. to the code in the trunk. You can even merge them into differ-
  1170. ent release branches. This largely eliminates the need to cut
  1171. and paste changes back and forth between different versions
  1172. of a system. We’ll have a lot to say about merging later.
  1173. L OCKING O PTIONS 23
  1174. 2.9 Locking Options
  1175. Imagine two developers, Fred and Wilma, working on the same
  1176. project. Each has checked out the project’s files onto their
  1177. respective local hard drives, and each wants to edit their local
  1178. copy of File1.java . What happens when they come to check that
  1179. file in?
  1180. A bad scenario would be for the version control system to
  1181. accept Fred’s changes and then accept Wilma’s version of the
  1182. same file. As Wilma’s copy won’t have Fred’s changes in it,
  1183. storing Wilma’s copy in the repository will effectively forget all
  1184. Fred’s hard work.
  1185. To prevent this from happening, version control systems must
  1186. implement some form of conflict resolution system (probably
  1187. a good thing in the case of Fred and Wilma). There are two
  1188. common versions of conflict resolution.
  1189. The first is called strict locking. In a strict locking version con- strict locking
  1190. trol system, all files that are checked out are initially flagged
  1191. as being “read-only.” You can look at them, and you can use
  1192. them to build your application, but you can’t edit or change
  1193. them. To do that, you have to ask the repository’s permission:
  1194. “please can I edit File1.java ?” If no one else is editing that same
  1195. file, then the repository gives you permission and changes the
  1196. permissions of your local copy of the file to be “read/write.”
  1197. You can then edit. If anyone else asks to edit that same file
  1198. while you have it flagged, they’ll be refused. After you’ve fin-
  1199. ished your changes and checked the file in, your local copy
  1200. reverts to being read only, and it becomes available for other
  1201. folks to edit.
  1202. The second form of conflict resolution is often called opti-
  1203. mistic locking, although it really is not locking at all. Here, optimistic locking
  1204. every developer gets to edit any checked-out file: the files are
  1205. checked out in a read/write state. However, the repository will
  1206. not allow you to check in a file that has been updated in the
  1207. repository since you last checked it out. Instead, it asks you
  1208. to update your local copy of the file to include the latest repos-
  1209. itory changes before checking in. This is where the cleverness
  1210. lies. Instead of simply overwriting all your hard work with the
  1211. latest repository version of the file, the version control system
  1212. attempts to merge the repository changes with your changes.
  1213. L OCKING O PTIONS 24
  1214. For example, let’s look at File1.java :
  1215. Line 1
  1216. public class File1 {
  1217. -
  1218. public String getName() {
  1219. -
  1220. return "Wibble";
  1221. - }
  1222. 5
  1223. public int getSize() {
  1224. -
  1225. return 42;
  1226. - }
  1227. - }
  1228. Wilma and Fred both check this file out. Fred changes line 3:
  1229. return "WIBBLE";
  1230. He then checks the file in. This means that Wilma’s copy of
  1231. the file is out-of-date. Not knowing this, Wilma changes line
  1232. 6, so it returns 99 instead of 42. When she goes to check the
  1233. file in, she’s told that her copy is out-of-date; she needs to
  1234. merge in the repository changes. This corresponds to the star
  1235. marked OUT OF SYNC in Figure 2.5 on the next page.
  1236. When Wilma merges the changes into her file, the version con-
  1237. trol system is clever enough to spot that Fred’s changes do not
  1238. overlap hers, so it simply updates her local copy with a new
  1239. line 3, leaving her changes still in her file. When she checks
  1240. in, she’ll be storing her changes and leaving Fred’s intact.
  1241. What happens if Fred and Wilma both updated line 3 but
  1242. made different changes to it? Assuming Fred checks in first,
  1243. his changes will be accepted. When Wilma goes to check in,
  1244. she’ll again be told that her copy is out-of-date. This time,
  1245. though, when she goes to merge in the repository version the
  1246. system will notice that she’s made a change to a line that has
  1247. also been changed in the repository. There’s a conflict. In this
  1248. case, Wilma will see some warning messages, and the conflict
  1249. will be marked up in her copy of the source file. She’ll have to
  1250. resolve it manually (probably by talking with Fred to find out
  1251. why they were both working on the same line of code).
  1252. Given this description, you might think that optimistic locking
  1253. is a somewhat reckless way of developing systems: multiple
  1254. people editing the same files at the same time. Often peo-
  1255. ple who haven’t tried it reason that it can’t work and insist
  1256. on working only with version control systems that implement
  1257. strict locking.
  1258. L OCKING O PTIONS 25
  1259. ˜™ š
  1260. ›
  1261. œ
  1262.  
  1263. ›
  1264. ž ŸŸ
  1265. œ
  1266. ›
  1267. ¡¢
  1268. £
  1269. ˜™ š
  1270. ›
  1271. œ
  1272. ¤
  1273. ¥
  1274. ¦
  1275. œ
  1276. §¨¨¡
  1277. ¥
  1278. © žª¡
  1279. «
  1280. ¬
  1281. £
  1282. ¦
  1283. ¡
  1284. ¥
  1285. ™
  1286. ¦
  1287. §
  1288. ­
  1289. ®
  1290. œ
  1291. š š
  1292. ›
  1293. ¡
  1294. ­
  1295. ¯
  1296. °
  1297. ˜™ š
  1298. ›
  1299. œ
  1300. 
  1301. œ
  1302. §
  1303. ¥
  1304. ¨¡
  1305. ¥
  1306. ¤
  1307. œ
  1308. ±¡
  1309. «
  1310. ¬
  1311. £
  1312. ¦
  1313. ¡
  1314. ¥
  1315. ™
  1316. ¦
  1317. § ²³
  1318. ¯
  1319. °
  1320. °
  1321. ˜ ™š
  1322. ›
  1323. œ
  1324.  
  1325. ›
  1326. ž ŸŸ
  1327. œ
  1328. ›
  1329. ¡ ¢
  1330. £
  1331. ˜™š
  1332. ›
  1333. œ
  1334. ¤
  1335. ¥
  1336. ¦
  1337. œ
  1338. §¨¨¡
  1339. ¥
  1340. © žª¡
  1341. «
  1342. ¬
  1343. £
  1344. ¦
  1345. ¡
  1346. ¥
  1347. ™
  1348. ¦
  1349. §
  1350. ­
  1351. ®
  1352. œ
  1353. šš
  1354. ›
  1355. ¡
  1356. ­
  1357. ¯
  1358. °
  1359. ˜™š
  1360. ›
  1361. œ
  1362. 
  1363. œ
  1364. §
  1365. ¥
  1366. ¨¡
  1367. ¥
  1368. ¤
  1369. œ
  1370. ±¡
  1371. «
  1372. ¬
  1373. £
  1374. ¦
  1375. ¡
  1376. ¥
  1377. ™
  1378. ¦
  1379. §²³
  1380. ¯
  1381. °
  1382. °
  1383. ˜™š
  1384. ›
  1385. œ
  1386. 
  1387. ›
  1388. žŸŸ
  1389. œ
  1390. ›
  1391. ¡¢
  1392. £
  1393. ˜™ š
  1394. ›
  1395. œ
  1396. ¤
  1397. ¥
  1398. ¦
  1399. œ
  1400. § ¨ ¨¡
  1401. ¥
  1402. ©žª¡
  1403. «
  1404. ¬
  1405. £
  1406. ¦
  1407. ¡
  1408. ¥
  1409. ™
  1410. ¦
  1411. §
  1412. ­
  1413. ®
  1414. œ
  1415. šš
  1416. ›
  1417. ¡
  1418. ­
  1419. ¯
  1420. °
  1421. ˜™ š
  1422. ›
  1423. œ
  1424. 
  1425. œ
  1426. §
  1427. ¥
  1428. ¨ ¡
  1429. ¥
  1430. ¤
  1431. œ
  1432. ±¡
  1433. «
  1434. ¬
  1435. £
  1436. ¦
  1437. ¡
  1438. ¥
  1439. ™
  1440. ¦
  1441. §² ³
  1442. ¯
  1443. °
  1444. °
  1445. ´
  1446. ´
  1447. ´
  1448. ˜™ š
  1449. ›
  1450. œ
  1451. ¤
  1452. ¥
  1453. ¦
  1454. œ
  1455. § ¨ ¨¡
  1456. ¥
  1457. ©žª¡
  1458. «
  1459. ¬
  1460. £
  1461. ¦
  1462. ¡
  1463. ¥
  1464. ™
  1465. ¦
  1466. §
  1467. ­
  1468. ®
  1469. µ
  1470. ¶ ¶· ¸
  1471. ­
  1472. ¯
  1473. ´
  1474. ´
  1475. ´
  1476. ´
  1477. ´
  1478. ˜™š
  1479. ›
  1480. œ
  1481. 
  1482. œ
  1483. §
  1484. ¥
  1485. ¨ ¡
  1486. ¥
  1487. ¤
  1488. œ
  1489. ± ¡
  1490. «
  1491. ¬
  1492. £
  1493. ¦
  1494. ¡
  1495. ¥
  1496. ™
  1497. ¦
  1498. §¹¹
  1499. ¯
  1500. ´
  1501. ´
  1502. ´
  1503. ˜™ š
  1504. ›
  1505. œ
  1506.  
  1507. ›
  1508. ž ŸŸ
  1509. œ
  1510. ›
  1511. ¡¢
  1512. £
  1513. ˜™ š
  1514. ›
  1515. œ
  1516. ¤
  1517. ¥
  1518. ¦
  1519. œ
  1520. §¨¨¡
  1521. ¥
  1522. © žª¡
  1523. «
  1524. ¬
  1525. £
  1526. ¦
  1527. ¡
  1528. ¥
  1529. ™
  1530. ¦
  1531. §
  1532. ­
  1533. ®
  1534. µ
  1535. ¶¶·¸
  1536. ­
  1537. ¯
  1538. °
  1539. ˜™ š
  1540. ›
  1541. œ
  1542. 
  1543. œ
  1544. §
  1545. ¥
  1546. ¨¡
  1547. ¥
  1548. ¤
  1549. œ
  1550. ±¡
  1551. «
  1552. ¬
  1553. £
  1554. ¦
  1555. ¡
  1556. ¥
  1557. ™
  1558. ¦
  1559. § ²³
  1560. ¯
  1561. °
  1562. °
  1563. ˜ ™š
  1564. ›
  1565. œ
  1566.  
  1567. ›
  1568. ž ŸŸ
  1569. œ
  1570. ›
  1571. ¡ ¢
  1572. £
  1573. ˜™š
  1574. ›
  1575. œ
  1576. ¤
  1577. ¥
  1578. ¦
  1579. œ
  1580. §¨¨¡
  1581. ¥
  1582. © žª¡
  1583. «
  1584. ¬
  1585. £
  1586. ¦
  1587. ¡
  1588. ¥
  1589. ™
  1590. ¦
  1591. §
  1592. ­
  1593. ®
  1594. µ
  1595. ¶ ¶ ·¸
  1596. ­
  1597. ¯
  1598. °
  1599. ˜™š
  1600. ›
  1601. œ
  1602. 
  1603. œ
  1604. §
  1605. ¥
  1606. ¨¡
  1607. ¥
  1608. ¤
  1609. œ
  1610. ±¡
  1611. «
  1612. ¬
  1613. £
  1614. ¦
  1615. ¡
  1616. ¥
  1617. ™
  1618. ¦
  1619. §¹¹
  1620. ¯
  1621. °
  1622. °
  1623. ˜ ™š
  1624. ›
  1625. œ
  1626. 
  1627. ›
  1628. žŸŸ
  1629. œ
  1630. ›
  1631. ¡ ¢
  1632. £
  1633. ˜ ™š
  1634. ›
  1635. œ
  1636. ¤
  1637. ¥
  1638. ¦
  1639. œ
  1640. § ¨¨ ¡
  1641. ¥
  1642. ©ž ª ¡
  1643. «
  1644. ¬
  1645. £
  1646. ¦
  1647. ¡
  1648. ¥
  1649. ™
  1650. ¦
  1651. §
  1652. ­
  1653. ®
  1654. µ
  1655. ¶¶ · ¸
  1656. ­
  1657. ¯
  1658. °
  1659. ˜ ™š
  1660. ›
  1661. œ
  1662. 
  1663. œ
  1664. §
  1665. ¥
  1666. ¨¡
  1667. ¥
  1668. ¤
  1669. œ
  1670. ± ¡
  1671. «
  1672. ¬
  1673. £
  1674. ¦
  1675. ¡
  1676. ¥
  1677. ™
  1678. ¦
  1679. §¹ ¹
  1680. ¯
  1681. °
  1682. °
  1683. º
  1684. »
  1685. ¼½¾¼ ¿ÀÁ
  1686. Â
  1687. Ã
  1688. À
  1689. »
  1690. Ä Å
  1691. Â
  1692. Æ
  1693. ÇÈ
  1694. É
  1695. Ê Ë
  1696. É
  1697. Ì ÍÎ
  1698. Ï
  1699. ÐÑÒ
  1700. ÐÓÔ Õ
  1701. Ö
  1702. ×ØÙ
  1703. Ù
  1704. Ú
  1705. Û
  1706. ÜÝ
  1707. Þ
  1708. ß
  1709. Ü Ý
  1710. Þ
  1711. ß
  1712. à áâ
  1713. â
  1714. ã
  1715. ä
  1716. å æ çå è
  1717. éêëìíî
  1718. Ý ï
  1719. ß
  1720. Üð
  1721. ñ Ü
  1722. ò
  1723. óÜ
  1724. ô õö
  1725. ö
  1726. ÷
  1727. ø
  1728. Figure 2.5: Fred and Wilma make changes to the same file,
  1729. but the conflict is handled by a merge.
  1730. C ONFIGURATION M ANAGEMENT (CM) 26
  1731. In reality, though, strict locking turns out to be a lot of extra
  1732. hassle with no particular payback. If you try an optimistic
  1733. locking system (such as Subversion), you’ll be surprised at
  1734. just how rarely conflicts arise. It turns out that in practice
  1735. the normal ways of dividing work on a team mean that peo-
  1736. ple work on different areas of the code; they don’t bump into
  1737. each other that often. And when they do need to edit the same
  1738. file, they’re often working on different parts of it. In a strict
  1739. locking system, one would have to wait for the other to finish
  1740. and check in before proceeding. In an optimistic locking sys-
  1741. tem, both can proceed. We’ve tried both kinds of locking over
  1742. the years, and our strong recommendation is that the vast
  1743. majority of teams should use a version control system with
  1744. optimistic locking.
  1745. Subversion 1.2 introduced optional file locking, discussed in
  1746. Chapter 7, File Locking and Binary Files, on page 99. Using a
  1747. simple file property you can ask Subversion to enforce strict
  1748. locking on individual files, such as sound, graphics, or other
  1749. unmergeable files.
  1750. 2.10 Configuration Management (CM)
  1751. Sometimes you’ll hear folks talking about Configuration Man-
  1752. agement or Software Configuration Management systems (or
  1753. flinging about the abbreviations CM or SCM). At first sight
  1754. they seem to be talking about version control. And that’s
  1755. largely true; the practices of CM rely very heavily on having
  1756. good version control in place. But version control is just one
  1757. tool used by configuration management.
  1758. CM is a set of project management practices that enables you
  1759. to accurately and reproducibly deliver software. It uses ver-
  1760. sion control to achieve its technical goals but also uses a lot
  1761. of human controls and cross-checks to make sure things are
  1762. not forgotten. You can think of configuration management as
  1763. a way of identifying the things that get delivered and version
  1764. control as a means of recording that identification. CM is a
  1765. large topic, and we won’t be covering it more in this book. If
  1766. you’re interested in CM, Software Configuration Management
  1767. Patterns [BA03] is an excellent resource, and goes into greater
  1768. detail on many of the issues we don’t have room to cover here.
  1769. C ONFIGURATION M ANAGEMENT (CM) 27
  1770. Many of the techniques and recipes in this book correspond
  1771. to an SCM Pattern, which we’ll mention by name.
  1772. For now, though, let’s concentrate on how we can use version
  1773. control systems to get our jobs done. The next chapter is a
  1774. gentle introduction to one particular version control system,
  1775. Subversion.
  1776. Chapter 3
  1777. Getting Started with
  1778. Subversion
  1779. The best way to get familiar with a new software tool is to try
  1780. it, so this chapter will show you how to create and work with
  1781. a live Subversion repository. You’ll be learning the basic steps
  1782. in using Subversion whilst maintaining a trivial project.
  1783. Since Subversion is reasonably recent software, you will prob-
  1784. ably need to install it on your computer. Basic installation,
  1785. which we’ll cover in this chapter, is pretty simple. For more
  1786. advanced installation, networking, security, and administra-
  1787. tion instructions, see Appendix A on page 151.
  1788. Subversion ships with a command-line client, but there are
  1789. a variety of third-party tools for interacting with your repos-
  1790. itory. TortoiseSVN integrates with the Windows Explorer, for
  1791. example, and some IDEs now include Subversion support.
  1792. 3.1 Installing Subversion
  1793. Obviously you need to have Subversion installed before you
  1794. can use it. Depending on how Subversion is packaged for your
  1795. operating system, you might get the option to install the client
  1796. and server components separately. This is more common for
  1797. Unix platforms where an adminstrator might want to set up a
  1798. server without installing client tools.
  1799. I NSTALLING S UBVERSION 29
  1800. Joe Asks...
  1801. Shells, Prompts, Command Windows?
  1802. Terminology can get confusing when you’re dealing
  1803. with command lines, so let’s clear things up a bit.
  1804. A command processor, also called a shell, is a pro-
  1805. gram that accepts a command and executes it. The
  1806. command can have parameters, and the command
  1807. processor often has additional capabilities (such as
  1808. redirecting the application’s output to a file). Under
  1809. Windows, cmd and command are common com-
  1810. mand processors (which you use depends on which
  1811. version of Windows you use). On Unix boxes, there’s
  1812. a great choice of shells, from the original sh , through
  1813. csh , bash , tcsh , zsh , and so on.
  1814. Back before we had GUI systems, the command
  1815. processor or shell was how you interacted with your
  1816. computer. When you booted up DOS, you got the
  1817. DOS prompt, and you were talking with the command
  1818. application; your computer monitor was effectively a
  1819. dumb terminal.
  1820. Now that we have fancy front ends, we need a place
  1821. to run these command processors, so folks have writ-
  1822. ten terminal applications that run in windows. When
  1823. one of these terminal applications is running a com-
  1824. mand processor or a shell, you can type in commands
  1825. at the prompt and have them execute. Sometimes
  1826. we’ll call these windows executing a command pro-
  1827. cessor a command window.
  1828. I NSTALLING S UBVERSION 30
  1829. Figure 3.1: Windows Command Prompt
  1830. Our first step is to check if Subversion is already installed on
  1831. your computer. The easiest way to do this is with the com-
  1832. mand line. If you’re familiar with the command line, you can
  1833. skip the next section.
  1834. The Command Line
  1835. The command line is a low-level facility that lets you run com-
  1836. mands directly on your computer. The command line is a
  1837. powerful tool, but it can also be fairly cryptic: you’re working
  1838. down in the engine room when you’re issuing commands.
  1839. On Windows boxes, you can get to a command-line window by
  1840. using Start > Run and typing cmd as the name of the program
  1841. to run (on some older Windows versions you may have to type
  1842. command instead). You should see a window that looks like
  1843. Figure 3.1 .
  1844. On Unix boxes, you may be working at the command line
  1845. already. If instead you use a desktop environment such as
  1846. Gnome or KDE, look for the terminal , konsole , or xterm appli-
  1847. cation and run it. You should see a window like that in Fig-
  1848. ure 3.2 on the next page. If you’re using Mac OS X, your shell
  1849. application is hidden in /Applications/Utilities/Terminal .
  1850. You use the command-line window to enter commands and
  1851. view their output; no GUI front ends here. For example, in the
  1852. I NSTALLING S UBVERSION 31
  1853. Figure 3.2: Unix Shell Prompt
  1854. command-line window you just created, enter the following
  1855. command and hit the Enter key (sometimes labeled Return):
  1856. echo Hello
  1857. You should see the text “Hello” echoed back at you, and just
  1858. below it a new prompt where you can enter another command.
  1859. An example is shown in Figure 3.3 on the following page.
  1860. Prompts
  1861. One of the joys of the command window is that you can cus-
  1862. tomize the prompt that the shell uses to tell you it’s ready for
  1863. input. You can include the time, the current directory, your
  1864. username, and all sorts of other essential information in the
  1865. prompt. Unfortunately, this flexibility can also lead to confu-
  1866. sion: looking at the previous screenshots you can see that the
  1867. Windows prompt looks different from the Unix prompt.
  1868. In this book, we’ll try to simplify things by standardizing on
  1869. a generic prompt in our examples. We’ll show the name of
  1870. the current directory followed by a greater-than sign (>). For
  1871. example, we might give an example of a command as follows:
  1872. work > svn update
  1873. I NSTALLING S UBVERSION 32
  1874. Figure 3.3: After echoing “hello”
  1875. This means we’re in a directory called work and we issued the
  1876. command svn update . It should be simple to map this “logi-
  1877. cal” prompt to the prompt you actually see in your operating
  1878. system’s command window.
  1879. The commands in this book are generally not Windows or Unix
  1880. specific: they should work on both systems. The only differ-
  1881. ences are in the names of files; Windows uses drive letters
  1882. and backward slashes between the components of filenames,
  1883. and Unix uses forward slashes. Use appropriate filenames
  1884. for your environment, and things should work out fine. An
  1885. exception to this rule is when dealing with file:// -based
  1886. repositories—the Windows and Unix syntax is quite a bit dif-
  1887. ferent. When this is the case, we’ll include both Windows and
  1888. Unix versions of each command.
  1889. Checking If Subversion Is Installed
  1890. Bring up a command window on your computer, and type
  1891. the command svn --version , followed by the Return key. If the
  1892. Subversion client is installed correctly, you will see a response
  1893. similar to that shown in Figure 3.4 on the next page. Next try
  1894. C REATING A R EPOSITORY 33
  1895. Figure 3.4: Subversion Client Installed Correctly
  1896. svnadmin --version to see if the Subversion administration tools
  1897. are installed. If both of these commands worked, you can skip
  1898. ahead to the next section.
  1899. Most likely your computer complained that it couldn’t find svn
  1900. or svnadmin .That’s okay—Subversion is not yet a standard
  1901. part of most operating system installs, so it was a long shot
  1902. anyhow. Subversion is distributed both as source code and
  1903. as binary packages for different operating systems. Complete
  1904. instructions for your operating system should be available
  1905. from the package download page at http://subversion.
  1906. tigris.org/project packages.html . You can also down-
  1907. load the source code if you want to compile Subversion your-
  1908. self, but since Subversion relies on a number of other pack-
  1909. ages, it may be easiest to download a precompiled version.
  1910. 3.2 Creating a Repository
  1911. Subversion requires a repository to store your data. In this
  1912. section you’ll create a repository for storing your first project.
  1913. C REATING A S IMPLE P ROJECT 34
  1914. Subversion Versions
  1915. The Subversion developers are busy people, and
  1916. since the original publication of this book have
  1917. released Subversion 1.2 and 1.3. Most of the exam-
  1918. ples in the book will work with any version of Subver-
  1919. sion, but the file locking features require Subversion
  1920. 1.2 (or better) and the more advanced authentica-
  1921. tion features require Subversion 1.3 (or better).
  1922. Whena feature requires a particularversion of Subver-
  1923. sion we’ll include a note to remind you. We generally
  1924. recommend using the most recent release of Subver-
  1925. sion if you can, because it will be the most stable and
  1926. best supported.
  1927. First you need to create an empty directory for the repository
  1928. and then tell Subversion to create a new repository in the
  1929. directory. Let’s suppose you’re using /home/mike/svn-repos (for
  1930. Unix) or c:\svn-repos (for Windows).
  1931. Windows:
  1932. mkdir c: \ svn-repos
  1933. svnadmin create c: \ svn-repos
  1934. Unix:
  1935. mkdir /home/mike/svn-repos
  1936. svnadmin create /home/mike/svn-repos
  1937. Once the svnadmin command completes, you’ll end up with
  1938. a set of files in your repository directory. We’ll go into more
  1939. detail later on how the repository is stored on disk, but for now
  1940. you can safely treat the repository directory and its contents
  1941. as a black box.
  1942. Your Subversion repository is now set up—next we’ll start cre-
  1943. ating a project.
  1944. 3.3 Creating a Simple Project
  1945. Let’s populate your repository with a new project. In the spirit
  1946. of pioneering Internet startups, we’ll use a cryptic yet cool-
  1947. sounding project name—Sesame. We’ll start by creating a
  1948. C REATING A S IMPLE P ROJECT 35
  1949. Using Remote Filesystems
  1950. If you’re using a remote filesystem, such as a Windows
  1951. home directory on a network share or your Unix home
  1952. directory mounted over NFS, the Subversion client will
  1953. work great. You can check out a working copy to any
  1954. kind of networked drive with no problems.
  1955. If you’re running the Subversion server, however, you
  1956. need to be a little more careful. Subversion 1.0
  1957. shipped with Berkeley DB as the backend in which the
  1958. repository is stored. BDB doesn’t like using database
  1959. files on a network drive because of the way it maps
  1960. them into memory.
  1961. Subversion 1.1 introduced the “fsfs” filesystem–based
  1962. backend, which became the default in Subversion
  1963. 1.2. If you’re using Subversion 1.2 or 1.3, repositories
  1964. created using svnadmin create will work just fine on a
  1965. remote filesystem.
  1966. If you want to use the BDB backend instead of fsfs,
  1967. add the --fs-type bdb option when creating your
  1968. repository. When using BDB you must store your repos-
  1969. itory on a local drive.
  1970. couple of files and then import them into a sesame directory
  1971. in the repository. (The project name is officially Sesame, but
  1972. we’ll use the lowercase sesame in our repository.)
  1973. Create a temporary directory on your computer called tmpdir .
  1974. Inside that directory, use your favorite text editor to create
  1975. two files: Day.txt and Number.txt .
  1976. File Day.txt :
  1977. monday
  1978. tuesday
  1979. wednesday
  1980. thursday
  1981. friday
  1982. File Number.txt :
  1983. zero
  1984. one
  1985. two
  1986. three
  1987. four
  1988. C REATING A S IMPLE P ROJECT 36
  1989. These don’t look much like source programs, but remember
  1990. that we’re using our repository to store all the stuff we need
  1991. to build our project. It looks like Sesame needs to know the
  1992. names of the days of the week and a few small numbers, and
  1993. these are the data files that help it do this.
  1994. We now need to tell Subversion to import these files into a new
  1995. project in the repository. Subversion organizes everything in
  1996. the repository by directory, which we’ll explain in more detail
  1997. in Chapter 8, Organizing Your Repository, on page 107. For
  1998. now, we’ll use the convention recommended by the Subver-
  1999. sion developers and store our Sesame project in /sesame/trunk .
  2000. In your command prompt, change to the tmpdir directory. If
  2001. you’re on Windows, run
  2002. tmpdir > svn import -m "importing Sesame project" \
  2003. . file:///c:/svn-repos/sesame/trunk
  2004. Adding Number.txt
  2005. Adding Day.txt
  2006. Committed revision 1.
  2007. Don’t type the backward slash after the log message. We ran
  2008. out of space and couldn’t fit the whole command on one line,
  2009. so we used \ to separate it over several lines. You’ll see this
  2010. used quite often throughout the book.
  2011. If instead you’re on Unix, run
  2012. tmpdir > svn import -m "importing Sesame project" \
  2013. . file:///home/mike/svn-repos/sesame/trunk
  2014. Adding Number.txt
  2015. Adding Day.txt
  2016. Committed revision 1.
  2017. The import keyword tells Subversion we want to import some
  2018. files to our repository. The -m option allows you to associate a
  2019. message with this import. It’s a good idea to use a log message
  2020. indicating what kind of import you’ve performed.
  2021. The next parameter ( . ) tells Subversion to import the contents
  2022. of the current directory, tmpdir , into the repository. The final
  2023. parameter is a repository URL describing where we want to
  2024. import the files. Here we’re telling Subversion to look on the
  2025. local filesystem for the repository in our svn-repos directory
  2026. and to import into /sesame/trunk inside it. 1
  2027. 1 We’re importing to /sesame/trunk because in the future the Sesame project
  2028. S TARTING TO W ORK WITH A P ROJECT 37
  2029. Repository URLs
  2030. You may have noticed that when we imported our
  2031. files into the repository, we used a file://... URL
  2032. to tell Subversion where to put the new project. This
  2033. syntax looks a lot like Internet addresses you see in a
  2034. web browser, except instead of starting with http://
  2035. the URL starts with file:// . This tells Subversion to
  2036. look on the local filesystem for the repository, instead
  2037. of on the web.
  2038. In Chapter 5, Accessing a Repository, on page 55
  2039. you’ll see how you can use different URLs to access a
  2040. Subversion repository via a network, either on a web
  2041. server or via the custom svn protocol.
  2042. Subversion responds by letting us know that it has added the
  2043. two files and has committed the change into the repository.
  2044. So, now we’ve got these files safely tucked away in the repos-
  2045. itory. If we are brave (or foolish), we can go ahead and delete
  2046. the copies in our temporary directory. However, the prudent
  2047. (and pragmatic) developer would probably want to verify that
  2048. they are indeed correctly stored in the repository before delet-
  2049. ing them. And the easiest way to do that is to get Subversion
  2050. to check the files in the Sesame project out into your local
  2051. work area. Once we’ve confirmed that everything is there,
  2052. and that it looks correct, we can delete our originals. The
  2053. next section shows how this is done.
  2054. 3.4 Starting to Work with a Project
  2055. It doesn’t matter whether you’re starting work with a new
  2056. project (such as project Sesame, which we just created) or if
  2057. you’re joining a project that has been running for months and
  2058. has thousands of source files. What you do to start working
  2059. with the project’s files is the same:
  2060. will need to support branches, which will be stored in /sesame/branches . This
  2061. is discussed more fully in Chapter 8, Organizing Your Repository, on page 107.
  2062. S TARTING TO W ORK WITH A P ROJECT 38
  2063. ù ú
  2064. û
  2065. ü
  2066. ý
  2067. þ ÿ ?
  2068. ?
  2069. ?
  2070. ú ù ?
  2071. û
  2072. ý
  2073. ?
  2074. ú
  2075. ? ??
  2076. ?
  2077. ?
  2078. ?
  2079. ?
  2080. þ
  2081. ?
  2082. þ??
  2083. ?
  2084. ý
  2085. ?
  2086. ?
  2087. ?
  2088. ?
  2089. ?
  2090. ?
  2091. Figure 3.5: Working Directory Layout
  2092. 1. Decide where to put the working copies of the files on
  2093. your local machine.
  2094. 2. Check the project out of the repository into that location.
  2095. The first decision is normally fairly simple. We tend to have
  2096. a single directory on our boxes called work . We then check
  2097. out all projects somewhere under this directory. For simple
  2098. projects, we tend to check out directly under work . For more
  2099. complex ones, maybe involving code branches, we’d organize
  2100. things into a few subdirectories. For now, let’s assume we are
  2101. working with simple projects. If we have checked out three
  2102. separate projects called poppy , sesame , and sunflower , we’d end
  2103. up with directories that looked something like Figure 3.5 .
  2104. So, if you haven’t already got one, let’s start off by creating
  2105. a work directory, either from the command line or using your
  2106. File Manager.
  2107. Windows: mkdir c: \ work
  2108. Unix: mkdir /home/mike/work
  2109. Now we’ll check out the source into our working directory.
  2110. We use a file:// URL to specify our repository, so again
  2111. this command looks a little different on Windows and Unix.
  2112. M AKING C HANGES 39
  2113. Change to your work directory, and then on Windows run
  2114. work > svn co file:///c:/svn-repos/sesame/trunk sesame
  2115. A sesame \ Number.txt
  2116. A sesame \ Day.txt
  2117. Checked out revision 1.
  2118. On Unix, you need to run
  2119. work > svn co file:///home/mike/svn-repos/sesame/trunk sesame
  2120. A sesame/Number.txt
  2121. A sesame/Day.txt
  2122. Checked out revision 1.
  2123. The argument co tells Subversion that we want to perform
  2124. a checkout, the file:// URL specifies which repository we
  2125. want to check out from, and finally we tell Subversion where
  2126. we want to put our working copy, in this case inside a sesame
  2127. directory in our working directory.
  2128. You now have a local copy 2 of the Sesame project containing
  2129. the two files that we initially imported. From now on, we’ll be
  2130. working with these copies of the files, because these are the
  2131. ones that are being managed by Subversion. After checking
  2132. that they look correct, we can go ahead and delete the original
  2133. copies in our temporary directory. We’ve handed control of
  2134. these files over to our version control system, and it’s just
  2135. too confusing to have the original and the managed copies
  2136. lying around on our machine. We’ll make sesame our current
  2137. directory and work with the checked-out files.
  2138. 3.5 Making Changes
  2139. Despite all our hard work, our customer comes back com-
  2140. plaining; it appears our software needs to work on weekends.
  2141. So, fire up your favorite editor and add two lines to the end of
  2142. Day.txt :
  2143. monday
  2144. tuesday
  2145. wednesday
  2146. thursday
  2147. friday
  2148. saturday
  2149. sunday
  2150. 2 Subversion calls this a working copy of the repository files, and this cor-
  2151. responds to the SCM “private workspace” pattern.
  2152. M AKING C HANGES 40
  2153. After saving these changes to disk, let’s see what Subversion
  2154. now thinks about the state of our project. You can use the svn
  2155. status command to get the status of one or more files:
  2156. sesame > svn status Day.txt
  2157. M Day.txt
  2158. The M here is showing us that Subversion recognizes that this
  2159. file has been modified locally (and that these changes have
  2160. not yet been saved in the repository).
  2161. If we do all our work in small increments, it’s easy to remem-
  2162. ber what changes we made to individual files. However, if
  2163. you’ve forgotten why a file has been modified (or if you just
  2164. want to double-check), you can use the svn diff command to
  2165. show the changes between the repository version of the file
  2166. and your local copy:
  2167. sesame > svn diff Day.txt
  2168. Index: Day.txt
  2169. ===================================================================
  2170. --- Day.txt (revision 1)
  2171. +++ Day.txt (working copy)
  2172. @@ -3,3 +3,5 @@
  2173. wednesday
  2174. thursday
  2175. friday
  2176. +saturday
  2177. +sunday
  2178. The output contains a bunch of information. The first line
  2179. tells us the name of the file being examined. This has a couple
  2180. of uses. First, if we’re examining a bunch of files with one
  2181. command, it helps us identify where we are. Second, it is also
  2182. used when generating patches (but that’s not something we’ll
  2183. be looking at for a while yet).
  2184. The two lines after the row of equals signs tell us the name
  2185. and revision number of the repository file and that we’re com-
  2186. paring it with the working copy.
  2187. The cryptic @@ -3,3 +3,5 @@ tells us where in the file the
  2188. differences are, followed by the actual difference. The lines
  2189. starting with + mean they’ve been added, and a line starting
  2190. with - would mean it has been removed.
  2191. This diff is shown in unified format, meaning that it contains
  2192. context information as well as lines that have been changed.
  2193. It’s a popular format because it’s easy to read, and the extra
  2194. U PDATING THE R EPOSITORY 41
  2195. context allows changes to be applied even if the original file
  2196. has been altered slightly. Subversion also allows us to specify
  2197. our own diff program using --diff-cmd . This is useful if we want
  2198. to use a graphical diff utility, for example.
  2199. This is an area where the GUI front ends to Subversion have a
  2200. distinct advantage: if you use such a tool, you should be able
  2201. to generate nice color-coded displays of file differences.
  2202. In addtion, the Subversion diff command can show differences
  2203. between your working copy and a specific repository version,
  2204. or between two versions within the repository. Section 6.6,
  2205. Using Subversion Revision Identifiers, on page 80 discusses
  2206. diff options in more detail.
  2207. 3.6 Updating the Repository
  2208. Having made our changes (and of course having run the unit
  2209. tests), we’re ready to save our latest version in the repository.
  2210. On a single-person project such as Sesame, this is really very
  2211. simple—you use the svn commit command:
  2212. sesame > svn commit -m "Client wants us to work on weekends"
  2213. Sending Day.txt
  2214. Transmitting file data .
  2215. Committed revision 2.
  2216. The commit function is used to save any changes we’ve made
  2217. back to the repository. The -m option is used to attach a
  2218. meaningful message to the changes.
  2219. Even though we asked Subversion to commit all files in the
  2220. Sesame project, it’s clever enough to know that Number.txt has
  2221. not changed, so only the changes in Day.txt are sent to the
  2222. repository.
  2223. Subversion tells us it has “committed revision 2.” It’s impor-
  2224. tant to note that this means revision 2 of the whole repository,
  2225. not just Day.txt . If we had changed both Day.txt and Number.txt ,
  2226. we’d still be at revision 2 in the repository. You can think of
  2227. Subversion revision numbers as kind of a global marker going
  2228. all the way through the repository, recording when each set of
  2229. changes went in.
  2230. Following the commit, you can use the log function to confirm
  2231. that the repository has indeed been updated:
  2232. U PDATING THE R EPOSITORY 42
  2233. sesame > svn log Day.txt
  2234. ---------------------------------------------------------
  2235. r2 | mike | 2004-09-08 21:54:19 -0600 (Wed, 08 Sep 2004)
  2236. Client wants us to work on weekends
  2237. ---------------------------------------------------------
  2238. r1 | mike | 2004-09-08 21:50:13 -0600 (Wed, 08 Sep 2004)
  2239. importing Sesame project
  2240. ---------------------------------------------------------
  2241. We can see that mike was the last user to change Day.txt , in
  2242. revision 2 ( r2 ) of the repository, and we can see the log mes-
  2243. sage that was used when adding Saturday and Sunday to our
  2244. list of days. We can also see that Day.txt was changed in revi-
  2245. sion 1, when we imported the Sesame project. If you use
  2246. --verbose , Subversion will tell you exactly what changed with
  2247. each revision:
  2248. sesame > svn log --verbose Day.txt
  2249. ---------------------------------------------------------
  2250. r2 | mike | 2004-09-08 21:54:19 -0600 (Wed, 08 Sep 2004)
  2251. Changed paths:
  2252. M /sesame/trunk/Day.txt
  2253. Client wants us to work on weekends
  2254. ---------------------------------------------------------
  2255. r1 | mike | 2004-09-08 21:50:13 -0600 (Wed, 08 Sep 2004)
  2256. Changed paths:
  2257. A /sesame
  2258. A /sesame/trunk
  2259. A /sesame/trunk/Day.txt
  2260. A /sesame/trunk/Number.txt
  2261. importing Sesame project
  2262. ---------------------------------------------------------
  2263. Now that Subversion is being extra talkative, we can see that
  2264. in revision 2 /sesame/trunk/Day.txt was modified—there’s an M
  2265. next to it. For revision 1, we can see that the /sesame directory
  2266. and contents were created. Because of the way Subversion
  2267. tracks commits—changes to a set of files, all saved at once
  2268. and associated with a single log message—it can display all
  2269. the files that were changed in each commit, even though we
  2270. asked only about Day.txt . This can be extremely useful, for
  2271. example, when reviewing historical information when tracking
  2272. down a bug.
  2273. Mixed Revision Working Copies
  2274. In the last example we used svn log to look at the history of
  2275. Day.txt . In fact, using svn log without any other arguments pro-
  2276. duces a log for the current directory and any subdirectories,
  2277. starting with the most recent changes and working backward.
  2278. U PDATING THE R EPOSITORY 43
  2279. Setting Up a Message Editor
  2280. Whenever you change the repository by importing
  2281. files, committing changes, or copying things around,
  2282. you need to enter a log message. If you don’t specify
  2283. the -m option, Subversion will try to open an editor for
  2284. you to type in a log message.
  2285. Subversion looks at environment variables to deter-
  2286. mine which editor it should use, trying SVN EDITOR ,
  2287. VISUAL , and EDITOR . If you’re on Windows andwould
  2288. like to set your editor to Notepad, open a command
  2289. prompt and type
  2290. work > set SVN EDITOR=notepad
  2291. This will set SVN EDITOR only for the lifetime of your
  2292. command window. If you want to set the environ-
  2293. ment variable permanently, you need to go into Win-
  2294. dows’ Control Panel (switch to Classic View if you’re
  2295. using Windows XP) and choose System. Under the
  2296. Advanced tab, hit the Environment Variables but-
  2297. ton, and create a new variable. The variable name
  2298. should be SVN EDITOR , and the value should be
  2299. notepad . After setting up the new environment vari-
  2300. able, you’ll need to close any open command win-
  2301. dows and re-open them for the new setting to take
  2302. effect.
  2303. If you’re a Unix user, you’ll set environment variables
  2304. differently depending on the shell you’re using. Try
  2305. looking at .profile , .bashrc , or .cshrc in your home direc-
  2306. tory for existing environment variables, and then add
  2307. a new one. You may need to log out and back in
  2308. again for a new setting to take effect.
  2309. W HEN W ORLDS C OLLIDE 44
  2310. If you ask for the log of the current directory immediately
  2311. after committing a change to Day.txt , Subversion won’t tell you
  2312. about your change. This is a bit counterintuitive—after all the
  2313. change is in the repository, we can see it if we ask for the log
  2314. for Day.txt —so why isn’t Subversion including it in the log for
  2315. the current directory?
  2316. The answer is that because Subversion tracks directories as
  2317. first-class objects, it remembers the revision number for each
  2318. directory in your working copy. When we commit a change to
  2319. Day.txt , Subversion knows the working copy is at revision 2,
  2320. but the actual directory is still at revision 1. In order to see
  2321. the log message, you’ll need to run svn update first, updating
  2322. the current directory to revision 2.
  2323. Most of the time you can just ignore mixed revisions. If you
  2324. do get tripped up by this behavior, a quick svn update will fix
  2325. the problem. In the recipes shown later in the book, we’ll
  2326. often include an update as the first step, helping to avoid this
  2327. problem altogether.
  2328. 3.7 When Worlds Collide
  2329. Everyone gets nervous when they first hear that Subversion
  2330. doesn’t lock files for editing. They wonder, “what happens if
  2331. two people edit the same file at the same time?” In this sec-
  2332. tion we’ll find out (and hopefully in the process put to rest any
  2333. worries you may have). To do this, we’ll need another user (so
  2334. that we can have multiple people editing a file at the same
  2335. time). Unfortunately, our supplier of do-it-yourself human
  2336. cloning kits is on the run, so we’ll have to make do with sim-
  2337. ulating the other you.
  2338. When it comes to handling conflicts, Subversion doesn’t really
  2339. know about users. Instead, it cares about making sure that
  2340. different working copies are consistent with the repository.
  2341. This means we can simulate our second user simply by check-
  2342. ing out a new copy of our project; we just need to put it in a
  2343. different place than the first copy. When we first checked out
  2344. our project, we put it in a directory called sesame , which is
  2345. the project name. To check it out again, we’ll need to specify
  2346. a different location, a directory parallel to the one we’ve been
  2347. W HEN W ORLDS C OLLIDE 45
  2348. working in. Let’s call that directory aladdin . To check out on
  2349. Windows, change to your work directory and run
  2350. work > svn co file:///c:/svn-repos/sesame/trunk aladdin
  2351. A aladdin \ Number.txt
  2352. A aladdin \ Day.txt
  2353. Checked out revision 2.
  2354. On a Unix system, you need to run
  2355. work > svn co file:///home/mike/svn-repos/sesame/trunk aladdin
  2356. A aladdin/Number.txt
  2357. A aladdin/Day.txt
  2358. Checked out revision 2.
  2359. We’ve checked out the project we’ve been working on all along
  2360. (Sesame) from the same repository. But we tell Subversion to
  2361. store the files in a new directory, called aladdin . Because we
  2362. checked in the files from our original directory, we now have
  2363. two copies of the project on our hard drive, one in sesame , the
  2364. other in aladdin . Right now the two sets of files are identical
  2365. (skeptical readers, feel free to check). Remember that two
  2366. different directories are our simulation of having two people
  2367. working on our project, each with their own checked-out copy
  2368. of the files.
  2369. Let’s first do a quick sanity check. We’ll alter a file in one
  2370. directory, check it in, and then ask Subversion to update our
  2371. local copy in the other directory.
  2372. First, edit the file Number.txt in the sesame directory, adding
  2373. two new lines (five and six):
  2374. zero
  2375. one
  2376. two
  2377. three
  2378. four
  2379. five
  2380. six
  2381. Now check this file into the repository:
  2382. sesame > svn commit -m "Customer wants more numbers"
  2383. Sending Number.txt
  2384. Transmitting file data .
  2385. Committed revision 3.
  2386. Now for the first moment of truth. Over in the aladdin direc-
  2387. tory, its version of Number.txt is now out-of-date (because the
  2388. repository now holds a more recent version). Let’s pop over
  2389. there and check:
  2390. W HEN W ORLDS C OLLIDE 46
  2391. sesame > cd ..
  2392. work > cd aladdin
  2393. aladdin > svn status --show-updates
  2394. * 2 Number.txt
  2395. Status against revision: 3
  2396. We’re using --show-updates (short form -u ) to get Subversion to
  2397. talk to the repository and find out if any updates are available
  2398. for files in the aladdin directory. We need to use this option
  2399. because by default Subversion just checks to see whether files
  2400. in the working copy have been locally modified, not whether
  2401. an updated version is available in the repository.
  2402. The asterisk shows that an update is available for Number.txt ,
  2403. which is currently at revision 2. Subversion also tells us that
  2404. the repository was at revision 3 when it performed the check.
  2405. Before we update to the latest version, we might ask Subver-
  2406. sion to tell us what’s different between our version of the file
  2407. and the version currently in the repository (as there are times
  2408. when you may want to defer an update if it affects stuff you’re
  2409. currently working on). Again, we use the svn diff command:
  2410. aladdin > svn diff -rHEAD Number.txt
  2411. Index: Number.txt
  2412. ===================================================================
  2413. --- Number.txt (revision 3)
  2414. +++ Number.txt (working copy)
  2415. @@ -3,5 +3,3 @@
  2416. two
  2417. three
  2418. four
  2419. -five
  2420. -six
  2421. The -rHEAD option tells Subversion we want to compare our
  2422. local copy of Number.txt against whatever revision is the most
  2423. recent in the repository. After another one of those cryptic @@
  2424. -3,5 +3,3 @@ lines, we see that the two new lines are miss-
  2425. ing from our working copy (which shouldn’t be a surprise).
  2426. If we hadn’t specified the -r flag, Subversion would compare
  2427. our local copy of Number.txt against the repository version that
  2428. was checked out to produce it (r2 in this case). As we haven’t
  2429. altered the file in our Aladdin persona, this would show no
  2430. changes.
  2431. We can update our copy in the aladdin directory to merge in
  2432. the changes we made over in sesame :
  2433. aladdin > svn update
  2434. U Number.txt
  2435. Updated to revision 3.
  2436. C ONFLICT R ESOLUTION 47
  2437. Subversion prints U next to Number.txt to let us know that it
  2438. has updated it and tells us that our working copy has been
  2439. updated to revision 3. If we look at Number.txt , we’ll see that
  2440. we now have the two extra lines.
  2441. 3.8 Conflict Resolution
  2442. So, what happens if two people edit the same file at the same
  2443. time? It turns out that there are two scenarios. The first is
  2444. when the changes don’t overlap. Simulating this takes a little
  2445. effort, so hang in there.
  2446. First, edit the copy of Number.txt in the sesame directory. Make
  2447. the first line uppercase:
  2448. ZERO
  2449. one
  2450. two
  2451. three
  2452. four
  2453. five
  2454. six
  2455. Number.txt (in Sesame)
  2456. Now edit the version of Number.txt over in aladdin . This time
  2457. make the last line uppercase:
  2458. zero
  2459. one
  2460. two
  2461. three
  2462. four
  2463. five
  2464. SIX
  2465. Number.txt (in Aladdin)
  2466. What we’ve just done is simulate two developers each mak-
  2467. ing local changes to the same file. Right now, these changes
  2468. are independent, because the repository knows about neither.
  2469. Let’s change that. A coin toss told us that Aladdin checked in
  2470. his version of the changed file first:
  2471. aladdin > svn commit -m "Make ' six ' important"
  2472. Sending Number.txt
  2473. Transmitting file data .
  2474. Committed revision 4.
  2475. A short time later, the sesame developer tries to check in too.
  2476. (Remember, this version of the file has the first line in upper-
  2477. case.)
  2478. sesame > svn commit -m "Zero needs emphasizing"
  2479. Sending Number.txt
  2480. svn: Commit failed (details follow):
  2481. svn: Out of date: ' /sesame/trunk/Number.txt ' in transaction ' 7 '
  2482. C ONFLICT R ESOLUTION 48
  2483. Subversion is telling us that it tried to commit the change
  2484. from sesame , but it failed because /sesame/trunk/Number.txt is
  2485. out-of-date. Let’s try bringing our local version of the file up-
  2486. to-date with the repository. Remember that our file has an
  2487. uppercase zero, and the repository version has an upper case
  2488. six.
  2489. sesame > svn update
  2490. G Number.txt
  2491. Updated to revision 4.
  2492. Subversion prints a G to tell us it has merged our changes
  2493. with the repository version (previously, it printed U to let us
  2494. know it had updated our working copy with a new version
  2495. from the repository). Let’s look at our local version:
  2496. ZERO
  2497. one
  2498. two
  2499. three
  2500. four
  2501. five
  2502. SIX
  2503. Magic! Our version now contains both our changes and the
  2504. Aladdin changes. We both edited a file at the same time, and
  2505. Subversion worked it out.
  2506. Before we get too smug, though, remember that our local
  2507. change (the ZERO ) hasn’t yet been stored in the repository. We
  2508. ask Subversion to commit our change, and this time it suc-
  2509. ceeds, because our local version contains the latest repository
  2510. revisions:
  2511. sesame > svn commit -m "Zero needs emphasizing"
  2512. Sending Number.txt
  2513. Transmitting file data .
  2514. Committed revision 5.
  2515. The next time Aladdin updates, he’ll get our changes too:
  2516. sesame > cd ..
  2517. work > cd aladdin
  2518. aladdin > svn update
  2519. U Number.txt
  2520. Updated to revision 5.
  2521. Butting Heads—When Changes Clash
  2522. In the previous example, the changes made by the two (vir-
  2523. tual) developers didn’t overlap. What happens if two develop-
  2524. ers edit the same lines in the same file at the same time? Let’s
  2525. find out.
  2526. C ONFLICT R ESOLUTION 49
  2527. Go into the sesame directory and change the second line in
  2528. Number.txt from one to ichi. Don’t check this change in. Now
  2529. go across to the aladdin directory and change the same line
  2530. from one to uno. Let’s assume that once again Aladdin gets to
  2531. check in his changes first:
  2532. aladdin > svn commit -m "User likes Italian one"
  2533. Sending Number.txt
  2534. Transmitting file data .
  2535. Committed revision 6.
  2536. Now let’s go back to the sesame directory. Remembering that
  2537. we’re supposed to be simulating two separate users, we pre-
  2538. tend we don’t know about the changes made by Aladdin, and
  2539. so try to check in our changes:
  2540. sesame > svn commit -m "One should be Japanese"
  2541. Sending Number.txt
  2542. svn: Commit failed (details follow):
  2543. svn: Out of date: ' /sesame/trunk/Number.txt ' in transaction ' c '
  2544. We’ve seen this message before: we need to update to get the
  2545. repository changes:
  2546. sesame > svn update
  2547. C Number.txt
  2548. Updated to revision 6.
  2549. Subversion tells us it has managed to update Sesame’s work-
  2550. ing copy to revision 6, but the C next to Number.txt tells us
  2551. that there was a conflict when it tried to merge the repository
  2552. changes with our local changes. Have we lost all our hard
  2553. work? No.
  2554. CVS Hint: When CVS detects a conflict, it’ll print a whole bunch of
  2555. warning messages and generally tell you the sky is falling. This is to
  2556. remind you to fix the conflict, as it’s very easy to check in a file that
  2557. still has conflict markers left in it. Subversion tracks the file’s state so it
  2558. knows whether you’ve resolved the conflict, and won’t let you check
  2559. in until things are okay.
  2560. When conflicts happen, it’s most often because two develop-
  2561. ers had some kind of misunderstanding. In this case, one
  2562. developer wanted to change the line to Italian, and the other
  2563. wanted Japanese. If you think about this, it becomes appar-
  2564. ent that what we have here is a breakdown in communication;
  2565. there’s a problem in the team (or at least in the team’s pro-
  2566. cess). Whatever the cause, we’re left wondering, “what should
  2567. the line really be?” Subversion doesn’t have a hot line to the
  2568. C ONFLICT R ESOLUTION 50
  2569. truth, so it can’t solve the problem. Instead, it adds special
  2570. annotations to the file to show what the conflict is. In this
  2571. case if we look at the file Number.txt , we’ll see it now looks like:
  2572. ZERO
  2573. <<<<<<< .mine
  2574. ichi
  2575. =======
  2576. uno
  2577. >>>>>>> .r6
  2578. two
  2579. three
  2580. four
  2581. five
  2582. SIX
  2583. The lines with the <<<<<<< and >>>>>>> show where the
  2584. conflict occurred. Between them we can see both our change
  2585. and the conflicting change in the repository.
  2586. Time to do some detective work. The first thing we need to do
  2587. is to find out who made the change in the repository. We’ll use
  2588. svn log to help us find out what happened here. The conflict
  2589. markers seem to suggest r6 is causing the problem:
  2590. sesame > svn log -r6 Number.txt
  2591. ---------------------------------------------------------
  2592. r6 | mike | 2004-09-08 23:01:03 -0600 (Wed, 08 Sep 2004)
  2593. User likes Italian one
  2594. ---------------------------------------------------------
  2595. Looking at the log entry, we can see the name of the author
  2596. of the change, along with their check in comment. We wander
  2597. over and ask him about the change. A quick call to the cus-
  2598. tomer resolves the problem: the customer wanted the word
  2599. one in Japanese, and two in Italian. Aladdin must have mis-
  2600. heard.
  2601. Armed with this new information, we can now resolve the con-
  2602. flict. Edit Number.txt in the sesame directory, remove Subver-
  2603. sion’s conflict markers, and make the changes requested by
  2604. the customer:
  2605. ZERO
  2606. ichi
  2607. due
  2608. three
  2609. four
  2610. five
  2611. SIX
  2612. Having removed the conflict markers, we can tell Subversion
  2613. we’ve resolved the conflict and then commit the file:
  2614. sesame > svn resolved Number.txt
  2615. Resolved conflicted state of ' Number.txt '
  2616. C ONFLICT R ESOLUTION 51
  2617. sesame > svn commit -m "One is Japanese, two Italian"
  2618. Sending Number.txt
  2619. Transmitting file data .
  2620. Committed revision 7.
  2621. Subversion actually helped us discover a misunderstanding.
  2622. We resolved the conflict, and everyone is happy. Optimistic
  2623. locking may actually deserve its name. And, just to make
  2624. things even less scary, we need to emphasize that conflicts
  2625. rarely happen on real projects.
  2626. However, it’s also worth noting that Subversion is not a mind-
  2627. reader. It might happen that two people fix the same bug
  2628. in two different ways. If these changes don’t conflict at the
  2629. source code level, Subversion will happily accept both, even
  2630. though it may make no sense to have both fixes in the same
  2631. code. The lack of a conflict means you haven’t trodden on
  2632. anyone else’s changes at the textual level, but you should still
  2633. rely on unit tests to verify that the change works.
  2634. Subversion also supports strict locking for unmergeable files
  2635. such as sound, graphics and video. Chapter 7, File Locking
  2636. and Binary Files, on page 99 discusses file locking in more
  2637. detail.
  2638. That’s all for our quick tour around Subversion. However, you
  2639. may want to leave your test repository lying around. Later,
  2640. you might find it helpful if you want to experiment with a par-
  2641. ticular facility before doing it for real in the project repository.
  2642. Chapter 4
  2643. How To...
  2644. Even though version control sounds great in theory, many
  2645. teams don’t use it. Sometimes this is because the theory
  2646. doesn’t seem to translate into practice too well. It’s all very
  2647. well reading a document that says something like “generate
  2648. a release branch,” but what does that actually mean when it
  2649. comes down to typing in the correct Subversion commands?
  2650. Another problem is that teams sometimes embrace version
  2651. control too vigorously, creating very complex structures to
  2652. hold their source, with correspondingly frightening lists of
  2653. instructions for achieving even the simplest task. The result?
  2654. Eventually (and in our experience that means very quickly),
  2655. the team gives up; using the version control system is seen to
  2656. be just too much hassle.
  2657. The remaining chapters in this book address both of these
  2658. problems. They present a simple way to organize your version
  2659. control system and a set of basic practices for doing the every-
  2660. day things a team needs to do. We suggest to start you use
  2661. these basic practices as a set of recipes; follow them whenever
  2662. you need to achieve a certain result. Try hard not to deviate
  2663. too much from them; if you find yourself wanting to create a
  2664. scenario we don’t cover, think hard before proceeding. Per-
  2665. haps you don’t really need it.
  2666. As with any set of recipes, you’ll soon find yourself feeling
  2667. more and more comfortable following them. This is the time
  2668. to start some gentle experimenting. However, we suggest you
  2669. don’t try something new directly in a real project’s repository.
  2670. O UR B ASIC P HILOSOPHY 53
  2671. Instead, set up the scenario in a test repository (such as the
  2672. one we set up in the previous chapter), and try things out
  2673. there.
  2674. 4.1 Our Basic Philosophy
  2675. We think version control is one of the three essential techni-
  2676. cal practices; every team needs to be proficient in all three (the
  2677. others are Pragmatic Unit Testing [HT03], [HT04], and Prag-
  2678. matic Project Automation [Cla04]). Every team should be using
  2679. version control—all the time, and for everything they pro-
  2680. duce. So we have to make it simple, obvious, and lightweight
  2681. (because if we don’t, people will eventually stop doing it).
  2682. Simplicity means that doing something that should be simple
  2683. will actually be simple. Checking in our changes is a simple
  2684. (and common) operation, so the basic operation should be one
  2685. or two actions. Creating a new customer release is a some-
  2686. what more complex concept, so it’s okay to use a few more
  2687. steps doing it, but it should still be as simple as possible.
  2688. Version control has to be obvious: we need to arrange things
  2689. so that it is clear what we’re doing and what version of the
  2690. software we’re doing it to. There should be no guessing when
  2691. it comes to the source.
  2692. Finally, we’re describing a lightweight process; we don’t want
  2693. version control to get in the way of getting real work done.
  2694. 4.2 Important Steps When Using Version
  2695. Control
  2696. Here is our basic set of rules for organizing your source in a
  2697. Subversion repository:
  2698. • Before you start, you need to establish an effective and
  2699. secure way to access your repository.
  2700. • Once you’ve gained access, there is a simple set of Sub-
  2701. version commands that you’ll be using daily.
  2702. • Each project that your company develops must be stored
  2703. in a distinct directory within the Subversion repository.
  2704. I MPORTANT S TEPS W HEN U SING V ERSION C ONTROL 54
  2705. You should be able to check out a project’s complete
  2706. source from a single point.
  2707. • If projects contain subcomponents that can be worked
  2708. on in isolation, or if you intend to share components
  2709. between projects, these components should be stored as
  2710. projects in their own right and included as an external
  2711. resource in other projects.
  2712. • If your project incorporates code from third parties (ven-
  2713. dors, or perhaps open-source projects) you need to man-
  2714. age this as a resource.
  2715. • Developers should use branches to separate the main
  2716. line of development from code lines that have different
  2717. life cycles, such as release branches and major code
  2718. experiments. Tags are used to identify significant points
  2719. in time, including releases and bug fixes.
  2720. We cover each of these topics in the chapters that follow.
  2721. Chapter 5
  2722. Accessing a Repository
  2723. In Chapter 3, Getting Started with Subversion, on page 28,
  2724. we created a repository and learned how to access it via a
  2725. file-based URL. This is great for a single user but doesn’t
  2726. really help a whole development team collaborate properly.
  2727. In this chapter we’ll discuss the three main ways you can
  2728. make an existing repository available over the network, what
  2729. they mean for a user accessing a repository, and the pros and
  2730. cons of the various access mechanisms.
  2731. Appendix A on page 151 includes a guide for administrators
  2732. who are installing, networking, and securing Subversion.
  2733. 5.1 Network Protocols
  2734. After creating our sandbox repository, we used a repository
  2735. URL to tell Subversion what we wanted to check out. This repository URL
  2736. URL included both a definition of where the repository was
  2737. and also what path inside the repository we were interested
  2738. in. Once we had a working copy we didn’t need to keep using
  2739. the repository URL, since Subversion remembers where our
  2740. working copy came from.
  2741. Repository URLs are important whenever we want to directly
  2742. access a repository (when we’re creating branches and tags or
  2743. merging big sets of changes, for example). Figure 5.1 on the
  2744. following page shows how the URL for our sandbox repository
  2745. is composed.
  2746. The first part of this URL is file . This specifies the scheme scheme
  2747. we’re using to locate the repository, in this case the local
  2748. N ETWORK P ROTOCOLS 56
  2749. ????????????????? ?? ?? ? ?????
  2750. ? ? ? !"#$%
  2751. &
  2752. '
  2753. $
  2754. (
  2755. )
  2756. *
  2757. $?+
  2758. '
  2759. &
  2760. $,-+
  2761. '
  2762. ? .
  2763. &
  2764. '
  2765. ?
  2766. &
  2767. ,
  2768. (
  2769. #$%
  2770. &
  2771. '
  2772. $
  2773. (
  2774. )
  2775. Figure 5.1: Components of a Repository URL
  2776. filesystem. The next part, c:/svn-repos , tells Subversion
  2777. the repository database files are in a particular directory on
  2778. the C: drive. Finally, /sesame/trunk/ specifies the path
  2779. within the repository that we’re interested in.
  2780. Subversion supports a number of different schemes in repos-
  2781. itory URLs and even allows you to define custom extensions
  2782. yourself. Each different scheme tells Subversion to access
  2783. the repository via a particular network protocol. We’ll start by
  2784. looking at the simple svn protocol.
  2785. svn
  2786. The easiest way to network a repository is to use the svn
  2787. scheme. Subversion comes with svnserve , a small server that
  2788. listens for network connections, allows repository access over
  2789. the network, and supports simple authentication of users.
  2790. svnserve is probably most suitable for teams on a private LAN
  2791. who want to get going quickly.
  2792. If an administrator (possibly you!) has used the instructions
  2793. in Section A.2, Networking with svnserve, on page 153 to put
  2794. the Sesame repository online, you can check it out by running
  2795. work > svn co svn://olio/sesame/trunk vizier
  2796. A vizier/Number.txt
  2797. A vizier/Day.txt
  2798. Checked out revision 7.
  2799. Success! We used the svn scheme to access a repository on a
  2800. machine called olio , and we checked out the Sesame project
  2801. to a new vizier working directory.
  2802. If you’ve tried playing with the working copy on your client
  2803. machine, you might find that Subversion doesn’t let you com-
  2804. N ETWORK P ROTOCOLS 57
  2805. mit any changes. For example, try adding a new data file,
  2806. Month.txt , to the project:
  2807. vizier > svn add Month.txt
  2808. A Month.txt
  2809. vizier > svn commit -m "Added month data"
  2810. svn: Commit failed (details follow):
  2811. svn: Connection is read-only
  2812. If this happens, your administrator has forgotten to enable
  2813. write access to the repository (it’s read-only by default). Get
  2814. them to look at Section A.5, svnserve, on page 163 and set up
  2815. some users. Once they’ve done this, you should be asked for
  2816. a username and password when you try to commit a change:
  2817. vizier > svn commit -m "Added month data"
  2818. Authentication realm: < svn://olio:3690 > sesame/trunk
  2819. Password for ' mike ' :
  2820. Adding Month.txt
  2821. Transmitting file data .
  2822. Committed revision 8.
  2823. Subversion decided to try username mike because that’s my
  2824. username on the client machine. If this isn’t right, just hit
  2825. Enter at the password prompt, and Subversion will let you
  2826. specify a different username.
  2827. svn+ssh
  2828. svnserve does a great job of getting a repository up on the net-
  2829. work, but it has a couple of drawbacks. Firstly, although
  2830. passwords are never transmitted in clear text over the net-
  2831. work, the contents of your files travel unencrypted. Anyone
  2832. who can sniff your network traffic can see what your files con-
  2833. tain. This might be okay for a team all on the same LAN, but if
  2834. you want to use the public Internet for accessing your repos-
  2835. itory it simply isn’t secure. Secondly, passwords are stored
  2836. in plain text in the server’s conf directory and can only be
  2837. changed by an administrator with access to the password file.
  2838. Subversion solves both of these security problems by leverag-
  2839. ing the Secure Shell (SSH). If you’re a Unix user, you might Secure Shell
  2840. already have SSH infrastructure in place for connecting to
  2841. your server. SSH employs strong encryption to protect the
  2842. contents of a client-server session. It is widely used for admin-
  2843. istering servers over the Internet. Figure 5.2 on the next page
  2844. shows how Subversion secures an svn connection using SSH.
  2845. N ETWORK P ROTOCOLS 58
  2846. / 0 1
  2847. / /2
  2848. /01/ 3
  2849. 4
  2850. 03
  2851. // 2 5
  2852. 678
  2853. 9
  2854. : ;
  2855. <
  2856. =7
  2857. 11 3
  2858. :
  2859. >
  2860. 9
  2861. 7
  2862. 1
  2863. ?@ A
  2864. B
  2865. C D
  2866. E
  2867. F GHI @ @FA
  2868. E
  2869. J
  2870. I@
  2871. Figure 5.2: Tunnel Subversion Over SSH
  2872. Subversion needs an SSH client installed on your machine
  2873. in order for you to access a repository using svn+ssh . Unix
  2874. users are likely to have SSH already installed, but if you’re on
  2875. Windows, you’ll need to do a bit of work. Putty is an excel-
  2876. lent SSH client and is available from http://www.chiark.
  2877. greenend.org.uk/ ˜ sgtatham/putty/ . Download plink.exe ,
  2878. and save it somewhere in your path; C:\Windows\system32 usu-
  2879. ally works. If you’re using TortoiseSVN you don’t need to
  2880. worry about installing an SSH client since Tortoise comes with
  2881. TortoisePlink .
  2882. Next you need to edit your Subversion client configuration
  2883. settings. Windows applications store user-specific data inside
  2884. a special folder, which changes location depending upon how
  2885. your computer is set up and which version of Windows you’re
  2886. using. If you’re not sure where your application data directory
  2887. is, open a command prompt and run the following:
  2888. work > echo %APPDATA%
  2889. C: \ Documents and Settings \ mike \ Application Data
  2890. Once you’ve found your application data directory, open the
  2891. Subversion subdirectory, and edit the config file that’s inside.
  2892. Edit the section on tunnels so it looks like this:
  2893. [tunnels]
  2894. ssh=plink
  2895. You need to specify a svn+ssh scheme if you’d like Subversion
  2896. to use SSH to protect your connections. If your server accepts
  2897. SSH connections, try running
  2898. N ETWORK P ROTOCOLS 59
  2899. work > svn checkout \
  2900. svn+ssh://olio/home/mike/svn-repos/sesame/trunk \
  2901. princess
  2902. mike@olio ' s password:
  2903. A princess/Month.txt
  2904. A princess/Number.txt
  2905. A princess/Day.txt
  2906. Checked out revision 8.
  2907. This looks just like the repository URL we used earlier with
  2908. svnserve , except we changed the scheme to svn+ssh . If you’re
  2909. having problems accessing your repository, Section A.3, Trou-
  2910. bleshooting an SSH Connection, on page 156 contains a guide
  2911. to diagnosing the problem.
  2912. Subversion is now using SSH to open a connection to the
  2913. server and authenticate you as a Unix user. Subversion uses
  2914. the standard Unix user and group permissions to determine
  2915. whether the user with which we connect has permission to
  2916. access the repository. If you’re using SSH public/private keys
  2917. or an SSH agent to manage your credentials, the Subver-
  2918. sion client automatically takes advantage of this, which might
  2919. mean you don’t get asked for a password at all.
  2920. Using svn+ssh is appealing if you already have SSH accounts
  2921. for your users, because you can leverage all your existing
  2922. infrastructure. The extra security lets you connect over the
  2923. Internet without fear that someone might steal your Sesame
  2924. project code and without all the hassle of setting up a full
  2925. VPN. svn+ssh is a straightforward solution that should have
  2926. you up and running pretty fast.
  2927. http
  2928. Subversion can also host a repository over the web by using
  2929. the Apache web server. A special Subversion module, called
  2930. mod dav svn , does the hard work and allows Subversion to
  2931. share the web server with traditional web sites. Apache is
  2932. highly configurable, and Subversion takes full advantage of
  2933. its built-in security and scalability. You can host a reposi-
  2934. tory using standard http and https and leverage any of the
  2935. authentication mechanisms already supported by Apache.
  2936. You may have heard that Subversion requires Apache—this
  2937. actually isn’t true; neither svn nor svn+ssh need anything
  2938. C HOOSING A N ETWORKING O PTION 60
  2939. extra to network your repository. Most prebuilt Unix pack-
  2940. ages have a dependency on Apache because they install all
  2941. three networking options, which is where the misunderstand-
  2942. ing comes from. Using Subversion with Apache is probably
  2943. the most popular solution for sharing a repository over the
  2944. Internet.
  2945. Apache provides a wealth of authentication options for users.
  2946. From basic authentication using password files to integra-
  2947. tion with a Windows domain or an LDAP server, Apache is
  2948. supremely flexible. You can even set up directory-based secu-
  2949. rity, dividing your repository into read-only or even completely
  2950. private sections. You can take advantage of standard SSL
  2951. certificates for encrypting connections to the server and avoid
  2952. firewall hassles by using standard web server port numbers.
  2953. To access a repository hosted by Apache on server olio , use
  2954. the following command:
  2955. work > svn checkout \
  2956. http://olio.mynetwork.net/svn-repos/sesame/trunk \
  2957. sesame
  2958. Authentication realm: ... Subversion repository
  2959. Password for ' mike ' : ******
  2960. A sesame/Month.txt
  2961. A sesame/Number.txt
  2962. A sesame/Day.txt
  2963. Checked out revision 8.
  2964. This particular repository requires an authenticated user even
  2965. for read-only access. Subversion automatically tries user-
  2966. name mike ; if that’s wrong, just hit Enter instead of typing a
  2967. password, and Subversion will let you specify the username.
  2968. 5.2 Choosing a Networking Option
  2969. All three network protocols for Subversion ( svn , svn+ssh and
  2970. http ) offer different trade-offs in terms of ease of setup, secu-
  2971. rity, and administration overhead. Which you choose will
  2972. depend on what kind of infrastructure you already have, your
  2973. security needs, and your familiarity with Apache.
  2974. It’s important to note that the networking option you choose
  2975. today doesn’t have to be the one you stick with tomorrow. Net-
  2976. working a repository simply puts it on the network—you can
  2977. change between svnserve and Apache (for example) as often as
  2978. C HOOSING A N ETWORKING O PTION 61
  2979. you like. It’s also possible to support multiple different access
  2980. mechanisms at the same time, although you have to be careful
  2981. with permissions.
  2982. If your team is on a reasonably secure LAN, or even a larger
  2983. network connected by a VPN, using the simple svnserve server
  2984. and svn protocol is a quick way to get up and running with
  2985. Subversion. You’ll have some administrative overhead when
  2986. adding new users or changing passwords, but this should be
  2987. offset by the easy startup. Subversion 1.3 added directory-
  2988. based authorization to svnserve making it almost as flexible as
  2989. Apache for teams on the same LAN.
  2990. If you already have existing SSH infrastructure in place, using
  2991. svn+ssh makes a lot of sense. You get strong crypto protect-
  2992. ing your connections and can take advantage of all of the key-
  2993. management and authentication options that SSH provides.
  2994. Make sure your Unix administrator understands how groups,
  2995. umasks, and sticky bits need to be set up before proceeding,
  2996. though.
  2997. If you want to host a repository over the Internet, leverage
  2998. Apache’s wide range of authentication mechanisms, or simply
  2999. play with the big boys and run a “real” server, using Apache
  3000. to host your Subversion repository is the way to go. You’ll be
  3001. able to use SSL and client-server certificates for encryption
  3002. and verifying you’re really talking to whom you think you’re
  3003. talking to, and you’ll be able to authorize users using a Win-
  3004. dows domain, LDAP, or any other authentication mechanism
  3005. that Apache supports. You’ll also be able to be much more
  3006. precise about which parts of a repository users have access
  3007. to, by leveraging the mod authz svn Apache module. Using
  3008. Apache on standard HTTP ports also means fewer holes need
  3009. to be opened on your firewalls. Your network administrator
  3010. will thank you for that.
  3011. Chapter 6
  3012. Common Subversion
  3013. Commands
  3014. In Chapter 3, Getting Started with Subversion, on page 28 we
  3015. created a simple project and experimented with basic Sub-
  3016. version commands. In this chapter we’ll take this further by
  3017. presenting a set of recipes: the Subversion commands that
  3018. you use to do everyday tasks.
  3019. This section is not exhaustive. Later in this book we’ll be look-
  3020. ing at more advanced issues, such as release management,
  3021. workspaces, and third-party code. However, the commands
  3022. and techniques in this chapter should handle 90 percent of
  3023. the work you do with Subversion.
  3024. These examples assume you have your repository up and run-
  3025. ning and that you’ve enabled network access. We’ll assume
  3026. the Sesame project’s main code line (the trunk) is located at
  3027. svn://olio/sesame/trunk . You’ll need to use your own
  3028. server name instead of olio and the right access scheme if
  3029. you’re using http or svn+ssh instead of the basic svn .
  3030. 6.1 Checking Things Out
  3031. The svn checkout command (often abbreviated co ) gets Subver-
  3032. sion to create a new working copy from a directory stored in
  3033. the repository. In its simplest form, the checkout command
  3034. creates a working copy in a directory with the same name as
  3035. the repository directory:
  3036. C HECKING T HINGS O UT 63
  3037. work > svn checkout svn://olio/sesame/trunk
  3038. A trunk/Month.txt
  3039. A trunk/Number.txt
  3040. A trunk/Day.txt
  3041. Checked out revision 8.
  3042. Here, Subversion created the working copy in a local trunk
  3043. directory, because that’s the name of the directory in the
  3044. repository. This might not be what you want, especially if
  3045. you’re following the conventions recommended in Chapter 8,
  3046. Organizing Your Repository, on page 107. You can use an
  3047. extra argument when checking out to specify the name of the
  3048. directory Subversion should use for your working copy:
  3049. work > svn checkout svn://olio/sesame/trunk sesame
  3050. A sesame/Month.txt
  3051. A sesame/Number.txt
  3052. A sesame/Day.txt
  3053. Checked out revision 8.
  3054. By default, Subversion checks out the latest revision stored in
  3055. the repository. If you’d like an older version, use the -r option
  3056. to specify the revision number or date you’d like. Section 6.6,
  3057. Using Subversion Revision Identifiers, on page 80 contains full
  3058. details on how to refer to a particular revision.
  3059. To check out a copy of the Sesame project before we added
  3060. Month.txt , we can specify revision 7:
  3061. work > svn checkout -r 7 svn://olio/sesame/trunk old-sesame
  3062. A old-sesame/Number.txt
  3063. A old-sesame/Day.txt
  3064. Checked out revision 7.
  3065. If you’re like us, you’ll probably end up with a bunch of differ-
  3066. ent working copies in your work directory. To figure out where
  3067. a working copy came from, use the svn info command:
  3068. work > svn info sesame
  3069. Path: sesame
  3070. URL: svn://olio/sesame/trunk
  3071. Repository UUID: d6959e13-a0e3-0310-8d55-a8c2e0b5e323
  3072. Revision: 34
  3073. Node Kind: directory
  3074. Schedule: normal
  3075. Last Changed Author: mike
  3076. Last Changed Rev: 7
  3077. Last Changed Date: 2004-10-05 13:07:15 -0700 (Tue 5 Oct 2004)
  3078. The important bit here is the URL on the second line. Sub-
  3079. version is telling us that the sesame directory on the local
  3080. machine originally came from svn://olio/sesame/trunk/ .
  3081. K EEPING U P - TO -D ATE 64
  3082. 6.2 Keeping Up-to-Date
  3083. If you’re not the only person working on a project, the chances
  3084. are pretty good that the repository is being updated by others
  3085. even as you are working. It’s a good idea to incorporate their
  3086. changes into your working copy fairly frequently; the longer
  3087. you leave it, the bigger the hassle of fixing any conflicts. 1 We
  3088. typically update our working copies every hour or so through-
  3089. out the day.
  3090. The svn update command is used within a working copy and
  3091. brings all the files in the directory (and its subdirectories) up-
  3092. to-date with the repository. Files and directories added to
  3093. the repository will be added to the working copy, and files
  3094. and directories removed from the repository will be removed
  3095. from the working copy. The following command updates the
  3096. working copy of the Sesame project:
  3097. work > cd sesame
  3098. sesame > svn update
  3099. You can choose to update just part of your checked-out tree.
  3100. If you issue the command in a subdirectory of a project, then
  3101. only files at or below that point will be updated. This may
  3102. save time, but it also leaves you exposed to working on an
  3103. inconsistent set of files.
  3104. You can also specify one or more individual files or directories
  3105. to update by naming them on the command line:
  3106. main > svn update build.xml src/ test/
  3107. During the update process, Subversion will show the status
  3108. of each file with significant activity. For example, the follow-
  3109. ing is the logging produced when updating the directory tree
  3110. containing the Subversion source code itself:
  3111. subversion > svn update
  3112. U include/svn repos.h
  3113. G libsvn client/status.c
  3114. A bindings/java/javahl/build
  3115. A bindings/java/javahl/build/build.xml
  3116. U bindings/swig/perl/native/Repos.pm
  3117. 1 Frequent merges serve another purpose. If another developer is going
  3118. down the wrong path, or if their changes are promising to be problematic in
  3119. the long term, you’ll find out sooner if you merge often. The earlier you get
  3120. this feedback, the less the pain involved in fixing the problem.
  3121. K EEPING U P - TO -D ATE 65
  3122. U bindings/swig/perl/native/Base.pm
  3123. A bindings/swig/perl/native/Makefile.PL.in
  3124. UU bindings/swig/perl/native/h2i.pl
  3125. U bindings/swig/perl/native/Ra.pm
  3126. D bindings/swig/perl/native/Makefile.PL
  3127. U bindings/swig/perl/native
  3128. U clients/cmdline/propedit-cmd.c
  3129. A po/pt BR.po
  3130. U po/zh TW.po
  3131. Updated to revision 11141.
  3132. Subversion prints the following characters to indicate what
  3133. has happened to each file or directory:
  3134. • A indicates Subversion has added a file to your working
  3135. copy in order to bring it up-to-date with a new file in the
  3136. repository.
  3137. • U shows a file that was out-of-date in your working copy
  3138. because a newer version was checked into the repository.
  3139. Subversion has updated your working copy of the file to
  3140. the new version.
  3141. • D indicates that Subversion has removed a file from your
  3142. working copy because the file has been deleted from the
  3143. repository.
  3144. • G shows a file that was out-of-date in your working copy,
  3145. which you had modified locally. Subversion successfully
  3146. merged the changes from the repository with your local
  3147. modifications.
  3148. • C shows a file that was out-of-date in your working copy,
  3149. which you had also modified locally. Subversion tried to
  3150. merge the changes from the repository with your local
  3151. modifications but encountered a conflict. You’ll need to
  3152. resolve the conflict before you can check in.
  3153. You might have noticed the line Subversion printed for h2i.pl
  3154. starts with UU and that the line for the bindings/swig/perl/native
  3155. directory has a space followed by a U . These aren’t typeset-
  3156. ting errors—Subversion is actually printing two columns of
  3157. information. The second column indicates changes to a file’s
  3158. properties, rather than to a file itself. Subversion properties
  3159. are discussed in more detail in Section 6.4, Properties, on the
  3160. following page.
  3161. A DDING F ILES AND D IRECTORIES 66
  3162. 6.3 Adding Files and Directories
  3163. The svn add command tells Subversion to add files and direc-
  3164. tories to the repository. When you add a directory, Subversion
  3165. automatically adds all the files within the directory and its
  3166. subdirectories, unless you specify the --non-recursive option:
  3167. sesame > mkdir timelib
  3168. sesame > cd timelib
  3169. timelib > # ..create and edit Time.java..#
  3170. timelib > cd ..
  3171. sesame > svn add timelib
  3172. A timelib
  3173. A timelib/Time.java
  3174. Note that at this point Subversion has just remembered the
  3175. names of the files you’d like to add to the repository; it hasn’t
  3176. actually added the files or made the change visible to anyone
  3177. else. You need to use svn commit to commit the new files into
  3178. the repository.
  3179. Subversion stores all files in the repository in a binary format,
  3180. using an efficient binary-delta algorithm to figure out what
  3181. has changed between revisions. This works great for text as
  3182. well as real binaries, so you don’t need to tell Subversion if a
  3183. file is binary when adding it to the repository.
  3184. Subversion treats text and binary files differently as we’ll see
  3185. in Section 6.4, Setting Mime Types, on page 73, which means
  3186. it’s sometimes worth checking that Subversion detected the
  3187. “binaryness” of a file correctly. When you add a file that Sub-
  3188. version thinks is binary, it’ll automatically set the svn:mime-
  3189. type property to application/octet-stream . The next sec-
  3190. tion covers properties in detail.
  3191. 6.4 Properties
  3192. Whilst we are mostly concerned with Subversion storing file
  3193. contents it can also store metadata associated with each file
  3194. (and directory) in the repository. 2 Subversion calls this meta-
  3195. data properties and manages changes to properties in the properties
  3196. same way as a file’s contents. Properties can be changed
  3197. 2 Subversion actually stores properties on revisions too. For example, the
  3198. log message associated with a particular commit is stored in a text property
  3199. on the revision.
  3200. P ROPERTIES 67
  3201. by different users and are updated in each working directory
  3202. when users run svn update . This can lead to merges and con-
  3203. flicts just like those encountered when changing file contents.
  3204. Properties are named using simple strings and can contain
  3205. any content that a normal file could contain—this specifically
  3206. includes binary content. Properties can be used to associate
  3207. extra data with a file, in whatever format you’d like. For exam-
  3208. ple, a Java source file could have an associated Reviewer prop-
  3209. erty that tells you who last performed a code review on that
  3210. file. A repository storing music files might have a short sam-
  3211. ple of each file stored in a binary property, rather than storing
  3212. the samples in files alongside the main file and using some
  3213. naming convention to link the two.
  3214. You can use Subversion’s properties however you like, but you
  3215. should be aware of a few special properties. These properties
  3216. change the way Subversion behaves when it encounters a file,
  3217. and all start with the svn: prefix.
  3218. Manipulating Properties
  3219. To set a property on a file, use the svn propset command:
  3220. sesame > svn propset checked-by "Mike Mason" Number.txt
  3221. property ' checked-by ' set on ' Number.txt '
  3222. sesame > svn status
  3223. M Number.txt
  3224. Here we’re setting the checked-by property on Number.txt to
  3225. value Mike Mason . Maybe our project’s release procedure
  3226. requires each of our files to have this property set so that
  3227. we can figure out who approved the contents. It’s important
  3228. to note that we’re making a change to the file’s properties,
  3229. which Subversion handles in the same way as a change to
  3230. the contents. Subversion records the file in our local copy as
  3231. modified, and we must commit the change to the repository if
  3232. we want anyone else to see it.
  3233. To edit a property, use svn propedit . This will bring up an editor
  3234. so that you can easily manage multiline text properties:
  3235. sesame > svn propedit checked-by Number.txt
  3236. # .. edit the property, then save and quit the editor ..
  3237. Set new value for property ' checked-by ' on ' Number.txt '
  3238. P ROPERTIES 68
  3239. The svn proplist and svn propget commands list all the properties
  3240. for a file and print out the current value of a property:
  3241. sesame > svn proplist Number.txt
  3242. Properties on ' Number.txt ' :
  3243. checked-by
  3244. sesame > svn propget checked-by Number.txt
  3245. Mike
  3246. Ian
  3247. Finally, you can use svn propdel to delete a property entirely.
  3248. Remember that the property is not lost forever—Subversion
  3249. tracks changes to properties just like changes to files, so you
  3250. can always go back in time and find any previous revision.
  3251. Keyword Expansion
  3252. If you’ve used another version control system, you may be
  3253. familiar with keyword expansion. This basically means get- keyword expansion
  3254. ting your version control system to modify your working copy
  3255. files as it checks them out and updates them so it can fill
  3256. in useful information for you. Each of these useful pieces of
  3257. information is represented by a keyword, usually surrounded keyword
  3258. by dollar signs, which you put strategically inside the files
  3259. you’re storing in version control. Keywords in Subversion
  3260. are stored unexpanded in the repository to make diffing and
  3261. merging a little easier.
  3262. We really recommend not using this Subversion feature, since
  3263. it can get you into lots of bother. We tried to make this page of
  3264. the book perforated so readers could tear it out and forget all
  3265. about keyword expansion, but our printers said it’d add too
  3266. much to the production costs....
  3267. To switch on keyword expansion, you need to set svn:keywords
  3268. on each file containing keywords. The property value should
  3269. list the keywords you’d like to expand for that particular file.
  3270. Subversion offers the following keywords:
  3271. $LastChangedDate$
  3272. Also abbreviated $Date$ , this keyword describes the last
  3273. time the file was committed to the repository. It expands
  3274. to a string such as 2004-09-26 18:11:03 -0700 (Sun, 26 Sep
  3275. 2004) .
  3276. $LastChangedRevision$
  3277. Also known as $Revision$ or $Rev$ , this keyword expands
  3278. P ROPERTIES 69
  3279. to the revision number the last time the file was commit-
  3280. ted to the repository.
  3281. $LastChangedBy$
  3282. Also abbreviated $Author$ , this keyword expands to the
  3283. name of the last user to have committed the file.
  3284. $HeadURL$
  3285. Also abbreviated $URL$ , this keyword expands to the full
  3286. URL of the file in the repository.
  3287. $Id$
  3288. This keyword expands to a short summary of the other
  3289. keywords, suitable for use in a file’s header section.
  3290. Let’s suppose we want to turn on keyword expansion for the
  3291. file Number.txt in our Sesame project. First we need to set
  3292. svn:keywords to the list of keywords we want to expand:
  3293. sesame > svn propset svn:keywords "HeadURL Id" Number.txt
  3294. property ' svn:keywords ' set on ' Number.txt '
  3295. Now edit Number.txt , and add two header lines with the key-
  3296. words we want expanded. Here we’re using $HeadURL$ and
  3297. $Id$ :
  3298. # $ HeadURL $
  3299. # $ Id $
  3300. ZERO
  3301. ichi
  3302. due
  3303. three
  3304. four
  3305. five
  3306. SIX
  3307. Now when we commit our changes, Subversion will notice that
  3308. we’ve asked for keyword expansion and modify the working
  3309. copy file. Each keyword is expanded to the latest information
  3310. Subversion has for the file:
  3311. sesame > svn commit -m "Added file keywords"
  3312. Sending Number.txt
  3313. Transmitting file data .
  3314. Committed revision 10.
  3315. sesame > cat Number.txt
  3316. # $ HeadURL: svn://olio/sesame/trunk/Number.txt $
  3317. # $ Id: Number.txt 10 2004-09-27 00:09:05Z mike $
  3318. ZERO
  3319. ichi
  3320. due
  3321. three
  3322. four
  3323. five
  3324. SIX
  3325. P ROPERTIES 70
  3326. Joe Asks...
  3327. Where’s the $Log$ keyword?
  3328. The keywords available in other version control sys-
  3329. tems, including CVS, often include a $ Log $ keyword.
  3330. This expands to list all of the log messages ever used
  3331. when committing changes to the file.
  3332. The practical problem is that all this extra stuff in the
  3333. source files gets in the way of reading the code.
  3334. We’ve seen source with two or three full pages of log
  3335. messages at the top of it, all before you get to a sin-
  3336. gle line of real code. Code is there to be read, and
  3337. anything that gets in the way of reading it is bad.
  3338. The philosophical problem is that you’re duplicating
  3339. information. Everything that can be inserted using
  3340. keywords is already stored within Subversion (it has to
  3341. be; otherwise Subversion couldn’t add it in the first
  3342. place). So why not just go to the horse’s mouth and
  3343. ask Subversion directly? That way you’ll get authorita-
  3344. tive information that’s guaranteed to be up-to-date.
  3345. The Subversion developers think the use of keywords,
  3346. especially anything that includes verbose possibly
  3347. long commit messages, should not be encouraged.
  3348. The result is they haven’t included a $Log$ keyword.
  3349. Keyword expansion really doesn’t have many bene-
  3350. fits, and it has several drawbacks. We recommend
  3351. not using it.
  3352. Whilst writing this book using the Pragmatic Program-
  3353. mers’ CVS-based system, Mike got caught out by the
  3354. expansion of $ Log $ and $ Id $ keywords and had to
  3355. switch it off for various chapters. The irony of using
  3356. CVS to write a Subversion book is not lost on him.
  3357. Editor’s note: Mike’s first edition of this book moved us
  3358. so deeply that we now do all book production using
  3359. Subversion.
  3360. P ROPERTIES 71
  3361. If you want to use keyword expansion on lots of files, say, all
  3362. your . java files, that’s a lot of property setting to remember
  3363. to do. Fortunately, Subversion has a feature called autoprops autoprops
  3364. that can set properties for you. Autoprops are explained in
  3365. detail in Section 6.4, Automatic Property Setting, on page 74.
  3366. Ignoring Certain Files
  3367. Most of the time your working copy will contain both files you
  3368. want under version control (source code, build scripts, graph-
  3369. ics for your application, and so on) and files that you’re happy
  3370. to have lying around but that don’t need to be stored in the
  3371. repository (temporary files, compiled code, and logfiles). Some
  3372. Subversion commands, notably svn status , svn add , and svn
  3373. import assume you’re interested in all the files in your working
  3374. copy. For example, svn status displays files that aren’t under
  3375. revision control in case you’ve forgotten to add them.
  3376. This extra output for files you really don’t want Subversion
  3377. to worry about can be annoying, or just plain dangerous (try
  3378. accidentally adding a few large temporary files to your repos-
  3379. itory, and see if your administrator comes running your way
  3380. with a big stick...). Fortunately, there’s an easy way to avoid
  3381. these problems: setting the svn:ignore property on a directory
  3382. specifies files you’d like Subversion to ignore.
  3383. Suppose we’ve been working on the time library in our Sesame
  3384. project. Ask Subversion for a status report, and we might see:
  3385. sesame > svn status timelib/
  3386. ? timelib/Time.class
  3387. ? timelib/Time.java.bak
  3388. M timelib/Time.java
  3389. Here we can see that we’ve changed Time.java but that Subver-
  3390. sion is also reporting on Time.class and Time.java.bak , neither of
  3391. which we actually care much about.
  3392. Use svn propedit svn:ignore timelib to bring up an editor for the
  3393. svn:ignore property on timelib . Enter the following contents:
  3394. *.class
  3395. *.bak
  3396. Now running svn status will ignore the . class and . bak files:
  3397. sesame > svn status
  3398. M timelib
  3399. M timelib/Time.java
  3400. P ROPERTIES 72
  3401. The timelib directory is listed as modified because we changed
  3402. its svn:ignore property.
  3403. Once your changes are committed, everyone will receive the
  3404. update to the svn:ignore property on timelib , causing Subver-
  3405. sion to ignore files in their working copies too. The svn:ignore
  3406. property applies only to the contents of a particular directory;
  3407. it doesn’t apply recursively to subdirectories.
  3408. Setting End-of-Line Style
  3409. Computer systems store text files using a combination of nor-
  3410. mal characters—the alphabet, numbers, and so on—and spe-
  3411. cial control characters.A combination of up to two of these control characters
  3412. are used to denote the end of a line of text. Depending on
  3413. the operating system, a computer will use a carriage-return
  3414. followed by a linefeed (CRLF, used by Windows computers),
  3415. simply a linefeed (LF, used by Unix and Mac OS X), or some-
  3416. times just a plain carriage-return (CR, used by older versions
  3417. of Mac OS).
  3418. If you’re storing files that should be usable on clients where
  3419. the line-ending style differs, you might be worried about how
  3420. line endings are stored. Subversion stores all files, whether
  3421. they’re text, graphics, compiled object code, or movies, using a
  3422. binary format in the repository. Unless you ask it to, Subver-
  3423. sion will never convert a file’s line-ending style, which might
  3424. mean you can ignore this section entirely.
  3425. If you do need to share files across different operating sys-
  3426. tems, you may already have noticed strange behavior. Open-
  3427. ing a Unix-formatted file using Windows’ Notepad, for exam-
  3428. ple, produces a file with lots of little squares in it instead of
  3429. newlines. Opening a Windows-formatted file in Unix might
  3430. result in lots of ˆM characters at the end of each line.
  3431. Whilst your editor or IDE might claim to be able to do conver-
  3432. sions for you, or to maintain the end-of-line style that exists
  3433. in a file when editing it, we often find the best thing is to stick
  3434. with native linefeed formats for each operating system. Sub-
  3435. version will do a conversion for you if you set the svn:eol-style
  3436. property to one of the values in the following table.
  3437. P ROPERTIES 73
  3438. native Subversion will translate end-of-line characters to
  3439. whatever the client operating system expects, and so
  3440. will use CRLF on Windows and LF on Unix.
  3441. CRLF Subversion will always use CRLF as an end-of-line
  3442. marker when it creates files in the working copy.
  3443. LF Subversion will always use LF as an end-of-line
  3444. marker on the client.
  3445. CR Subversion will always use CR as an end-of-line
  3446. marker on the client.
  3447. Setting Mime Types
  3448. Setting the svn:mime-type property on a file tells Subversion
  3449. exactly what type of content a file has. Mime types are used a
  3450. lot on the Internet—especially by e-mail and web servers—to
  3451. describe files that are being transferred around or sent as e-
  3452. mail attachments. For example, XML documents have a mime
  3453. type of text/xml, JPEG graphics are of type image/jpeg, and
  3454. Microsoft Word documents have an application/msword mime
  3455. type.
  3456. Setting svn:mime-type on a file is useful for a couple of reasons.
  3457. Firstly, Subversion assumes files that don’t have a text mime
  3458. type (starting text/) have binary contents, so it should treat
  3459. them differently on the client when merging and displaying
  3460. diffs. A diff on a binary file probably won’t be human readable,
  3461. so Subversion skips trying to show you a diff and just tells
  3462. you the file has changed. A merge on a binary file is equally
  3463. unlikely to work very well, so when you’re receiving changes
  3464. from the repository to a binary file you’ve changed in your
  3465. working directory, Subversion renames your version of the
  3466. file with a . orig file extension and replaces your file with new
  3467. data from the repository.
  3468. Secondly, when Subversion is being used with Apache as its
  3469. network server, you can browse the repository using a normal
  3470. web browser. When you click on a link, Subversion uses the
  3471. svn:mime-type property to figure out what the type of the file
  3472. P ROPERTIES 74
  3473. should be when Apache returns it to your web browser. This
  3474. helps avoid seeing a screenful of binary data when you click
  3475. on a zip file in the repository.
  3476. Executable Flags
  3477. Some operating systems, most notably Unix, treat simple data
  3478. files differently than program files. To be able to run a pro-
  3479. gram on Unix it must have its “execute bit” set. If you’re
  3480. checking executable files or scripts into your repository, users
  3481. checking the files out won’t automatically get the execute bit
  3482. set. Setting the svn:executable property on a file means that
  3483. Subversion will set the execute bit for you whenever that file is
  3484. checked out. It doesn’t matter what the property is set to—if
  3485. it’s set at all, Subversion will set the execute bit.
  3486. On Windows, all files are executable, so you probably won’t
  3487. have to worry about this.
  3488. Automatic Property Setting
  3489. Subversion properties are very useful, but unfortunately they
  3490. need to be applied to each file or directory we’re interested in.
  3491. It’s easy to forget to set a property, and that might lead to
  3492. problems later.
  3493. Fortunately, Subversion includes a feature called autoprops
  3494. that allows you to specify properties that should be added
  3495. automatically. For example, you might decide that . java files
  3496. should have svn:keywords set to LastChangedDate and have
  3497. svn:eol-style set to native. You might also decide that whenever
  3498. someone adds a . gpg file to the repository it should have its
  3499. svn:mime-type set to application/pgp-encrypted.
  3500. Autoprops are a client-side setting, so if you want all your
  3501. developers to use them you’ll need some kind of policy for
  3502. making sure everyone is set up correctly. Unfortunately, Sub-
  3503. version doesn’t (yet) have the ability to “broadcast” configura-
  3504. tion settings from the server to clients, so you’ll have to do
  3505. this by hand.
  3506. Subversion stores your settings in a user-specific application
  3507. data folder. Where this actually is depends on whether you’re
  3508. using Unix or Windows. Section 5.1, svn+ssh, on page 57
  3509. C OPYING AND M OVING F ILES AND D IRECTORIES 75
  3510. covers finding the folder on Windows, and on Unix Subversion
  3511. uses
  3512. ˜ /.subversion .
  3513. Edit Subversion’s config file, and uncomment the following
  3514. line:
  3515. enable-auto-props = yes
  3516. Next scroll down a little, and uncomment the autoprops sec-
  3517. tion, adding whatever properties you’d like to set. To enable
  3518. a mime type on . gpg files and native end-of-line style on . java
  3519. files, you’d want a section like this:
  3520. [auto-props]
  3521. *.java = svn:eol-style=native
  3522. *.gpg = svn:mime-type=application/pgp-encrypted
  3523. 6.5 Copying and Moving Files and Directories
  3524. Subversion remembers every file and directory you ever com-
  3525. mit to the repository. This is great in most cases, but if
  3526. you make a mistake and add a file to the wrong directory,
  3527. or add it with the wrong name, you might want to move or
  3528. rename something. Modern programming includes a tech-
  3529. nique called refactoring, which often involves renaming a pro-
  3530. gram file when you come up with a better name for what that
  3531. file does or a more logical location for it in your project.
  3532. Fortunately, Subversion includes copy and move commands
  3533. allowing you to move and rename 3 files and directories. Sub-
  3534. version’s history tracking also knows about these operations,
  3535. so it’s much better to move a file using a Subversion command
  3536. than to move it yourself manually.
  3537. Copying a File
  3538. Whilst you could manually copy a file using Windows Explorer
  3539. or the Unix cp command, then add the new file to version
  3540. control, Subversion provides the svn copy command to allow
  3541. copying of files.
  3542. 3 A “rename” is just a “move” that happens to move a file to the same
  3543. directory. Unix gurus will probably be able to explain exactly why this makes
  3544. sense, but Subversion’s move and rename commands do the same thing.
  3545. C OPYING AND M OVING F ILES AND D IRECTORIES 76
  3546. Copying is the fundamental operation in Subversion upon
  3547. which everything else is based. Successive revisions of a file
  3548. are copies of the file with the contents changed. Branches are
  3549. copies of entire directories to a new location. Tags are copies
  3550. of a set of files that provide a snapshot of the repository at a
  3551. particular point in time.
  3552. Given that copying is such an epic activity, why would you
  3553. want to do it just to add another copy of a file to your reposi-
  3554. tory? Ultimately you might not, but when you copy a file using
  3555. svn copy , Subversion can track the history of both the original
  3556. and the copy back to the same source. In fact, Subversion
  3557. doesn’t even store a complete copy of the file; it just stores a
  3558. reference to where it was copied from. This might be useful if
  3559. you have a lot of big files that came from the same source and
  3560. have just been changed a little.
  3561. Enough evangelism. Using svn copy is a good idea, and it
  3562. works like this:
  3563. sesame > svn copy Number.txt Data.txt
  3564. A Data.txt
  3565. sesame > svn commit -m "Created example data file"
  3566. Adding Data.txt
  3567. Committed revision 24.
  3568. Copying a file or directory creates copies in your local working
  3569. directory and schedules them for addition to the repository. A
  3570. normal svn commit will check them in and complete the copy.
  3571. Since Subversion remembers the shared history of the files,
  3572. asking for the log for Data.txt also gives us the history for the
  3573. file Number.txt :
  3574. sesame > svn log Data.txt
  3575. ----------------------------------------------------------
  3576. r24 | mike | 2004-11-17 16:00:37 -0700 (Wed, 17 Nov 2004)
  3577. Created example data file
  3578. ----------------------------------------------------------
  3579. r11 | mike | 2004-10-04 21:05:37 -0600 (Mon, 04 Oct 2004)
  3580. Added Ian as reviewer
  3581. ----------------------------------------------------------
  3582. r10 | mike | 2004-09-26 18:09:05 -0600 (Sun, 26 Sep 2004)
  3583. Added file keywords
  3584. ----------------------------------------------------------
  3585. r7 | mike | 2004-09-08 23:22:06 -0600 (Wed, 08 Sep 2004)
  3586. One is Japanese, two Italian
  3587. ----------------------------------------------------------
  3588. C OPYING AND M OVING F ILES AND D IRECTORIES 77
  3589. Renaming a File
  3590. Let’s suppose that our Sesame project’s Time.java has actually
  3591. become more of a “clock” class and that we’d like to rename
  3592. it. We could rename the file in our working copy using Win-
  3593. dows Explorer or the Unix mv command, then use svn delete
  3594. to delete Time.java and svn add to add Clock.java , but that won’t
  3595. allow Subversion to track the file history for us.
  3596. First let’s examine the history for Time.java :
  3597. timelib > svn log Time.java
  3598. ----------------------------------------------------------
  3599. r14 | mike | 2004-10-04 21:12:48 -0600 (Mon, 04 Oct 2004)
  3600. Added freeze/unfreeze time methods
  3601. ----------------------------------------------------------
  3602. r13 | mike | 2004-10-04 21:10:50 -0600 (Mon, 04 Oct 2004)
  3603. Added getCurrentDate() method
  3604. ----------------------------------------------------------
  3605. Our most recent change to the file, adding methods for freez-
  3606. ing and unfreezing the system time, really means that our
  3607. class would be better named Clock . We know that things can
  3608. get out of hand if we don’t name our classes well, so we decide
  3609. to make the change sooner rather than later. Use the svn move
  3610. command to rename the file:
  3611. timelib > svn move Time.java Clock.java
  3612. A Clock.java
  3613. D Time.java
  3614. Here Subversion is letting us know that our “move” is really an
  3615. add and a delete. Someday Subversion may support renames
  3616. as first-class operations, but for the moment a Subversion
  3617. move is stored in the repository as a history-aware copy from
  3618. the old name to the new name and a delete of the old name.
  3619. Before you get all excited and commit the change, you should
  3620. crank up your unit tests and make sure you didn’t break
  3621. anything. At the very least, this Java file now won’t com-
  3622. pile because it contains a Time class in a file called Clock.java .
  3623. Open your favorite editor, and change the class name to Clock .
  3624. Then make sure your tests pass. You might need to change
  3625. code that references the class so it uses the new name too. 4
  3626. 4 Renaming a Java file requires quite a few steps, as does a rename in
  3627. other programming languages. Fortunately, some development environments
  3628. integrate directly with version control and will perform all the renames, adds,
  3629. and deletes for you automatically. Check your IDE for “refactoring support.”
  3630. C OPYING AND M OVING F ILES AND D IRECTORIES 78
  3631. What’s in a Name?
  3632. Subversion’s move command can also be referred to
  3633. as svn mv , rename , and ren . The svn copy command
  3634. can be shortened to svn cp if you’re into the whole
  3635. brevity thing.
  3636. While we’re on the subject of naming, it’s worth point-
  3637. ing out that naming things (classes, variables, meth-
  3638. ods, tests, data files, machines, processes, etc.) is
  3639. both really difficult and really important. Most peo-
  3640. ple don’t name stuff completely right the first time
  3641. around, but a well-named object helps avoid misun-
  3642. derstanding and speeds communication. Once you
  3643. realize there’s a better name for something, make the
  3644. effort to rename it. Your colleagues will thank you!
  3645. Once everything is working, commit your changes:
  3646. timelib > svn commit -m "Renamed Time to Clock"
  3647. Adding timelib/Clock.java
  3648. Deleting timelib/Time.java
  3649. Transmitting file data .
  3650. Committed revision 15.
  3651. Now if we view the history for the new Clock.java , we’ll see the
  3652. hard work has paid off, as Subversion follows the history of
  3653. the file across the rename:
  3654. timelib > svn log -v Clock.java
  3655. ----------------------------------------------------------
  3656. r15 | mike | 2004-10-04 21:13:40 -0600 (Mon, 04 Oct 2004)
  3657. Changed paths:
  3658. A /sesame/trunk/timelib/Clock.java
  3659. (from /sesame/trunk/timelib/Time.java:14)
  3660. D /sesame/trunk/timelib/Time.java
  3661. Renamed Time to Clock
  3662. ----------------------------------------------------------
  3663. r14 | mike | 2004-10-04 21:12:48 -0600 (Mon, 04 Oct 2004)
  3664. Changed paths:
  3665. M /sesame/trunk/timelib/Time.java
  3666. Added freeze/unfreeze time methods
  3667. ----------------------------------------------------------
  3668. r13 | mike | 2004-10-04 21:10:50 -0600 (Mon, 04 Oct 2004)
  3669. Changed paths:
  3670. M /sesame/trunk/timelib/Time.java
  3671. Added getCurrentDate() method
  3672. ----------------------------------------------------------
  3673. C OPYING AND M OVING F ILES AND D IRECTORIES 79
  3674. Renaming a Directory
  3675. With Subversion, directories are first-class objects just like
  3676. files. We can happily move or rename a directory using the
  3677. svn move command. Maybe the time library has had a few
  3678. extra utilities added to it and should be renamed util .
  3679. timelib > cd ..
  3680. sesame > svn move timelib util
  3681. A util
  3682. D timelib/Clock.java
  3683. D timelib
  3684. sesame > svn commit -m "Renamed timelib to util"
  3685. Deleting timelib
  3686. Adding util
  3687. Adding util/Clock.java
  3688. Committed revision 16.
  3689. Using Repository URLs
  3690. The svn move command we’ve seen so far has been running on
  3691. the working copy—moves, renames, adds, and deletes hap-
  3692. pen on the client before being committed to the server. This is
  3693. appropriate in most cases, because program code often needs
  3694. to be edited after being moved so that the code will still com-
  3695. pile and the tests will still pass.
  3696. Subversion also allows you to run these commands using a
  3697. repository URL, without the need for a working copy at all.
  3698. The changes are made instantly in the repository and require
  3699. a commit message. It might be appropriate to use this kind
  3700. of renaming if you have a lot of big files and don’t want to
  3701. move them around using a working copy. If you’re moving
  3702. code, however, think twice—you won’t be able to run your
  3703. tests without a working copy and might well break stuff.
  3704. To perform a repository-based rename, use two URLs like the
  3705. one initially used for a checkout. Let’s rename the util directory
  3706. common instead:
  3707. work > svn move -m "Renamed util to common" \
  3708. svn://olio/sesame/trunk/util \
  3709. svn://olio/sesame/trunk/common
  3710. Committed revision 17.
  3711. Back in the Sesame working copy, performing an update will
  3712. get the new common directory and delete the old util directory:
  3713. sesame > svn update
  3714. A common
  3715. A common/Clock.java
  3716. D util
  3717. Updated to revision 17.
  3718. S EEING W HAT H AS C HANGED 80
  3719. 6.6 Seeing What Has Changed
  3720. The svn diff command shows you the differences between ver-
  3721. sions of files. You can compare the version of a file in the
  3722. repository with your locally modified copy, and you can see
  3723. the differences between two versions of a file in the reposi-
  3724. tory.
  3725. Seeing What You’ve Changed in Your Working Copy
  3726. The simplest use of svn diff is to show you what you’ve changed
  3727. since you last updated your working copy from the repository:
  3728. common > svn diff Clock.java
  3729. Index: Clock.java
  3730. ==========================================================
  3731. --- Clock.java (revision 21)
  3732. +++ Clock.java (working copy)
  3733. @@ -20,6 +20,11 @@
  3734. frozen = true;
  3735. }
  3736. + public static void setTime(long time)
  3737. + {
  3738. + frozenTime = time;
  3739. + }
  3740. +
  3741. public static void unfreezeTime()
  3742. {
  3743. frozen = false;
  3744. Here we can see that we last updated to revision 21 of the file
  3745. Clock.java and that since then we added the setTime () method.
  3746. The basic svn diff command shows the changes between the file
  3747. in your workspace and the version to which you last updated.
  3748. Subversion can do this without contacting the server because
  3749. it stores a pristine, local copy of each file in your working
  3750. directory. If someone else has changed the file and committed
  3751. their changes into the repository, however, you won’t see them
  3752. in the diff. We’ll see how to handle this shortly.
  3753. Using Subversion Revision Identifiers
  3754. We looked at Subversion’s -r option when checking out and
  3755. updating, and it turns out referring to revisions is something
  3756. we’ll be doing a lot with Subversion. The option you supply
  3757. after -r is called a revision identifier. When you’re using a revision identifier
  3758. revision identifier, Subversion will accept revision numbers,
  3759. dates, and a few symbolic names, shown in the following
  3760. table.
  3761. S EEING W HAT H AS C HANGED 81
  3762. number A revision number within the repository, for
  3763. example 87 .
  3764. { date } A revision at the start of the date, for exam-
  3765. ple { "2004-09-26 13:35:06" }. The curly
  3766. braces tell Subversion you’re using a date,
  3767. and the quotes are required if you’re using
  3768. a date format containing spaces. Subversion
  3769. supports a variety of date formats, including
  3770. the basic HH:mm denoting a particular time
  3771. on today’s date.
  3772. HEAD The latest revision stored in the repository.
  3773. BASE The base revision of an item’s working copy—
  3774. this is the revision you last checked out or
  3775. updated to.
  3776. COMMITTED The last revision in which an item changed at
  3777. or before BASE.
  3778. PREV The revision just before COMMITTED.
  3779. Some commands accept a revision range, which is simply two revision range
  3780. revision identifiers separated by a colon. Revision ranges are
  3781. used to refer to two revisions separated over time.
  3782. The symbolic revisions BASE, COMMITTED, and PREV can be
  3783. used only to refer to an item in a working copy, because they
  3784. don’t make sense otherwise.
  3785. Figure 6.1 on the following page shows Subversion’s symbolic
  3786. revisions. In this scenario, you have revision 2 of Graph.java
  3787. in your working copy, and another developer checks in some
  3788. changes, creating revision 3 in the repository. Since you
  3789. haven’t updated your working copy, the BASE revision for
  3790. your copy of Graph.java is revision 2. The PREV revision is
  3791. one earlier than this, namely revision 1. HEAD is always the
  3792. newest version in the repository, in this case revision 3.
  3793. S EEING W HAT H AS C HANGED 82
  3794. K
  3795. L
  3796. MN
  3797. O
  3798. P
  3799. QR S
  3800. T
  3801. U
  3802. Q V Q
  3803. W
  3804. X
  3805. W
  3806. Y
  3807. W
  3808. Z
  3809. W
  3810. Y [ \
  3811. W
  3812. ]
  3813. ^
  3814. _ `a
  3815. \b c
  3816. d efg
  3817. h f ie
  3818. jkel
  3819. mn o p
  3820. q
  3821. r
  3822. q
  3823. s
  3824. t
  3825. u
  3826. Figure 6.1: Symbolic Revisions for a Working Copy File
  3827. Finding Differences between Versions
  3828. To compare two revisions of a particular file, use the -r option
  3829. to specify a revision range:
  3830. common > svn diff -r19:21 Clock.java
  3831. Index: Clock.java
  3832. ==========================================================
  3833. --- Clock.java (revision 19)
  3834. +++ Clock.java (revision 21)
  3835. @@ -1,9 +1,11 @@
  3836. package timelib;
  3837. +import java.util.Date;
  3838. +
  3839. public class Clock
  3840. {
  3841. - private boolean frozen = false;
  3842. - private long frozenTime = 0;
  3843. + private static boolean frozen = false;
  3844. + private static long frozenTime = 0;
  3845. public static Date getCurrentDate()
  3846. {
  3847. Here we used a file in the working copy to produce the diff,
  3848. even though a working copy doesn’t contain any historical
  3849. information. Under the hood, Subversion translates the file
  3850. path into a repository URL so it can retrieve the earlier ver-
  3851. sions as needed.
  3852. If you don’t have a working copy, you can diff directly against
  3853. the repository:
  3854. S EEING W HAT H AS C HANGED 83
  3855. common > svn diff -r19:21 \
  3856. svn://olio/sesame/trunk/common/Clock.java
  3857. Index: Clock.java
  3858. ==========================================================
  3859. --- Clock.java (revision 19)
  3860. +++ Clock.java (revision 21)
  3861. @@ -1,9 +1,11 @@
  3862. package timelib;
  3863. +import java.util.Date;
  3864. +
  3865. public class Clock
  3866. {
  3867. - private boolean frozen = false;
  3868. - private long frozenTime = 0;
  3869. + private static boolean frozen = false;
  3870. + private static long frozenTime = 0;
  3871. public static Date getCurrentDate()
  3872. {
  3873. Earlier we noted that a common gotcha with svn diff is that it
  3874. doesn’t show changes that have happened in the repository.
  3875. To get Subversion to compare your working copy against the
  3876. latest revision in the repository, use the HEAD keyword:
  3877. common > svn diff -r HEAD Clock.java
  3878. Index: Clock.java
  3879. ==========================================================
  3880. --- Clock.java (revision 26)
  3881. +++ Clock.java (working copy)
  3882. @@ -1,6 +1,7 @@
  3883. package timelib;
  3884. import java.util.Date;
  3885. +import java.util.Calendar;
  3886. public class Clock
  3887. {
  3888. @@ -24,6 +25,11 @@
  3889. frozenTime = System.currentTimeMillis();
  3890. }
  3891. + public static void switchToGMT()
  3892. + {
  3893. + frozenTime -= Calendar.getInstance()
  3894. + .get(Calendar.ZONE OFFSET);
  3895. + }
  3896. +
  3897. public static void setTime(long time)
  3898. {
  3899. frozenTime = time;
  3900. @@ -38,10 +44,5 @@
  3901. {
  3902. frozen = false;
  3903. }
  3904. -
  3905. - public static boolean isFrozen()
  3906. - {
  3907. - return frozen;
  3908. - }
  3909. }
  3910. S EEING W HAT H AS C HANGED 84
  3911. In our working copy of Clock we’ve added the switchToGMT ()
  3912. method. Meanwhile, another developer added the isFrozen ()
  3913. method and checked in. When we ask for a diff against HEAD,
  3914. we can see our local changes as additions and the other devel-
  3915. oper’s changes as deletions—if we check in Clock.java exactly
  3916. as it is in our working copy, we’ll undo the change adding
  3917. isFrozen ().
  3918. Fortunately, Subversion won’t let us do this—we’ll need to
  3919. update before checking in, which will add the isFrozen () method
  3920. to our working copy.
  3921. Sometimes it’s useful to see the most recent change to a file
  3922. before you start working on it. You can do this by using the
  3923. PREV symbolic revision:
  3924. common > svn diff -r PREV:BASE Clock.java
  3925. Index: Clock.java
  3926. ==========================================================
  3927. --- Clock.java (revision 22)
  3928. +++ Clock.java (working copy)
  3929. @@ -26,6 +26,11 @@
  3930. frozenTime = time;
  3931. }
  3932. + public static void setTime(Date date)
  3933. + {
  3934. + frozenTime = date.getTime();
  3935. + }
  3936. +
  3937. public static void unfreezeTime()
  3938. {
  3939. frozen = false;
  3940. Here Subversion is showing us that the previous change to
  3941. Clock.java was the addition of the setTime () method.
  3942. Subversion’s diff command can also examine changes between
  3943. different development branches or show you what changed
  3944. since a certain version of the code was tagged. Chapter 9,
  3945. Using Tags and Branches, on page 111 covers diffing and
  3946. merging across tags and branches.
  3947. Diffs and Patch
  3948. If you’ve spent any time in the open-source community, you’ll
  3949. have come across folks flinging source patches around the
  3950. world. These patches are based on the same diffs that Sub-
  3951. version generates, which turns out to be remarkably useful.
  3952. S EEING W HAT H AS C HANGED 85
  3953. Perhaps you’re working with an open-source library, and you
  3954. need to make a change. The library is on CodeHaus, 5 which
  3955. among other things provides free Subversion repositories for
  3956. open-source developers. As a member of the public, Code-
  3957. Haus lets you check the source code of the project out of the
  3958. repository, but because you aren’t on the list of developers,
  3959. you can’t check changes back in.
  3960. This is where patches come in. Simply ask Subversion to give
  3961. you a list of all the changes you’ve made (using svn diff ). E-
  3962. mail the file containing the diff output to the library’s main-
  3963. tainer, who will be able to use the patch program to apply
  3964. those patches to their source.
  3965. The following command creates a file called mychanges.patch
  3966. containing all the changes that have been made to files in or
  3967. below the directory oslibrary :
  3968. oslibrary > svn diff > mychanges.patch
  3969. You can then e-mail this file to the maintainer, who can apply
  3970. the patch to his or her version of the source using (surprise!)
  3971. the patch command:
  3972. oslibrary > patch -p0 -i mychanges.patch
  3973. Correct use of patch is a mystic art that probably cannot be
  3974. taught in a book this size, but here’s a rough breakdown of
  3975. what’s going on:
  3976. • The patch is being applied in oslibrary , the same directory
  3977. in which it was created.
  3978. • The -p0 option is instructing patch to strip zero direct-
  3979. ories from files named in the patch before applying it. If
  3980. you don’t include this option, patch will complain about
  3981. being unable to find the right files.
  3982. • The -i option is telling patch to use mychanges.patch as
  3983. input.
  3984. patch is pretty clever and can usually ignore “garbage” text
  3985. surrounding a patch, so you can save an e-mail containing
  3986. someone’s changes and apply the whole thing. What most
  3987. 5 http://codehaus.org/
  3988. H ANDLING M ERGE C ONFLICTS 86
  3989. people forget is the magic -p0 that lets patch find the right
  3990. files.
  3991. Patches are useful outside the context of open source. You
  3992. can use patches to send suggested changes to other members
  3993. of your project team. If your clients have your source code,
  3994. you can even use patches to distribute those urgent three-
  3995. in-the-morning fixes that seem to crop up from time to time.
  3996. Just remember to check in the changes you’ve made into the
  3997. repository as well.
  3998. 6.7 Handling Merge Conflicts
  3999. Subversion doesn’t lock files: 6 everyone in a project can edit
  4000. any file at any time. This feature of Subversion seems to give
  4001. some people sleepless nights. “What stops two people editing
  4002. the same file at the same time?” they ask. “Won’t work get
  4003. lost?”
  4004. The simple answers are “nothing, and no.” If they edit differ-
  4005. ent parts of that same file, Subversion will happily merge the
  4006. two changes together, and life carries on.
  4007. Sometimes, however, two people edit the same parts of the
  4008. same file (although it happens far more rarely than you might
  4009. first think). When that happens, Subversion cannot automat-
  4010. ically perform a merge: it wouldn’t know whose changes to
  4011. keep. In these cases, Subversion declares that the two ver-
  4012. sions of a file conflict and passes the matter back to a human
  4013. (you) to solve.
  4014. To illustrate a conflict, we’ll use our old friend Numbers.txt
  4015. again. This time, we’ll check it out into two separate work-
  4016. ing directories: 7
  4017. 6 At least, Subversion doesn’t lock files by default. Subversion 1.2 sup-
  4018. ports optional locking, sometimes known as reserved checkouts, which we
  4019. discuss in Chapter 7, File Locking and Binary Files, on page 99.
  4020. 7 Eagle-eyed readers will notice these examples take us back to revision 1
  4021. of the repository, when we had only two files and no timelib directory. This was
  4022. possible through some Subversion administration magic—we made a backup
  4023. of our repository including just revision 1 and loaded the backup into a new
  4024. repository. Section A.6, Backing Up Your Repository, on page 170 covers this
  4025. magic in detail.
  4026. H ANDLING M ERGE C ONFLICTS 87
  4027. work > svn checkout svn://olio/sesame/trunk sesame1
  4028. A sesame1/Number.txt
  4029. A sesame1/Day.txt
  4030. Checked out revision 1.
  4031. work > svn checkout svn://olio/sesame/trunk sesame2
  4032. A sesame2/Number.txt
  4033. A sesame2/Day.txt
  4034. Checked out revision 1.
  4035. In the sesame1 directory, we’ll change the first line of Num-
  4036. bers.txt so that it contains the following:
  4037. ZERO
  4038. one
  4039. two
  4040. We’ll check this change in:
  4041. sesame1 > svn commit -m "Made zero uppercase"
  4042. Sending Number.txt
  4043. Transmitting file data .
  4044. Committed revision 2.
  4045. Now we’ll bop over to sesame2 . Remember that we want to
  4046. create a merge conflict, so we’ll pretend that we don’t know
  4047. that someone changed the file we’re about to work on. In
  4048. sesame2 we’ll alter Numbers.txt , changing the first line to read
  4049. Zero :
  4050. sesame2 > svn commit -m "Capitalized ' Zero ' "
  4051. Sending Number.txt
  4052. Transmitting file data .svn: Commit failed (details follow):
  4053. svn: Out of date: ' /sesame/trunk/Number.txt ' in transaction ' 9 '
  4054. So far, so good. Subversion has detected that Number.txt is
  4055. out-of-date, so we do an svn update :
  4056. sesame2 > svn update
  4057. C Number.txt
  4058. Updated to revision 2.
  4059. Subversion marks the file with a C to let us know there’s a
  4060. conflict in the merge, and it’s our job to fix it.
  4061. Fixing a Conflict
  4062. The first question to be answered when fixing a merge conflict
  4063. is, “why did this happen in the first place?” This isn’t an issue
  4064. of blame, but it often is one of communication. What are two
  4065. developers doing editing the same lines of code in the same
  4066. file at the same time?
  4067. Sometimes there’s a good reason. Perhaps they both discover
  4068. the same bug at the same time, and both decide to fix it. Or
  4069. H ANDLING M ERGE C ONFLICTS 88
  4070. perhaps they’re both adding functionality which uses a com-
  4071. mon data structure, and both add fields to that structure at
  4072. the same time. These are reasonable changes, and they might
  4073. lead to a conflict.
  4074. But often conflicts happen because folks aren’t doing a good
  4075. job of letting others know what’s going on. So, we strongly
  4076. recommend that if you come across a merge conflict without a
  4077. sensible explanation you make a point of mentioning it at the
  4078. next team meeting. The goal here is to discuss the cause and
  4079. to come up with ways of improving communication so that
  4080. the chances of something similar happening in the future are
  4081. reduced.
  4082. Now that’s all fine, but you’re still left with a conflict. Subver-
  4083. sion marks these in the local copy of the file using sequences
  4084. of <<< and >>> characters:
  4085. <<<<<<< .mine
  4086. Zero
  4087. =======
  4088. ZERO
  4089. >>>>>>> .r2
  4090. one
  4091. two
  4092. Number.txt
  4093. Here we can see our change, Zero , helpfully labeled mine ,
  4094. and the change from the repository, ZERO , with the hint that
  4095. it came from revision 2.
  4096. We now have to decide how to fix this. In the real world, this
  4097. involves a negotiation with the other person who made the
  4098. change; simply blowing their hard work away and replacing it
  4099. with yours is a great way to jeopardize your invitation to the
  4100. next project picnic.
  4101. The resolution could go a number of ways:
  4102. • You decide to scrap your changes and use the version
  4103. in the repository. All you have to do is svn revert your
  4104. changes—Subversion will back out your change and use
  4105. the version of the file from the repository:
  4106. sesame2 > svn revert Number.txt
  4107. Reverted ' Number.txt '
  4108. sesame2 > svn update Number.txt
  4109. At revision 2.
  4110. • You decide to keep your changes and lose those in the
  4111. repository. Subversion saves a copy of each version of
  4112. H ANDLING M ERGE C ONFLICTS 89
  4113. Conflicts and Curly Brace Wars
  4114. Suppose two developers like to lay their code out dif-
  4115. ferently. Fred likes his code indented with two spaces
  4116. and likes all his curly braces to sit on the same line as
  4117. a declaration. His code would look like this:
  4118. for (i = 0; i < max; i++) {
  4119. if (values[i] < 0) {
  4120. process(values[i]);
  4121. }
  4122. }
  4123. Wilma, however, likes her code indented with four
  4124. spaces and doesn’t appreciated the cluttered look
  4125. of Fred’s code. She puts her curly braces on a dif-
  4126. ferent line to declarations. If Wilma were writing the
  4127. same piece of code, it would look like this:
  4128. for (i = 0; i < max; i++)
  4129. {
  4130. if (values[i] < 0)
  4131. {
  4132. process(values[i]);
  4133. }
  4134. }
  4135. One day Fred is editing some of Wilma’s code and
  4136. decides he dislikes the indentation. He tells his editor
  4137. to reindent the whole file to two-character offsets and
  4138. to put the curly braces where he likes them. He then
  4139. makes a small change to one line, saves the file, and
  4140. commits the changes to the repository.
  4141. The problem is that as far as Subversion is concerned,
  4142. every line in the file has changed. If Wilma (or any-
  4143. one else) changes something, they’ll get a merge
  4144. conflict, because Fred’s change to the indentation
  4145. means that the corresponding line in the repository is
  4146. different from the line in Wilma’s workspace.
  4147. Now you can get around this: you can tell Sub-
  4148. version to use an external diff program that ignores
  4149. changes in whitespace when determining the dif-
  4150. ference between files, for example. However, this
  4151. doesn’t get around the fact that you have changed
  4152. the whole file and that folks with local changes to that
  4153. file will get conflicts the next time they update.
  4154. H ANDLING M ERGE C ONFLICTS 90
  4155. Conflicts and Curly Brace Wars (continued)
  4156. The rule is simple: don’t wantonly change the layout
  4157. of a shared file. If you absolutely must change the
  4158. indentation, first make sure no one else on the team
  4159. has made local changes to the file. Then change the
  4160. layout and check in the changed file, without chang-
  4161. ing anything else. Then tell folks to update, so they’ll
  4162. all be working on the new version. This’ll cut down on
  4163. the number of conflicts people experience, and will
  4164. reduce the amount of hate mail you receive.
  4165. the file when a conflict arises, with extensions . mine , . r1 ,
  4166. . r2 , etc. Copy your version of the file, the one with the
  4167. . mine extension, over the original, and tell Subversion
  4168. you’ve fixed the conflict:
  4169. sesame2 > cp Number.txt.mine Number.txt
  4170. sesame2 > svn resolved Number.txt
  4171. Resolved conflicted state of ' Number.txt '
  4172. Subversion will clean up all the various . mine and . r2 files
  4173. when you tell it you’ve resolved the conflict.
  4174. • If you decide you want to use parts of both versions, then
  4175. you’ll need to do some manual editing. Simply edit the
  4176. file that contains the conflict markers, making it look the
  4177. way you want. Be sure to remove the conflict markers.
  4178. For example, in our case we might decide that the first
  4179. line shouldn’t be Zero or ZERO but Empty :
  4180. <<<<<<< .mine Empty
  4181. Zero one
  4182. ======= becomes = > two
  4183. ZERO
  4184. >>>>>>> .r2
  4185. one
  4186. two
  4187. Subversion won’t let you commit a file that is still in a con-
  4188. flicted state. 8 In order to let Subversion know you’ve fixed a
  4189. 8 This is probably reassuring for folks who have big projects and lots of
  4190. files—“What if I don’t see a C next to a file as it scrolls past my screen?” is
  4191. a common question. If you miss the conflict, and by some chance having
  4192. a bunch of <<< characters in your code doesn’t horribly break your build,
  4193. C OMMITTING C HANGES 91
  4194. conflict, use the svn resolved command:
  4195. sesame2 > svn resolved Number.txt
  4196. Resolved conflicted state of ' Number.txt '
  4197. 6.8 Committing Changes
  4198. After you make a set of changes (and, in an ideal world, after
  4199. you’ve tested they don’t break anything), you’ll want to store
  4200. them in the repository. We’ve already done this many times in
  4201. this book; you simply use svn commit .
  4202. However, we’d like to recommend a slightly more complex
  4203. sequence of commands to follow at every commit:
  4204. myproject > svn update
  4205. myproject > #... resolve conflicts ...
  4206. myproject > #... run tests ...
  4207. myproject > svn commit -m "check in message"
  4208. The first line brings our local workspace into step with the
  4209. current state of the repository. This is important; although
  4210. our code may work fine with the project files as they were
  4211. when we last updated our workspace, other folks may have
  4212. changed things that break our new code. After updating, we
  4213. might have to resolve conflicts.
  4214. Even if there are no conflicts, we should compile and test our
  4215. code again, fixing any problems that arise. This ensures that
  4216. when we do check in we’ll be checking in something that actu-
  4217. ally works in the larger project context. You’ll need a fast test
  4218. suite for this to work—developers won’t want to hang around
  4219. more than a few minutes while their tests run.
  4220. Once we’ve checked that everything is correct, we can commit
  4221. our changes, using the -m option to add a meaningful mes-
  4222. sage. If you omit the -m option, Subversion will bring up an
  4223. editor and let you type in a longer comment.
  4224. 6.9 Examining Change History
  4225. You can look at the log messages that you and your team have
  4226. entered using the svn log command:
  4227. Subversion will complain about any files remaining unresolved when you try
  4228. to commit.
  4229. E XAMINING C HANGE H ISTORY 92
  4230. Meaningful Log Messages
  4231. What makes a good log message? To answer this
  4232. question, imagine you are another developer com-
  4233. ing to this code base a couple of years from now. You
  4234. are puzzling over a particular piece of the system, try-
  4235. ing to work out why something is done a certain way.
  4236. You notice that changes were made in this area, and
  4237. hope that the log messages will give you hints as to
  4238. the motivation for the particular design chosen.
  4239. Now, back to the present. What little breadcrumbs
  4240. can you drop into the log messages today to help
  4241. your fellow developers a couple of years from now?
  4242. Part of the answer comes from realizing that Subver-
  4243. sion already stores the actual details of the changes
  4244. you made to the code. There’s no point in writing
  4245. a log message that says “changed timeout to 42.”
  4246. when a simple diff could show that setTimeout(10)
  4247. became setTimeout(42) . Instead, use the log mes-
  4248. sage to answer the question “why?”:
  4249. If the round-robin DNS returns a machine that
  4250. is unavailable, the connect() method attempts
  4251. to retry for 30mS. In these circumstances our
  4252. timeout was too low.
  4253. If a change is being made in response to a bug
  4254. report, include the tracking number in the log mes-
  4255. sage: the description of the problem is already in
  4256. the bug database and doesn’t need to be repeated
  4257. here.
  4258. E XAMINING C HANGE H ISTORY 93
  4259. sesame > svn log Number.txt
  4260. ---------------------------------------------------------
  4261. r4 | mike | 2004-09-08 22:45:16 -0600 (Wed, 08 Sep 2004)
  4262. Make ' six ' important
  4263. ---------------------------------------------------------
  4264. r3 | mike | 2004-09-08 22:05:32 -0600 (Wed, 08 Sep 2004)
  4265. Customer wants more numbers
  4266. ---------------------------------------------------------
  4267. r1 | mike | 2004-09-08 21:50:13 -0600 (Wed, 08 Sep 2004)
  4268. ---------------------------------------------------------
  4269. If you’d just like to get a general idea of what has changed
  4270. recently, you can ask Subversion for a log of everything that
  4271. happened in a particular directory. Doing this at the top of a
  4272. large tree might produce quite a bit of output, so use a pipe 9
  4273. through the more command to paginate Subversion’s output:
  4274. work > svn log sesame | more
  4275. Subversion will accept a -r option to specify which revisions
  4276. you’re interested in. Using a single revision number will show
  4277. just what changed in that revision, and using a revision range
  4278. will show a section of history:
  4279. sesame > svn log -r 19:24 Clock.java
  4280. ----------------------------------------------------------
  4281. r19 | mike | 2004-10-04 21:47:09 -0600 (Mon, 04 Oct 2004)
  4282. Renamed util to common
  4283. ----------------------------------------------------------
  4284. r21 | mike | 2004-10-09 16:33:00 -0600 (Sat, 09 Oct 2004)
  4285. Fixed compilation problems
  4286. ----------------------------------------------------------
  4287. r22 | dave | 2004-10-09 16:48:23 -0600 (Sat, 09 Oct 2004)
  4288. Added setTime() method
  4289. ----------------------------------------------------------
  4290. r23 | ian | 2004-10-09 17:00:23 -0600 (Sat, 09 Oct 2004)
  4291. Added setTime() method taking a Date
  4292. ----------------------------------------------------------
  4293. r24 | dave | 2004-10-10 18:07:08 -0600 (Sun, 10 Oct 2004)
  4294. Added Log class
  4295. ----------------------------------------------------------
  4296. Here we asked to see revisions 19 through 24 of Clock.java . We
  4297. didn’t actually change Clock.java in revision 20 of the reposi-
  4298. tory, which is why we’re missing a revision here. Also notice
  4299. how Subversion printed the revisions with the newest at the
  4300. bottom—retrieving a log without using the -r option prints
  4301. the newest revision at the top.
  4302. The final message says “Added Log class” but is being shown
  4303. as part of the history for Clock.java . This looks a bit strange,
  4304. 9 The pipe character is Shift+\ on a U.S. keyboard.
  4305. E XAMINING C HANGE H ISTORY 94
  4306. so let’s get more information using the -v (verbose) option:
  4307. common > svn log -r 24 -v Clock.java
  4308. ----------------------------------------------------------
  4309. r24 | dave | 2004-10-10 18:07:08 -0600 (Sun, 10 Oct 2004)
  4310. Changed paths:
  4311. M /sesame/trunk/common/Clock.java
  4312. A /sesame/trunk/common/Log.java
  4313. Added Log class
  4314. ----------------------------------------------------------
  4315. Now that Subversion is being more talkative, we can see that
  4316. revision 24 added Log.java and also made a change to the
  4317. file Clock.java . In this case, the new Log class depends on
  4318. some extra functionality in Clock . When Dave committed his
  4319. change, he committed both the files at once, since they make
  4320. logical sense together.
  4321. Subversion’s ability to track changes to multiple files in a sin-
  4322. gle commit is extremely powerful. If you’re browsing history
  4323. for a particular file and see a change you’re interested in,
  4324. adding the -v option to svn log will show all the files that were
  4325. changed in that particular commit. This comes in handy when
  4326. tracking down what needed to be changed for a particular bug
  4327. fix, for example.
  4328. Line-by-Line History
  4329. The svn blame 10 command displays the contents of one or
  4330. more files. For each line in each file it shows the latest revi-
  4331. sion number to change that line, along with the author of the
  4332. change:
  4333. sesame > svn blame Number.txt
  4334. 10 mike # $ HeadURL $
  4335. 10 mike # $ Id $
  4336. 5 dave ZERO
  4337. 7 mike ichi
  4338. 7 mike due
  4339. 1 mike three
  4340. 1 mike four
  4341. 3 andy five
  4342. 4 ian SIX
  4343. This is a great tool when you’re involved in software archeol-
  4344. ogy; you can quickly find the patterns to changes and identify
  4345. exactly which lines were changed by a particular revision.
  4346. 10 It’s called blame because it’s often used to determine who is responsible
  4347. for a particular piece of code (or a particular bug!). svn blame , praise , annotate
  4348. and ann all mean the same thing.
  4349. R EMOVING A C HANGE 95
  4350. svn blame accepts a -r option specifying a revision or revision
  4351. range to use when displaying the file. This stops Subversion
  4352. from examining the entire history of the file when displaying
  4353. annotations.
  4354. 6.10 Removing a Change
  4355. Sometimes we make changes to code that we’d rather forget.
  4356. If the change is a set of changes in our local workspace that
  4357. have yet to be checked in, then we can simply throw the
  4358. changes away using svn revert .
  4359. CVS Hint: CVS users will be used to simply deleting a file with local
  4360. modifications and then doing an update to restore the file. Whilst
  4361. this will work with Subversion too, doing an actual revert is safer and
  4362. faster—an update will contact the server and possibly pull down new
  4363. changes that you’re not ready to receive, whilst a revert will not need
  4364. to contact the server and will not retrieve new changes from the
  4365. repository.
  4366. If the change is already committed, Subversion can help us
  4367. remove it. There are a number of ways of doing this; here
  4368. we’ll show a sequence of steps that we consider to be the sim-
  4369. plest and least error prone. For this example, let’s assume
  4370. we’re working on a contact management system. We’ve been
  4371. making preliminary releases to beta sites, and things have
  4372. been going well until a client phones up in a panic; when they
  4373. removed a client contact from their address list, it removed all
  4374. the client’s information from the database too.
  4375. The first step is to make sure we’re up-to-date.
  4376. contacts > svn update
  4377. U Contacts.java
  4378. Updated to revision 28.
  4379. Then we identify the exact revision we want to remove. svn
  4380. log is useful for this. Let’s have a look at the log for the main
  4381. contact manager class:
  4382. contacts > svn log Contacts.java
  4383. ----------------------------------------------------------
  4384. r28 | mike | 2004-10-11 10:54:08 -0600 (Mon, 11 Oct 2004)
  4385. Reformat PMB Addresses
  4386. ----------------------------------------------------------
  4387. r27 | fred | 2004-10-11 10:52:47 -0600 (Mon, 11 Oct 2004)
  4388. Remove from database too
  4389. ----------------------------------------------------------
  4390. r26 | ian | 2004-10-11 10:51:38 -0600 (Mon, 11 Oct 2004)
  4391. R EMOVING A C HANGE 96
  4392. Sort clients into alpha order (Bug 2942)
  4393. ----------------------------------------------------------
  4394. Revision 27 looks suspicious, so we use svn diff to see exactly
  4395. what changed between revisions 26 and 27:
  4396. contacts > svn diff -r 26:27 Contacts.java
  4397. Index: Contacts.java
  4398. ==========================================================
  4399. --- Contacts.java (revision 26)
  4400. +++ Contacts.java (revision 27)
  4401. @@ -25,6 +25,7 @@
  4402. public void removeClient(Client client)
  4403. {
  4404. + database.deleteAll(client);
  4405. clientList.remove(client);
  4406. }
  4407. }
  4408. This looks like the problem. However, before we start wan-
  4409. tonly hacking someone else’s change, let’s do some investi-
  4410. gating. Looking at the log, we see that this particular change
  4411. was made by Fred, so we wander over and chat. It turns out
  4412. that this was a simple misunderstanding; Fred hadn’t real-
  4413. ized that the call would delete all the client records. It’s okay
  4414. to remove the change. 11
  4415. We now have to remove the changes to Contacts.java that were
  4416. made in revision 27. We use the svn merge command to back
  4417. out the change:
  4418. contacts > svn merge -r 27:26 Contacts.java
  4419. U Contacts.java
  4420. We’re asking Subversion to calculate the changes between
  4421. revisions 27 and 26 for Contacts.java and apply those changes
  4422. to our working copy. We used revision range 27:26 because
  4423. we’d like to reverse the change. We can use svn diff to verify
  4424. that Subversion has correctly undone the change:
  4425. contacts > svn diff Contacts.java
  4426. Index: Contacts.java
  4427. ==========================================================
  4428. --- Contacts.java (revision 28)
  4429. +++ Contacts.java (working copy)
  4430. @@ -26,7 +26,6 @@
  4431. public void removeClient(Client client)
  4432. {
  4433. - database.deleteAll(client);
  4434. clientList.remove(client);
  4435. }
  4436. 11 It would also be prudent to do a quick search of the rest of the code to
  4437. see if Fred has used the deleteAll () call in other places.
  4438. R EMOVING A C HANGE 97
  4439. At this point, we’re back into a normal flow. We’ve made a
  4440. change to the source, so we should test it then commit the
  4441. change to the repository:
  4442. contacts > svn commit -m "Revert deleteAll change from r27"
  4443. Sending contacts/Contacts.java
  4444. Transmitting file data .
  4445. Committed revision 29.
  4446. Reverting Bigger Changes
  4447. The recipe we just showed was for reverting changes to a sin-
  4448. gle file. How can we handle changes that involve many files?
  4449. Fortunately, Subversion tracks all the files we changed in
  4450. each commit; as long as changes are grouped together in log-
  4451. ical chunks, they’re easy to undo. If r27 had actually been
  4452. a change to a bunch of different files in the contacts direc-
  4453. tory, we can undo all those changes by using “ . ” (the current
  4454. directory) as the target:
  4455. contacts > svn merge -r 27:26 .
  4456. U Contacts.java
  4457. U Database.java
  4458. It’s very important to commit related changes together in a
  4459. single revision. If a single logical change, such as “add date of
  4460. birth field,” is spread over several commits, it becomes more
  4461. difficult to revert the change and also more difficult to track
  4462. which files the change touched. When browsing history, you
  4463. can use the -v (verbose) option to list all the files that changed
  4464. in a particular revision.
  4465. The svn merge command also allows you to specify repository
  4466. URLs when merging. We’ll be using this in Chapter 9, Using
  4467. Tags and Branches, on page 111 for merging changes between
  4468. branches.
  4469. Checking Your Workspace
  4470. You work in your local working copy, editing files and adding
  4471. new files (and occasionally deleting files too). At the same
  4472. time, other folks on your team are doing the same thing,
  4473. checking their changes into the repository. As a result, it’s
  4474. easy to lose track of the state of your working copy. In partic-
  4475. ular, a common problem is forgetting to add new files in your
  4476. working copy to the repository.
  4477. R EMOVING A C HANGE 98
  4478. The svn status command can get information about the files in
  4479. your working directory:
  4480. proj > svn status
  4481. ? common/Calendar.java
  4482. M contacts/Contacts.java
  4483. Here Subversion is telling us that Calendar.java is in our work-
  4484. ing directory but that it has not been added to version control.
  4485. We can also see that we’ve modified Contacts.java .
  4486. By default Subversion just displays information about your
  4487. working copy and doesn’t need to hit the network to do so. If
  4488. someone else has changed a file in the repository and we’re
  4489. out-of-date we won’t know about it. However, Subversion will
  4490. talk to the server and display extra information if you specify
  4491. the --show-updates option (you can use -u if you’re trying to
  4492. avoid RSI):
  4493. proj > svn status --show-updates
  4494. ? common/Calendar.java
  4495. * 26 common/Log.java
  4496. M * 27 contacts/Contacts.java
  4497. Status against revision: 30
  4498. Now we know that both Log.java and Contacts.java are out-
  4499. of-date in our working copy. We have revision 26 of Log.java
  4500. and revision 27 of Contacts.java (which we’ve also modified).
  4501. The repository is currently at revision 30, and when we do
  4502. an update, we’ll get those extra changes incorporated into our
  4503. working copy.
  4504. Chapter 7
  4505. File Locking and Binary Files
  4506. A common question when learning about version control is,
  4507. “But what happens if two people edit the same file? Won’t
  4508. we waste our time undoing each others’ changes?” Thanks to
  4509. the magic of text merging, most of the time it isn’t a problem.
  4510. But what if the file is a picture or CAD model and cannot
  4511. be merged? Subversion 1.2 introduced optional file locking
  4512. which can help avoid problems with unmergeable files.
  4513. 7.1 File Locking Overview
  4514. Many projects contain unmergeable files. Sound, graphics,
  4515. and even many document formats cannot be merged in any
  4516. meaningful way. If Alice and Bob both decide to edit Currency-
  4517. ConversionRates.xls at the same time, one of them will be first to
  4518. commit and the other will have to re-do their changes.
  4519. Fundamentally, this problem is about your team not commu-
  4520. nicating effectively. It’s unlikely that Alice and Bob should
  4521. both be editing the project theme song audio file at the same
  4522. time, but without asking everyone else on the team whether
  4523. they have that file open there’s a chance they might be wast-
  4524. ing their time. Subversion provides a mechanism to help the
  4525. team communicate through optional file locking. file locking
  4526. Any file can be set to require a lock before it is edited by set-
  4527. ting its needs-lock property (it doesn’t matter what the property
  4528. contains—if it’s set, Subversion will enable locking on that
  4529. file). Any file with locking enabled will be checked out read-
  4530. F ILE L OCKING IN P RACTICE 100
  4531. only in the working copy. Most modern editors will refuse to
  4532. edit a read-only file, or will at least warn that you are doing
  4533. so, in an effort to remind the user that the file needs to be
  4534. locked before editing.
  4535. We can issue a svn lock command to obtain a lock on the file.
  4536. The Subversion client will chat with the server ensuring the
  4537. file isn’t already locked, obtain a lock token, and then mark lock token
  4538. the file read-write in the working copy. Additionally we can
  4539. specify a lock comment informing other users why we locked
  4540. the file.
  4541. If a file is locked, another user cannot lock the file or commit
  4542. a change to it without first destroying the original lock (we’ll
  4543. talk more about situations in which this is appropriate later).
  4544. When the user who locked the file is done and commits their
  4545. changes, the lock is released.
  4546. Let’s see how this works in practice. If you want to follow
  4547. along with these examples, create separate working copies for
  4548. Alice and Bob similar to those we created in Section 6.7, Han-
  4549. dling Merge Conflicts, on page 86.
  4550. 7.2 File Locking in Practice
  4551. The Sesame project is moving up in the world. In addition
  4552. to all of its existing features, our customers now want the
  4553. software to work in many different countries. As part of this
  4554. initiative we’ll need to convert between local currencies. The
  4555. real system will use some kind of web service to find out what
  4556. the exchange rates are, but for testing, Bob would like to use
  4557. something simple such as an Excel spreadsheet.
  4558. Why File Locking is Important
  4559. Bob creates a spreadsheet file, CurrencyConversionRates.xls , and
  4560. adds it to the repository:
  4561. sesame > svn add CurrencyConversionRates.xls
  4562. A (bin) CurrencyConversionRates.xls
  4563. sesame > svn commit -m "Added conversion rates for testing"
  4564. Adding (bin) CurrencyConversionRates.xls
  4565. Transmitting file data .
  4566. Committed revision 32.
  4567. F ILE L OCKING IN P RACTICE 101
  4568. Subversion automatically detects that the spreadsheet is a
  4569. binary file when it’s added, which also flags it as being non-
  4570. mergeable. If Alice checks out revision 32 and both Bob and
  4571. Alice change the file and attempt to commit, only one of them
  4572. will succeed. Here’s what Bob might see:
  4573. sesame > svn commit -m "Added Norwegian Krona conversion rate"
  4574. Sending CurrencyConversionRates.xls
  4575. Transmitting file data .svn: Commit failed (details follow):
  4576. svn: Out of date: ' /trunk/CurrencyConversionRates.xls '
  4577. in transaction ' 43-1 '
  4578. Bob’s working copy is out of date because Alice snuck her
  4579. changes in first. If this were a text file, Bob could simply
  4580. update his working copy and Subversion would merge Alice’s
  4581. committed changes with Bob’s pending changes. This doesn’t
  4582. work for the spreadsheet, however; it just produces a conflict:
  4583. sesame > svn up
  4584. C CurrencyConversionRates.xls
  4585. Updated to revision 33.
  4586. Subversion tells Bob his copy of CurrencyConversionRates.xls is
  4587. conflicting with the new revision in the repository. Bob has
  4588. some options now. He can do some detective work with svn log
  4589. to see who else changed the file, and he can choose to keep
  4590. his changes, keep Alice’s changes, or manually merge the two
  4591. files. All of this seems to be quite a lot of work.
  4592. Enabling Locking on a File
  4593. Bob decides he’ll throw away his changes and redo them.
  4594. After all, he only added a single line to the spreadsheet and
  4595. can quickly re-apply his change to the latest version. He’d like
  4596. to avoid the same problem in the future, though, so he adds
  4597. the svn:needs-lock property to the spreadsheet.
  4598. sesame > svn propset svn:needs-lock true CurrencyConversionRates.xls
  4599. property ' svn:needs-lock ' set on ' CurrencyConversionRates.xls '
  4600. sesame > svn commit -m "Enabled locking for spreadsheet"
  4601. Sending CurrencyConversionRates.xls
  4602. Committed revision 34.
  4603. Bob sets svn:needs-lock to “true” (remember it doesn’t actually
  4604. matter what the property contains; if it is present Subversion
  4605. enables locking for the file). This property change doesn’t take
  4606. effect until it is committed to the repository. If you’re adding
  4607. an unmergeable file and would like to enable locking, it’s good
  4608. F ILE L OCKING IN P RACTICE 102
  4609. practice to set the svn:needs-lock property right away. Subver-
  4610. sion’s autoprops, covered in Section 6.4, Automatic Property
  4611. Setting, on page 74, can help with this.
  4612. Basic File Locking
  4613. Once Alice and Bob update their working copies, Subver-
  4614. sion will make the CurrencyConversionRates.xls file read-only.
  4615. The idea behind making the working copy read-only is that
  4616. next time a user edits the file, they will be reminded they are
  4617. attempting to change a read-only file and remember to lock
  4618. the file before continuing. Depending on the application used
  4619. to edit the file you may or may not get a warning. Excel will
  4620. happily open a read-only file and let you change it without giv-
  4621. ing any warning—it’s only when you come to save the mod-
  4622. ified spreadsheet that you’re prompted for a new filename.
  4623. This isn’t usually too much of a problem, though, as many
  4624. users instinctively hit “save” quite often. Other applications
  4625. such as graphics or sound editors may treat read-only files
  4626. differently. You will have to experiment with your particular
  4627. application to find out.
  4628. After setting svn:needs-lock , Bob decides to add the Norwegian
  4629. Krona exchange rate again. This time, he locks the file before
  4630. editing it. 1
  4631. sesame > svn lock CurrencyConversionRates.xls \
  4632. -m "Adding Norwegian Krona"
  4633. ' CurrencyConversionRates.xls ' locked by user ' bob ' .
  4634. It’s advisable to always include a comment indicating why you
  4635. are locking the file. Subversion can provide the lock comment
  4636. to other users and it’s a good way to improve communication.
  4637. Bob can now examine the file and see that it’s locked:
  4638. sesame > svn info CurrencyConversionRates.xls
  4639. Path: CurrencyConversionRates.xls
  4640. Name: CurrencyConversionRates.xls
  4641. URL: svn://olio/sesame/trunk/CurrencyConversionRates.xls
  4642. Repository Root: svn://olio/sesame
  4643. Repository UUID: 63a31077-dc47-8e48-8372-099aabc6682c
  4644. Revision: 34
  4645. Node Kind: file
  4646. Schedule: normal
  4647. Last Changed Author: bob
  4648. 1 Subversion will only let you lock a file if it is up to date—you cannot lock
  4649. an old revision.
  4650. F ILE L OCKING IN P RACTICE 103
  4651. Last Changed Rev: 34
  4652. Last Changed Date: 2006-03-06 15:31:04 -0700 (Mon, 06 Mar 2006)
  4653. Text Last Updated: 2006-03-06 15:29:58 -0700 (Mon, 06 Mar 2006)
  4654. Properties Last Updated: 2006-03-06 15:30:40 -0700 (Mon, 06 Mar 2006)
  4655. Checksum: 7cd95b6dcf6b3ce39baf073f56253e20
  4656. Lock Token: opaquelocktoken:42eef8ec-0355-d548-805b-16b5a8e830aa
  4657. Lock Owner: bob
  4658. Lock Created: 2006-03-06 17:10:17 -0700 (Mon, 06 Mar 2006)
  4659. Lock Comment (1 line):
  4660. Adding Norwegian Krona
  4661. There’s a lot of information here, but the stuff we’re interested
  4662. in is the final five lines. We can see that Bob’s working copy
  4663. has a lock token and that Bob is the lock owner. We can also
  4664. see when the lock was created and Bob’s comment explaining
  4665. why he locked the file.
  4666. If Alice now attempts to lock the file, she’ll receive an error.
  4667. sesame > svn lock CurrencyConversionRates.xls \
  4668. -m "Adding Euro conversion rate"
  4669. svn: warning: Path ' /trunk/CurrencyConversionRates.xls '
  4670. is already locked by user ' bob '
  4671. in filesystem ' /home/svnroot/sesame/db '
  4672. Subversion lets her know that Bob has already locked the file.
  4673. If Alice runs svn info on her working copy she won’t see a lock
  4674. token, indicating she doesn’t have a lock (she couldn’t, Bob
  4675. has a lock already). For Alice to find out more about why the
  4676. file is locked, she can ask Bob directly (improving team com-
  4677. munication) or she can ask the Subversion server. Running
  4678. svn info with the full URL for the file yields more information:
  4679. sesame > svn info svn://olio/sesame/trunk/CurrencyConversionRates.xls
  4680. Path: CurrencyConversionRates.xls
  4681. Name: CurrencyConversionRates.xls
  4682. URL: svn://olio/sesame/trunk/CurrencyConversionRates.xls
  4683. Repository Root: svn://olio/sesame
  4684. Repository UUID: 63a31077-dc47-8e48-8372-099aabc6682c
  4685. Revision: 34
  4686. Node Kind: file
  4687. Last Changed Author: bob
  4688. Last Changed Rev: 34
  4689. Last Changed Date: 2006-03-06 15:31:04 -0700 (Mon, 06 Mar 2006)
  4690. Lock Token: opaquelocktoken:42eef8ec-0355-d548-805b-16b5a8e830aa
  4691. Lock Owner: bob
  4692. Lock Created: 2006-03-06 17:10:17 -0700 (Mon, 06 Mar 2006)
  4693. Lock Comment (1 line):
  4694. Adding Norwegian Krona
  4695. Alice needs to use the full URL to find out about Bob’s lock—
  4696. if she uses just the file name, Subversion shows information
  4697. about her working copy. Alice’s working copy doesn’t have the
  4698. F ILE L OCKING IN P RACTICE 104
  4699. lock, so she needs to ask the server about the latest version
  4700. of the file.
  4701. Once Bob is done editing the file he can commit. When you
  4702. commit a file or directory, Subversion automatically releases
  4703. any locks you are holding. 2
  4704. Breaking Locks
  4705. The owner of a lock can always use svn unlock to release it.
  4706. But what if the lock owner isn’t currently available? Suppose
  4707. Alice tries to lock the exchange rates file to add some data.
  4708. Subversion warns her the file is already locked, so she does a
  4709. bit of investigation:
  4710. sesame > svn info \
  4711. svn://olio/sesame/trunk/CurrencyConversionRates.xls | grep Lock
  4712. Lock Token: opaquelocktoken:42eef8ec-0355-d548-805b-16b5a8e830aa
  4713. Lock Owner: bob
  4714. Lock Created: 2006-03-06 17:10:17 -0700 (Mon, 06 Mar 2006)
  4715. Lock Comment (1 line):
  4716. Alice can see that Bob has a lock on the file, but he created it
  4717. yesterday and still hasn’t released the lock. Since Bob is off
  4718. sick today, Alice decides to break the lock so she can make
  4719. her change. She also makes a mental note to remind Bob not
  4720. to leave important files locked for too long in the future.
  4721. The svn unlock command can be used to release someone else’s
  4722. lock on a file. Alice needs to pass the --force option because
  4723. she doesn’t own the lock herself:
  4724. sesame > svn unlock svn://olio/sesame/trunk/CurrencyConversionRates.xls
  4725. svn: warning: User ' alice ' is trying to use a lock owned
  4726. by ' bob ' in filesystem ' /home/svnroot/sesame/db '
  4727. sesame > svn unlock --force \
  4728. svn://olio/sesame/trunk/CurrencyConversionRates.xls
  4729. ' CurrencyConversionRates.xls ' unlocked.
  4730. If Alice forgets to tell Bob that she broke his lock, when he
  4731. tries to commit the change Subversion will let him know he no
  4732. longer has a matching lock token. The token in Bob’s working
  4733. copy corresponds to the lock that Alice broke, so Bob will have
  4734. to attempt to lock the file again before he can commit it.
  4735. 2 Subversion releases locks for all files in your working copy, not just those
  4736. you are committing. This encourages users to release locks as quickly as
  4737. possible, but might catch you by surprise the first few times you do it.
  4738. F ILE L OCKING IN P RACTICE 105
  4739. sesame > svn commit -m "Added Norwegian Krona"
  4740. Sending CurrencyConversionRates.xls
  4741. Transmitting file data .svn: Commit failed (details follow):
  4742. svn: Cannot verify lock on path ' /trunk/CurrencyConversionRates.xls ' ;
  4743. no matching lock-token available
  4744. Given that Alice can just forcibly unlock the file, you might
  4745. think that Subversion’s file locking is a bit pointless. Bob is
  4746. in the same situation as if there were no locking at all—he
  4747. has to decide whether to throw away his changes or overwrite
  4748. Alice’s. What we have achieved, however, is better commu-
  4749. nication between people editing the file. Alice knew she was
  4750. breaking Bob’s lock, and did so for a good reason—Bob wasn’t
  4751. at work that day and Alice needed to get on with the project.
  4752. Subversion allows you to restrict who can lock and unlock
  4753. files, and who can break locks, through the use of special
  4754. hook scripts. The pre-lock and pre-unlock hooks run before
  4755. a file is locked or unlocked (respectively). These hooks can
  4756. examine whether a file is already locked and, depending on
  4757. site policy, restrict lock breaking operations to certain users.
  4758. The post-lock and post-unlock hooks can be used, for example,
  4759. to send email after a lock is broken. That way Alice can’t forget
  4760. to tell Bob she broke his lock, there will be an email waiting
  4761. for him to let him know.
  4762. After forcibly releasing Bob’s lock, Alice should then lock the
  4763. spreadsheet so she can make modifications to it. But there’s
  4764. a small chance someone else will lock the file in between Alice
  4765. typing those two commands, so Subversion also provides the
  4766. ability to steal the lock from another user.
  4767. Using the --force option with svn lock will steal the lock without
  4768. giving anyone else the chance to lock the file.
  4769. sesame > svn lock --force CurrencyConversionRates.xls
  4770. ' CurrencyConversionRates.xls ' locked by user ' alice ' .
  4771. sesame > svn info CurrencyConversionRates.xls | grep Lock
  4772. Lock Token: opaquelocktoken:b8c434ce-98ef-1046-a553-7479abccdbca
  4773. Lock Owner: alice
  4774. Lock Created: 2006-03-07 14:44:26 -0700 (Tue, 07 Mar 2006)
  4775. It’s important to note that a lock is specific to a working copy
  4776. as well as being owned by a particular user. If Bob locks a file
  4777. using his office computer, then works from home the next day
  4778. on his laptop, the lock is still stored on the office machine. If
  4779. W HEN TO USE L OCKING 106
  4780. he wants to edit the file at home he’ll have to break the lock
  4781. held by the office working copy.
  4782. 7.3 When to use Locking
  4783. Subversion’s optional locking is very useful for controlling
  4784. access to unmergeable files. Adding svn:needs-lock to a file
  4785. can help your team communicate more effectively about who
  4786. is working on the file, and can help prevent wasted effort.
  4787. Try to lock as few files as possible for as short a time as possi-
  4788. ble. Don’t be like Bob—locking a file and then going home for
  4789. the night. The longer a file is locked, the greater the chance
  4790. someone else has to wait around before they can make their
  4791. changes. In the worst case, Alice might be waiting for Bob to
  4792. finish work on a file while Bob waits for Alice to finish work
  4793. on a different file. The two of them will wait forever for the
  4794. other’s lock to be released. Developers moving to Subversion
  4795. from systems such as Visual Source Safe will be familiar with
  4796. this “deadlock” situation.
  4797. If your files are text, such as program code, Subversion can
  4798. usually merge changes for you and you don’t need to lock
  4799. them. There can be cases where it seems attractive to start
  4800. locking mergeable files, such as an important source code
  4801. file that developers update quite often and which seems to
  4802. encounter a lot of conflicts. Usually the best solution isn’t
  4803. to start locking the file, it’s to figure out how to split the file
  4804. into several logical pieces so the whole team doesn’t need to
  4805. continually trip over each other when making changes.
  4806. Chapter 8
  4807. Organizing Your Repository
  4808. When using a version control system, you’ll most likely want
  4809. to store more than one project. A single Subversion repository
  4810. can be used to store files used by developers across an orga-
  4811. nization, whether those developers are working on the same
  4812. team or not. Version control systems use a variety of tech-
  4813. niques for splitting a repository into projects, subprojects,
  4814. modules, and so on. Subversion uses a fairly simple mech-
  4815. anism, organizing everything into directories.
  4816. 8.1 A Simple Project
  4817. Throughout this book, we’ve been using the Sesame project
  4818. as our main example. Back in Section 3.3, Creating a Simple
  4819. Project, on page 34, we imported our Sesame project files to
  4820. /sesame/trunk inside the repository. At the time we deferred
  4821. explanation of why we needed trunk instead of putting files
  4822. directly in the sesame directory—now it’s time to explain a
  4823. little more.
  4824. Most projects will have a main line of development, where the main line
  4825. majority of development activity occurs. Projects also tend
  4826. to have release branches where code that has been finished release branches
  4827. and shipped to production is stored. A release branch won’t
  4828. change very much, except for bug fixes that need to be made.
  4829. Finally, significant events in the life cycle of a project are often
  4830. recorded in tags. A tag might contain the exact code used for tags
  4831. releasing version 5 of Sesame, for example.
  4832. M ULTIPLE P ROJECTS 108
  4833. v w v xyw
  4834. z
  4835. {
  4836. x| v
  4837. z
  4838. {
  4839. }
  4840. ~ €
  4841. 
  4842. ‚ ƒ„
  4843. †
  4844. ‡
  4845. ˆ
  4846. 
  4847. ‰
  4848. }
  4849. x
  4850. Š‹
  4851. wv
  4852. z
  4853. ‚ Œ
  4854. †
  4855. ‡
  4856. ˆ
  4857. z
  4858. 
  4859. 
  4860. 
  4861. 
  4862. 
  4863. 
  4864. 
  4865. 
  4866. 
  4867. Figure 8.1: The Sesame Project Trunk and Branches
  4868. Chapter 9, Using Tags and Branches, on page 111 has lots of
  4869. information about tags and branches, but for now you just
  4870. need to know that both tags and branches are created by
  4871. copying directories in the Subversion repository. The recom-
  4872. mended location for tags is a tags/ directory and (surprise!) for
  4873. branches a branches/ directory.
  4874. Both of these directories need to be easy to find for your
  4875. project, so for Sesame we’d end up with /sesame/trunk for the
  4876. main development area, /sesame/tags for storing tags, and
  4877. /sesame/branches for storing branches. Figure 8.1 shows this
  4878. a little more visually.
  4879. Storing the code for your project in a trunk directory corre-
  4880. sponds to the SCM “mainline” pattern.
  4881. 8.2 Multiple Projects
  4882. So far we have a repository storing the Sesame project. It’s
  4883. easy to see how we could store other projects, Aladdin and
  4884. Rapunzel, as shown in Figure 8.2 on the following page.
  4885. M ULTIPLE R EPOSITORIES 109
  4886. ŽŽ‘
  4887. ’
  4888. “
  4889. ”Ž
  4890. ’
  4891. “
  4892. •
  4893. –—˜
  4894. ™
  4895. š
  4896. š
  4897. š
  4898. ›
  4899. •
  4900. 
  4901. —œ
  4902. Ž
  4903. ’
  4904. š
  4905. š
  4906. š
  4907. š
  4908. š
  4909. š
  4910. 
  4911. ž
  4912. ŸŸ
  4913. —
  4914. ’
  4915. “
  4916.  ” Ž
  4917. ’
  4918. “
  4919. •
  4920. –—˜
  4921. ™
  4922. š
  4923. š
  4924. š
  4925. ›
  4926. •
  4927. 
  4928. — œ
  4929. Ž
  4930. ’
  4931. š
  4932. š
  4933. š
  4934. š
  4935. š
  4936. š
  4937. •
  4938. ¡
  4939. – —¢
  4940. 
  4941. ž
  4942. ’
  4943. “
  4944. ”Ž
  4945. ’
  4946. “
  4947. •
  4948. – — ˜
  4949. ™
  4950. š
  4951. š
  4952. š
  4953. ›
  4954. •
  4955. 
  4956. —œ
  4957. Ž
  4958. ’
  4959. š
  4960. š
  4961. š
  4962. š
  4963. š
  4964. š
  4965. •
  4966. ¡£Ž
  4967. “
  4968. £
  4969. •
  4970. ¤
  4971. ’
  4972. Figure 8.2: Aladdin and Rapunzel Projects
  4973. It’s important to realize that because Subversion uses direc-
  4974. tory copies for branching and tagging, you don’t have to name
  4975. your tags directory tags . It might be confusing for your users,
  4976. however, if you’re using a different name. You also don’t have
  4977. to put your trunk, tags, and branches directories all together
  4978. in a single directory. You don’t need to have each project at
  4979. the root directory of the repository—depending on how your
  4980. developers and IT department are organized, something like
  4981. /finance/revenue/ali-baba might work best for you.
  4982. Subversion’s ability to move directories means that if your
  4983. repository gets out of control—perhaps you have a few dozen
  4984. projects at the root level and things are getting unwieldy—
  4985. you can move projects around easily. Using svn move with two
  4986. repository URLs, as discussed in Section 6.5, Using Repository
  4987. URLs, on page 79, will do a server-side rename and instantly
  4988. move directories. You should coordinate with developers to
  4989. make sure they have checked in any outstanding changes,
  4990. perform the move, and then get everyone to run svn update to
  4991. get the new directory structure.
  4992. 8.3 Multiple Repositories
  4993. Splitting your projects into different directories makes a lot
  4994. of sense—developers can easily find the project they should
  4995. M ULTIPLE R EPOSITORIES 110
  4996. be working on and make changes. It’s also possible to split
  4997. projects across multiple repositories. Since a repository exists
  4998. on disk as a set of files in a particular directory, you can create
  4999. multiple repositories in different directories on a single server
  5000. or create repositories on entirely separate servers.
  5001. If you’re accessing a Subversion repository using file://
  5002. and svn+ssh:// URLs, the first part of the URL specifies the
  5003. path to the repository directory on the server. You can easily
  5004. change this to specify a different directory for the repository.
  5005. When using svnserve , its --root option specifies a virtual root
  5006. directory for your repositories. If you create directories named
  5007. (for example) repos1 and repos2 inside the virtual root, with a
  5008. repository in each, these repository directory names become
  5009. part of the repository URL. In this case you’d access repos1
  5010. using svn://myserver/repos1/... .
  5011. If you’re using Apache to network a Subversion repository,
  5012. you might define a virtual directory for each repository on
  5013. the server. Apache configuration is covered in Appendix A
  5014. on page 151.
  5015. Of course, separating projects across multiple repositories is
  5016. extra administration overhead—you’ll have to back up each
  5017. repository separately. Users might also need more informa-
  5018. tion on where to find a particular project. The upside to this
  5019. extra admin overhead is flexibility. If you need to take down
  5020. a repository for maintenance, 1 you can do so without affect-
  5021. ing other repositories. If a particular project is outgrowing the
  5022. server on which it’s hosted, it might make sense to split the
  5023. repository in two so you can add a second server.
  5024. You don’t have to make a final decision on day one. Sub-
  5025. version provides tools to allow you to migrate data between
  5026. repositories, so you can change your mind when you know
  5027. more about your requirements. To keep things as simple as
  5028. possible, we recommend using just a single repository until
  5029. you’ve got a concrete problem that will be solved by using
  5030. multiple repositories.
  5031. 1 This is somewhat unlikely, since most Subversion maintenance, includ-
  5032. ing performing backups, can be done without taking down the server.
  5033. Chapter 9
  5034. Using Tags and Branches
  5035. Day-to-day use of Subversion is pretty simple: you update
  5036. from your repository, edit files, and save the changes back
  5037. after you’ve tested. However, many developers are put off
  5038. by tags and branches. Perhaps they’ve worked previously
  5039. in teams that abused branches and where a diagram of the
  5040. repository structure would have looked like a bowl of spaghetti
  5041. rather than a controlled, linear development. Or perhaps
  5042. they worked in a team where merges between branches were
  5043. delayed and delayed, so when they did finally occur, it was
  5044. a nightmare resolving the conflicts. Or perhaps it’s just the
  5045. incredible flexibility that branches offer; with so much choice,
  5046. it’s hard to know what to do.
  5047. In reality, tags and branches can (and should) be simple to
  5048. use. The trick is to use them in the correct circumstances.
  5049. In this chapter we present two scenarios where we believe
  5050. branches should be used by teams: generating releases and
  5051. giving developers a place to experiment.
  5052. Beyond these two circumstances, we suggest you think hard
  5053. before adding branches to a repository. Excessive branching
  5054. can quickly render any project’s repository unusable.
  5055. Before we go into the specific recipes, we need to discuss tags
  5056. and branches in general.
  5057. T AGS AND B RANCHES 112
  5058. ¥¦ §
  5059. ¨
  5060. © ª
  5061. ¨
  5062. «
  5063. ¬
  5064. © ­ ©
  5065. ¥
  5066. ®
  5067. ¦ª¯
  5068. «
  5069. ¬
  5070. ©­©
  5071. °© ±
  5072. «
  5073. ¬
  5074. ©­©
  5075. ²
  5076. ³´
  5077. µ
  5078. ¶·
  5079. µ
  5080. ¶ ·
  5081. ²
  5082. ³´
  5083. ²
  5084. ³´
  5085. ²
  5086. ³ ´
  5087. Figure 9.1: Tags as Slices Through the Repository
  5088. 9.1 Tags and Branches
  5089. Your Subversion repository probably contains a lot of informa-
  5090. tion. Apart from the sheer number of source files that com-
  5091. prise a typical project, Subversion also stores every revision of
  5092. each file. Adding time as a dimension to locating information
  5093. in your repository means the complexity just explodes—how
  5094. can we possibly keep track of it all? A tag is a symbolic name
  5095. for a set of files, each with a particular revision number. You
  5096. can think of a tag as making a slice through your repository
  5097. and labeling everything inside, as shown in Figure 9.1 .
  5098. Tags are really useful for keeping track of important events in
  5099. the life cycle of your project. Instead of having to remember
  5100. that you built a release for your customer using revision 16
  5101. of Calendar.java , revision 23 of Schedule.java , and revision 12
  5102. of contacts.dat , you can use a tag to remember this for you.
  5103. Since a Subversion revision number is also a slice through
  5104. the repository, you might think we could just use revision
  5105. numbers or maybe the date we checked the code out in order
  5106. to build a release. This could work, but tags can also be
  5107. made from a mixed revision working copy—a set of files you’ve
  5108. checked out that doesn’t correspond to a single repository
  5109. revision number. This might be needed if you want to pick
  5110. and choose which versions of project components should be
  5111. packaged together during a release.
  5112. To create a tag in Subversion, copy your code (typically from
  5113. the trunk) in the tags directory for your project. Subversion
  5114. T AGS AND B RANCHES 113
  5115. Joe Asks...
  5116. How Do I Make a Tag Read-Only?
  5117. Tags are just copies of your repository at a particular
  5118. revision, so there’s nothing to stop people from check-
  5119. ing changes into the tags directory. Whilst sometimes
  5120. it’s useful to be able to change a tag, most of the
  5121. time it’s best to treat tags as being read-only.
  5122. You can make your tags directory read-only (or more
  5123. correctly create-only—new tags should be allowed)
  5124. by using one of the repository permissions scripts cov-
  5125. ered in Section A.5, Access Control with Hook Scripts,
  5126. on page 168. Often, though, this is overkillsince devel-
  5127. opers will be working on the trunk or a release branch,
  5128. rather than on a tag.
  5129. handles this copy process very efficiently, making the copy
  5130. instantly and requiring very little space to store it. The direc-
  5131. tory to which you copy the code is the symbolic name for the
  5132. tag. The copy serves as a reference point, storing the files in
  5133. your project as they were when the tag was created.
  5134. Directory copies in Subversion are just that—simple copies.
  5135. By convention, you’ll never make changes to the code stored
  5136. underneath tags , but there’s nothing actually stopping you
  5137. from doing so. If you do check in changes to a tag direc-
  5138. tory, the tag effectively becomes a branch. Subversion won’t
  5139. move it to your branches directory or anything clever like that,
  5140. but the tag will no longer contain a fixed snapshot of your
  5141. repository. This could be useful in certain cases—for exam-
  5142. ple, you could set up a latest tag that always contains your
  5143. most recently built (and tested) code.
  5144. We first talked about branches in Section 2.7, Branches, on
  5145. page 19, when we discussed how we can use them to handle
  5146. releases in a version control system. A branch represents a
  5147. fork in the history of the repository; the same file may have
  5148. two or more sets of independent changes made to it, each set
  5149. existing in a separate branch.
  5150. T AGS AND B RANCHES 114
  5151. To create a branch in Subversion, you’ll copy your trunk code
  5152. to a directory underneath branches for your project. The new
  5153. directory names the branch, and initially just stores a Subver-
  5154. sion “cheap copy” of the files as they were when the branch
  5155. was made. When you check in a change to files on a branch,
  5156. Subversion remembers the changes in parallel with changes
  5157. made to the original on the trunk. Subversion also remembers
  5158. that the two files have a common history.
  5159. Tags and Branches in Practice
  5160. Tags and branches have many possible uses. However, exces-
  5161. sive tagging and branching can end up being remarkably con-
  5162. fusing. So to keep things simple, we suggest that initially you
  5163. use them for four different purposes:
  5164. Release Branches
  5165. We recommend putting each release of a project onto
  5166. a separate branch. The directory used inside branches
  5167. names the branch.
  5168. Releases
  5169. The release branch will contain one (and possibly more)
  5170. releases: points at which the project is shipped. The
  5171. release tags identify these points.
  5172. Bug Fixes
  5173. Bugs in the release are fixed on the release branch. If
  5174. appropriate the fix is then merged into the trunk and
  5175. other release branches. In cases where a bug is fixed
  5176. in one commit, a Subversion revision number is enough
  5177. to identify what changed and perform any merges. For
  5178. more complicated bugs a branch is created for the bug
  5179. fix and merged into the release branch and trunk when
  5180. the fix is complete. Tags are created to mark the start
  5181. and end of the bug fix in order to make merging easier.
  5182. Developer Experiments
  5183. Sometimes a subteam has to make far-reaching changes
  5184. to a project’s code base. During the time that these
  5185. changes are being made, the code is incompatible with
  5186. the rest of the system and will break the main build. The
  5187. developers may choose to create a branch labeled as a
  5188. developer experiment and perform their changes there.
  5189. C REATING A R ELEASE B RANCH 115
  5190. Thing to Name Name Style Examples
  5191. Release branch RB-rel RB-1.0
  5192. RB-1.0.1a
  5193. Releases REL-rel REL-1.0
  5194. REL-1.0.1a
  5195. Bug fix branches BUG-track BUG-3035
  5196. BUG-10871
  5197. Pre–bug fix PRE-track PRE-3035
  5198. PRE-10871
  5199. Post–bug fix POST-track POST-3035
  5200. POST-10871
  5201. Developer experiments TRY-initials-desc TRY-MGM-cache-pages
  5202. TRY-MR-neo-persistence
  5203. Figure 9.2: Tag and Branch Naming Conventions
  5204. It’s a good idea to agree upon a naming convention for tags
  5205. and branches with your team. The table in Figure 9.2 shows
  5206. one simple scheme; this is what we’ll be using in this book.
  5207. In this table, rel stands for the release number, and track is a
  5208. bug tracking number.
  5209. Next we’ll take a look at branches and tags in action, starting
  5210. with (we hope!) a common event in your project life cycle—
  5211. creating a release branch so we can ship some code.
  5212. 9.2 Creating a Release Branch
  5213. At intervals throughout the life of your software you’ll want to
  5214. generate releases. As the date for each release nears, atten-
  5215. tion will start to focus away from adding new features, instead
  5216. concentrating on tidying the smaller release-specific details.
  5217. Although initially the whole team may participate in this pro-
  5218. cess, there’ll come a time when the law of diminishing returns
  5219. takes effect, and it becomes more efficient to have a release
  5220. subteam focus on polishing the code for release. If this sub-
  5221. C REATING A R ELEASE B RANCH 116
  5222. ¸¹
  5223. º
  5224. »¹
  5225. ¼ ½ ¾¿
  5226. » ¹ À Á
  5227. º
  5228. Â
  5229. ¿ Ã
  5230. Ä
  5231. º
  5232. ¾ ¿¼½
  5233. Figure 9.3: Release Branch Merges to the Trunk
  5234. team was working in the trunk, the rest of the team would be
  5235. stalled, waiting for them to finish.
  5236. Instead, at this point in the process, move the code to be
  5237. released into its own branch. While the release team works
  5238. in that branch, the rest of the project can continue in the
  5239. trunk. When the release itself is made, we tag the state of the
  5240. release branch with the release number (remember that a tag
  5241. is simply a copy of the release branch at a particular point
  5242. in time). Changes made by the release team in the release
  5243. branch can then be merged back in to the trunk, as shown in
  5244. Figure 9.3 .
  5245. Create the release branch by copying your project’s trunk to a
  5246. new directory underneath branches/ . It’s best to do this using
  5247. repository URLs, because then the branch creation will hap-
  5248. pen entirely on the server and be a lot quicker. You should
  5249. make sure everyone has checked their local working copy in
  5250. and is ready for the branch to be created. 1
  5251. In the following example, we create a branch for release 1.0
  5252. of our project. We also need to create the /sesame/branches
  5253. directory, because this is the first branch we’ve made:
  5254. work > svn mkdir -m "Creating branches directory" \
  5255. svn://olio/sesame/branches
  5256. Committed revision 32.
  5257. 1 Using repository URLs to create a branch, it’s possible to make the
  5258. branch start from any revision in the repository. If you’re a bit late mak-
  5259. ing a branch, it’s always possible to talk to other developers, figure out which
  5260. revision the branch should have started at, and use that instead.
  5261. W ORKING IN A R ELEASE B RANCH 117
  5262. work > svn copy -m "Creating release branch for 1.0" \
  5263. svn://olio/sesame/trunk \
  5264. svn://olio/sesame/branches/RB-1.0
  5265. Committed revision 33.
  5266. Both the branches directory creation and the creation of the
  5267. actual branch require a commit message since they change
  5268. the repository.
  5269. At this point, all we’ve done is to create the release branch.
  5270. Any working copies checked out by developers will still be
  5271. pointing at the trunk. To start actually using the release
  5272. branch, we’ll need to check it out into a new working copy.
  5273. 9.3 Working in a Release Branch
  5274. To access a release branch, you need to check out the project
  5275. from its branch directory instead of the trunk. You can check
  5276. out to a separate directory or switch an existing working copy switch
  5277. to the branch. We recommend the former; it leads to less con-
  5278. fusion and simplifies working on both branches at the same
  5279. time. The svn switch command is useful for assembling differ-
  5280. ent code branches in a working copy, so we’ll discuss both
  5281. methods.
  5282. Checking Out a Release Branch
  5283. If you’re like us, you have plenty of disk space and would
  5284. rather waste a bit of it than have to remember what branch a
  5285. particular working copy is looking at. We tend to keep a work-
  5286. ing copy checked out for each active development branch, just
  5287. to make things easy.
  5288. Change back to your work directory, and then check out from
  5289. the branch directory overriding the default directory name, so
  5290. the source will be checked out under the directory rb1.0 . When
  5291. you check out a branch, you are checking out the most recent
  5292. files in that branch; it’s equivalent to the way that checking
  5293. out in the trunk returns the latest development copies of the
  5294. files:
  5295. work > svn co svn://olio/sesame/branches/RB-1.0 rb1.0
  5296. A rb1.0/Month.txt
  5297. A rb1.0/Number.txt
  5298. A rb1.0/common
  5299. A rb1.0/common/Log.java
  5300. A rb1.0/common/Clock.java
  5301. W ORKING IN A R ELEASE B RANCH 118
  5302. A rb1.0/Day.txt
  5303. A rb1.0/contacts
  5304. A rb1.0/contacts/Contacts.java
  5305. Checked out revision 33.
  5306. If we now edit a file in this checked-out release directory and
  5307. commit the changes, Subversion adds the changes into the
  5308. branch, not into the trunk. We can now continue to refine the
  5309. files in preparation for the actual release.
  5310. Switching a Working Copy to a Release Branch
  5311. The svn switch command alters all or part of a working copy so
  5312. that it points to a different branch. Since most branches con-
  5313. tain only a few differences from the trunk, Subversion can do
  5314. this operation extremely efficiently, transmitting only changed
  5315. files to the client. Switching a working copy to point at a dif-
  5316. ferent branch is much faster than checking out a new working
  5317. copy for that branch.
  5318. To switch your working copy of the Sesame trunk to the 1.0
  5319. release branch, run the following svn switch command:
  5320. work > cd sesame
  5321. sesame > svn switch svn://olio/sesame/branches/RB-1.0
  5322. U common/Clock.java
  5323. U contacts/Contacts.java
  5324. Updated to revision 36.
  5325. Subversion updates the files in the Sesame working copy so
  5326. that they reflect the latest files in the release branch, in this
  5327. case updating two Java files to reflect bug fixes made on the
  5328. branch.
  5329. The svn switch command also accepts a --revision argument
  5330. to specify which revision of the branch you’d like to switch to.
  5331. By default, Subversion switches to the latest revision of the
  5332. branch (the HEAD revision).
  5333. You can switch your working copy back to the trunk like this:
  5334. sesame > svn switch svn://olio/sesame/trunk
  5335. U common/Clock.java
  5336. U contacts/Contacts.java
  5337. Updated to revision 36.
  5338. Subversion can also switch a subdirectory or even a single file
  5339. to a different branch. This ability is used in the next section to
  5340. assemble a working copy with a precise bug fix for a customer.
  5341. G ENERATING A R ELEASE 119
  5342. 9.4 Generating a Release
  5343. After all the tweaking is over, and the acceptance tests run,
  5344. the team decides to generate a release. The most important
  5345. consideration is to ensure that we tag the correct combination
  5346. of files on the correct branch so that we know precisely what’s
  5347. in the release.
  5348. The simplest way to create a release tag is to copy the branch
  5349. to a new directory under tags . This will tag the latest code in
  5350. the release branch.
  5351. Sometimes you might want to tag files or directories that are
  5352. not all at the same revision. Generally, wanting to tag any-
  5353. thing other than the latest code on a branch is an indication
  5354. that something has gone wrong somewhere, so we don’t advise
  5355. making a habit of it. Subversion can tag the state of any work-
  5356. ing copy, copying a mixture of revisions into a tag, from which
  5357. you can potentially create a release.
  5358. These two methods are a little confusing at first, so let’s start
  5359. with the simplest. Once you’re happy with the latest code in
  5360. the release branch, copy it to a new directory under tags :
  5361. work > svn mkdir -m "Creating tags directory" \
  5362. svn://olio/sesame/tags
  5363. Committed revision 34.
  5364. work > svn copy -m "Tag release 1.0.0" \
  5365. svn://olio/sesame/branches/RB-1.0 \
  5366. svn://olio/sesame/tags/REL-1.0.0
  5367. Committed revision 35.
  5368. The previous svn copy copied the latest code, revision 34 in
  5369. this case, from the release branch to the new tag REL-1.0.0 .
  5370. Sometimes you’ll need to tag something other than the lat-
  5371. est code in a branch. Suppose release 1.0.0 was a couple of
  5372. months ago, and the team has successfully shipped a bunch
  5373. of small fixes, taking them to release 1.0.4. An important
  5374. client requires a fix to release 1.0.0 but doesn’t want to wait
  5375. for 1.0.5 to get the fix. The bug is pretty trivial, so we’d like to
  5376. add the fix for it to the 1.0.0 code and ship that to the client. 2
  5377. 2 This is really a pretty nasty kludge, but if your client really doesn’t want
  5378. to upgrade, it might be the only solution.
  5379. G ENERATING A R ELEASE 120
  5380. We’ll check out a working copy with everything as it was in
  5381. 1.0.0 and then update a few files for our client. In this exam-
  5382. ple, Clock.java contained the bug we’re trying to fix:
  5383. work > svn checkout svn://olio/sesame/tags/REL-1.0.0 \
  5384. client-fix
  5385. A client-fix/Month.txt
  5386. A client-fix/Number.txt
  5387. A client-fix/common
  5388. A client-fix/common/Log.java
  5389. A client-fix/common/Clock.java
  5390. A client-fix/Day.txt
  5391. A client-fix/contacts
  5392. A client-fix/contacts/Contacts.java
  5393. Checked out revision 37.
  5394. Next use svn switch to change where the common directory in
  5395. your working copy is pointing. We’d like to get the bug fixes
  5396. from the release branch that have been made since the 1.0.0
  5397. tag was created, so we switch and point at RB-1.0 :
  5398. work > cd client-fix
  5399. client-fix > svn switch \
  5400. svn://olio/sesame/branches/RB-1.0/common \
  5401. common
  5402. U common/Clock.java
  5403. Updated to revision 37.
  5404. Now your working copy contains what the client wants—the
  5405. code as it was when 1.0.0 was shipped, with the critical bug
  5406. fix that was made on the release branch since then.
  5407. After running tests and verifying the code in our working copy
  5408. does fix the problem, we can create the new tag. We use svn
  5409. copy to copy our client-fix working copy into a new tag directory
  5410. REL-1.0.0-clientfix :
  5411. client-fix > cd ..
  5412. work > svn copy -m "Tagging client ' s 1.0.0 fix" client-fix \
  5413. svn://olio/sesame/tags/REL-1.0.0-clientfix
  5414. Committed revision 37.
  5415. Developers can retrieve the code used to build a particular
  5416. release using svn checkout and the tag’s URL:
  5417. work > svn co svn://olio/sesame/tags/REL-1.0.0
  5418. A REL-1.0.0/Month.txt
  5419. A REL-1.0.0/Number.txt
  5420. A REL-1.0.0/common
  5421. A REL-1.0.0/common/Log.java
  5422. A REL-1.0.0/common/Clock.java
  5423. A REL-1.0.0/Day.txt
  5424. A REL-1.0.0/contacts
  5425. A REL-1.0.0/contacts/Contacts.java
  5426. Checked out revision 37.
  5427. F IXING B UGS IN A R ELEASE B RANCH 121
  5428. 9.5 Fixing Bugs in a Release Branch
  5429. Bugs happen. The trick is to handle them in a controlled
  5430. manner. In a release branch, this means we need to keep
  5431. track of the changes made to fix the bug and then make sure
  5432. we apply those fixes to every other branch that might contain
  5433. the same problem. That last point is particularly important.
  5434. By their nature, branches contain duplicate code. That means
  5435. if you find a bug in the source code in one branch, there’s
  5436. always the possibility the same bug exists in another branch
  5437. (after all, originally the source code was the same, bugs and
  5438. all). In the case of a release branch, we need to be able to
  5439. apply our fix to the trunk. We might also need to apply it to
  5440. other release branches (if they also contain the buggy code).
  5441. Without version control, this is a tricky problem. With version
  5442. control, we can manage the process better. We do this by
  5443. getting the version control system to keep track of the source
  5444. code changes made while fixing the bug and then merging
  5445. those changes into the code in other affected branches.
  5446. With Subversion, how exactly we track the bug fix depends on
  5447. how “difficult” the bug is to fix. If it’s a small bug, the fix might
  5448. be a couple of lines changed in a few files. For a more major
  5449. defect, the fix might involve changing quite a bit of code, and
  5450. adding and removing some files, and might be a group effort
  5451. involving more than one developer.
  5452. Subversion tracks changes using revision numbers, as we
  5453. saw in Section 3.6, Updating the Repository, on page 41. If
  5454. you can fix a bug in a single commit, just remembering the
  5455. revision number is enough for us to copy the change to other
  5456. branches. If the bug is more complicated and requires several
  5457. commits to fix (or includes a number of failed attempts to fix
  5458. it), you might need to create a branch to track the fix.
  5459. Simple Bug Fixes
  5460. Let’s assume we’re trying to fix a reasonably simple problem,
  5461. where the fix just requires changes to a couple of files. The
  5462. process is described in the following list.
  5463. 1. Check out the code containing the bug into a local work-
  5464. ing copy.
  5465. F IXING B UGS IN A R ELEASE B RANCH 122
  5466. 2. Generate a test to reveal the bug, fix the code so the new
  5467. test passes, and verify the build.
  5468. 3. Commit your changes into the repository, and remember
  5469. the new revision number. A good way of remembering
  5470. this revision number is to add it to your bug tracking
  5471. system so everyone can find it later.
  5472. 4. Use the new revision number to merge the change to all
  5473. other affected branches (potentially including the trunk).
  5474. As an example, let’s fix bug 3065 on the release branch. First
  5475. we go into the release branch working copy, fix the bug, and
  5476. check in:
  5477. rb1.0 > # .. edit contacts/Contacts.java and fix the bug .. #
  5478. rb1.0 > svn commit -m "Fix bug 3065 (address formatting)"
  5479. Sending contacts/Contacts.java
  5480. Transmitting file data .
  5481. Committed revision 38.
  5482. Subversion tells us our fix was committed as revision 38. To
  5483. merge the fix to the trunk, we go to the trunk working copy
  5484. and ask Subversion to merge revision 38. More specifically,
  5485. we ask for the difference between revisions 37 and 38 to be
  5486. merged to the trunk working copy:
  5487. rb1.0 > cd ../sesame
  5488. sesame > svn update
  5489. At revision 38.
  5490. sesame > svn merge -r37:38 svn://olio/sesame/branches/RB-1.0
  5491. U contacts/Contacts.java
  5492. sesame > svn commit -m "Merge r38 (fix bug 3065)"
  5493. Sending contacts/Contacts.java
  5494. Transmitting file data .
  5495. Committed revision 39.
  5496. Complex Bugs
  5497. If you’re dealing with a difficult bug that might take several
  5498. developers a few days to fix, plain old Subversion revision
  5499. numbers might not cut it. Cheap copies to the rescue once
  5500. again—we’ll create a branch where the bug fixing can be car-
  5501. ried out and use tags to identify when we start and finish the
  5502. fix. These tags will help us merge the fix to other branches.
  5503. The process works like this:
  5504. 1. Branch the code containing the bug into a new bug fix
  5505. branch.
  5506. F IXING B UGS IN A R ELEASE B RANCH 123
  5507. 2. Tag the new branch to mark the start of the bug fix.
  5508. 3. Generate a test to reveal the bug, fix the code so the new
  5509. test passes, and verify the build.
  5510. 4. Commit your changes into the repository. If it takes a
  5511. few tries to fix the bug, don’t worry.
  5512. 5. Once you’re happy with the fix, tag the branch again to
  5513. mark the end of the bug fix.
  5514. 6. Use the two tags to merge the fix to all the other affected
  5515. branches.
  5516. When creating a branch for the bug fix, we’re using the nam-
  5517. ing convention BUG-track, where track is a bug tracking num-
  5518. ber. We use tags named PRE-track and POST-track to mark
  5519. the start and end of the bug fix:
  5520. work > svn copy -m "create bugfix branch" \
  5521. svn://olio/sesame/branches/RB-1.0 \
  5522. svn://olio/sesame/branches/BUG-10512
  5523. Committed revision 40.
  5524. work > svn copy -m "tag bugfix start" \
  5525. svn://olio/sesame/branches/BUG-10512 \
  5526. svn://olio/sesame/tags/PRE-10512
  5527. Committed revision 41.
  5528. We’ve tagged the start of the bug fix using the tag PRE-10512
  5529. and can do the actual bug fixing work in branch BUG-10512 .
  5530. Check out a new working copy of the branch, and fix the bug:
  5531. work > svn checkout svn://olio/sesame/branches/BUG-10512
  5532. A BUG-10512/Month.txt
  5533. A BUG-10512/Number.txt
  5534. A BUG-10512/common
  5535. A BUG-10512/common/Log.java
  5536. A BUG-10512/common/Clock.java
  5537. A BUG-10512/Day.txt
  5538. A BUG-10512/contacts
  5539. A BUG-10512/contacts/Contacts.java
  5540. Checked out revision 41.
  5541. work > cd BUG-10512
  5542. BUG-10512 > # .. Fix bug, possibly adding and removing files .. #
  5543. BUG-10512 > svn commit -m "Fixing bug 10512"
  5544. Adding Year.txt
  5545. Sending common/Log.java
  5546. Transmitting file data ..
  5547. Committed revision 42.
  5548. BUG-10512 > # .. Bug wasn ' t fixed, ask Bob to help out too .. #
  5549. BUG-10512 > svn commit -m "Still fixing bug 10512"
  5550. Sending Number.txt
  5551. Transmitting file data .
  5552. Committed revision 43.
  5553. D EVELOPER E XPERIMENTAL B RANCHES 124
  5554. At this point we’ve fixed the bug. It took us a couple of
  5555. attempts, and maybe we even asked a colleague to check out
  5556. branch BUG-10512 and take a look at it for us. Now we should
  5557. tag the bug fix branch so we can identify the end of the bug
  5558. fix:
  5559. BUG-10512 > cd ..
  5560. work > svn copy -m "tag bugfix finish" \
  5561. svn://olio/sesame/branches/BUG-10512 \
  5562. svn://olio/sesame/tags/POST-10512
  5563. Committed revision 44.
  5564. Now merge the bug fix to the release branch, which is where
  5565. we wanted the fix in the first place. After merging, run the
  5566. test suite to make sure nothing is broken, and then check in:
  5567. work > cd rb1.0
  5568. rb1.0 > svn update
  5569. At revision 44.
  5570. rb1.0 > svn merge svn://olio/sesame/tags/PRE-10512 \
  5571. svn://olio/sesame/tags/POST-10512
  5572. U Number.txt
  5573. U common/Log.java
  5574. A Year.txt
  5575. rb1.0 > # ... run tests ... #
  5576. rb1.0 > svn commit -m "Merged fix for bug 10512"
  5577. Sending Number.txt
  5578. Adding Year.txt
  5579. Sending common/Log.java
  5580. Transmitting file data ..
  5581. Committed revision 45.
  5582. The same svn merge command can be used to pull the bug
  5583. fix into other branches and the trunk. Just change into your
  5584. trunk working copy, make sure it’s up-to-date, and use the
  5585. same merge command to get the fix.
  5586. In many cases the simpler method of just tracking the revi-
  5587. sions committed during a bug fix will work fine, so use it if
  5588. you can. Some bug tracking software includes a place to track
  5589. revision numbers explicitly, but if yours doesn’t you can just
  5590. put revision numbers into the bug’s comments field.
  5591. 9.6 Developer Experimental Branches
  5592. Sometimes developers need to make wide-ranging changes to
  5593. a project (for example, to change a persistence layer or intro-
  5594. duce a new security mechanism). These kinds of things take
  5595. a minimum of several days to code, and (unfortunately) they
  5596. can’t be introduced incrementally: they just affect too much
  5597. D EVELOPER E XPERIMENTAL B RANCHES 125
  5598. code. These changes are typically at a low level in the appli-
  5599. cation and normally have a far-reaching impact on the rest of
  5600. the system.
  5601. If a single developer wants to make a wide-ranging change
  5602. to the source, they could work in their local workspace. How-
  5603. ever, this has a couple of potential downsides. First, the devel-
  5604. oper loses the benefit of version control while they’re working
  5605. on the change; also, they lose the ability to revert just sec-
  5606. tions of their work, they lose revision history, and so on. They
  5607. also don’t have their work in a central repository, so there’s a
  5608. chance it won’t be backed up.
  5609. If multiple developers are working on a wide-ranging change,
  5610. then they have bigger problems; they need to be able to share
  5611. changes and work on the same (experimental) code base.
  5612. The answer is to put the experimental code into a branch in
  5613. the version control system. The developers working on the
  5614. changes use that branch in their workspace. When they’ve
  5615. finished their work, they can make the decision about inte-
  5616. grating their work into the trunk. If they decide that exper-
  5617. iment is a failure, they can abandon the branch. Otherwise
  5618. they simply merge the changes made in the branch into the
  5619. trunk. Whatever their decision, future work continues in the
  5620. trunk, and the branch becomes history.
  5621. Creating a developer branch is effectively the same as creating
  5622. a release branch. We copy the trunk into a new experimental
  5623. branch directory, stored alongside release branches: 3
  5624. work > svn copy -m "new hibernate persistence spike" \
  5625. svn://olio/sesame/trunk \
  5626. svn://olio/sesame/branches/TRY-MGM-hbn-spike
  5627. Committed revision 45.
  5628. To start using the branch, you need to either check it out into
  5629. a new working copy or switch an existing working copy to the
  5630. new branch.
  5631. 3 You might not want experimental branches cluttering up your release
  5632. branches directory, and Subversion is perfectly happy to let you put a branch
  5633. anywhere you like. Just make sure you remember that /branches/cb/fluffy
  5634. contains that new persistence framework you’re betting the company on....
  5635. W ORKING WITH E XPERIMENTAL C ODE 126
  5636. 9.7 Working with Experimental Code
  5637. If you have a working copy of your project already checked
  5638. out, you can switch it to the new experimental branch using
  5639. svn switch . Here we’ll switch our sesame working copy:
  5640. work > cd sesame
  5641. sesame > svn switch svn://olio/sesame/branches/TRY-MGM-hbn-spike
  5642. At revision 45.
  5643. To switch the sesame working copy back to the trunk, we use
  5644. svn switch again:
  5645. sesame > svn switch svn://olio/sesame/trunk
  5646. At revision 45.
  5647. Instead of reusing a working copy, you can check out the
  5648. branch into a new directory. This is our preferred option,
  5649. because it’s harder to get confused about what you’re work-
  5650. ing on:
  5651. work > svn co svn://olio/sesame/branches/TRY-MGM-hbn-spike hbn-spike
  5652. A hbn-spike/Month.txt
  5653. A hbn-spike/Number.txt
  5654. A hbn-spike/common
  5655. A hbn-spike/common/Log.java
  5656. A hbn-spike/common/Clock.java
  5657. A hbn-spike/Day.txt
  5658. A hbn-spike/Year.txt
  5659. A hbn-spike/contacts
  5660. A hbn-spike/contacts/Contacts.java
  5661. Checked out revision 45.
  5662. 9.8 Merging the Experimental Branch
  5663. Once you’re happy with the changes you’ve made in an exper-
  5664. imental branch, you’ll need to merge them back to the trunk.
  5665. To do this, first make sure all the developers have checked in
  5666. their changes and that you have an up-to-date working copy
  5667. of the trunk (this little dance is the reason we suggest check-
  5668. ing out the experimental branch in a different directory).
  5669. We need to tell Subversion to merge all the changes in the
  5670. experimental branch, from when it was created to its latest
  5671. state, into the trunk. For this, we need to know when the
  5672. branch was created. Fortunately, svn log has a --stop-on-
  5673. copy option that will tell us exactly:
  5674. work > svn log --stop-on-copy \
  5675. svn://olio/sesame/branches/TRY-MGM-hbn-spike
  5676. M ERGING THE E XPERIMENTAL B RANCH 127
  5677. ----------------------------------------------------------
  5678. r47 | mike | 2004-11-12 13:47:13 -0700 (Fri, 12 Nov 2004)
  5679. Added hibernate utils
  5680. ----------------------------------------------------------
  5681. r46 | mike | 2004-11-12 13:46:27 -0700 (Fri, 12 Nov 2004)
  5682. Made Contacts a hibernate mapped class
  5683. ----------------------------------------------------------
  5684. r45 | mike | 2004-11-12 12:55:21 -0700 (Fri, 12 Nov 2004)
  5685. new hibernate persistence spike
  5686. ----------------------------------------------------------
  5687. This tells us the TRY-MGM-hbn-spike branch was created at revi-
  5688. sion 45 (Subversion also told us this when we created the
  5689. branch, but we might have forgotten by the time we want to
  5690. merge). Now we can merge all the changes between revision
  5691. 45 and HEAD into our trunk working copy:
  5692. work > cd sesame
  5693. sesame > svn update
  5694. At revision 47.
  5695. sesame > svn merge -r 45:HEAD \
  5696. svn://olio/sesame/branches/TRY-MGM-hbn-spike
  5697. A common/HibernateHelper.java
  5698. A contacts/Contacts.hbm.xml
  5699. U contacts/Contacts.java
  5700. Now we resolve any conflicts produced during the merge, run
  5701. our unit tests to make sure everything works, and check in:
  5702. sesame > # .. run unit tests to make sure everything ' s ok .. #
  5703. sesame > svn commit -m "Merged TRY-MGM-hbn-spike to the trunk"
  5704. Adding common/HibernateHelper.java
  5705. Adding contacts/Contacts.hbm.xml
  5706. Sending contacts/Contacts.java
  5707. Transmitting file data .
  5708. Committed revision 48.
  5709. The techniques in this chapter map directly to a number of
  5710. SCM Patterns. Using a release branch corresponds to the
  5711. “release line” and “release-prep codeline” patterns. Experi-
  5712. mental developer branches correspond to the “task branch”
  5713. pattern. Branches usually have an associated “codeline pol-
  5714. icy” (even if the policy is fairly informal), helping developers
  5715. understand how they should handle the code on each branch.
  5716. Chapter 10
  5717. Creating a Project
  5718. The word project is fairly loosely defined. One person working
  5719. for a week to implement a web form can be a project, as can
  5720. many hundred laboring for many years. But most projects
  5721. share a set of common characteristics:
  5722. • Each project has a name. This may sound trivial, but we
  5723. tend to give things names when we want to identify them
  5724. as independent entities. Names don’t have to be external
  5725. brands, approved by marketing and subject to field tests
  5726. in major metropolitan areas. Project names are simply
  5727. internal to your organization.
  5728. • Each project is cohesive; the components of the project
  5729. work together to achieve some business aim.
  5730. • The components within a project tend to be maintained
  5731. as a unit; you’ll release a version of the project as a
  5732. whole.
  5733. • The stuff in a project shares a common set of engineering
  5734. standards and guidelines and uses a common architec-
  5735. ture.
  5736. It is important to consider this list when putting projects into
  5737. a version control system, as it’s often hard to know where to
  5738. draw the boundaries between different projects. Getting the
  5739. project structure wrong is a major source of frustration when
  5740. using version control and can lead to a lot of wasted effort
  5741. as time goes on. Subversion does make it straightforward
  5742. C REATING THE I NITIAL P ROJECT 129
  5743. to move things around once a project has started, but this
  5744. requires coordination with everyone using the repository.
  5745. Subversion organizes everything by directory, so projects will
  5746. correspond to directory locations inside your repository. Sub-
  5747. projects might correspond to subdirectories, and so on. This
  5748. scheme gives you the flexibility to dream up a directory struc-
  5749. ture that works for your projects, but it can also be a little
  5750. hard to know where to start.
  5751. So, before creating projects in your repository, spend some
  5752. time planning. For example, is your project going to imple-
  5753. ment a framework that the company will use in future devel-
  5754. opment efforts? If so, then perhaps that framework should be
  5755. a separate project in its own right, with your current project
  5756. and those other future projects sharing in its use. Is your
  5757. project developing multiple independent components? Per-
  5758. haps each should be its own project. Or is your project writ-
  5759. ing an extension for an existing chunk of code? Perhaps then
  5760. it should be a subproject of that original project.
  5761. 10.1 Creating the Initial Project
  5762. There are basically three ways to create directories (and thus
  5763. projects) within a Subversion repository:
  5764. • Import existing source into a directory in the repository.
  5765. • Manually create directories using svn mkdir until you have
  5766. the desired project structure.
  5767. • Convert an existing source code repository. There are
  5768. Subversion tools to convert CVS, RCS, Visual Source-
  5769. Safe, and Perforce repositories.
  5770. Converting from some other version control system is a big
  5771. topic and is covered in detail in Appendix B on page 174.
  5772. That leaves us with two options: import and manual directory
  5773. creation.
  5774. Importing Into Subversion
  5775. If you have existing source files (even if it’s just the project’s
  5776. README file), you can use the svn import command to pull those
  5777. C REATING THE I NITIAL P ROJECT 130
  5778. files into your repository. In the examples that follow, we’ll
  5779. assume you’re working on the Wibble project (the Wickedly
  5780. Integrated Business-to-Business Lease Exchange).
  5781. You’ll need a directory tree containing the files you want to
  5782. import (and only the files you want to import; be sure to clean
  5783. up all the various backup files and other dross before going
  5784. any further). Make sure you’re in the top-level directory of
  5785. this tree (in our case, in the directory wibble ), and then issue
  5786. an svn import command:
  5787. wibble > svn import -m "Wibble initial import" \
  5788. svn://olio/wibble/trunk
  5789. Adding wibble.build
  5790. Adding src
  5791. Adding src/Wibble.cs
  5792. Adding src/WibbleTest.cs
  5793. Adding README
  5794. Committed revision 49.
  5795. This tells Subversion to import the contents of the current
  5796. directory, storing it in the repository in /wibble/trunk . Subver-
  5797. sion automatically creates parent directories as needed dur-
  5798. ing an import, but you will probably also want the tags and
  5799. branches directories for your project:
  5800. wibble > svn mkdir -m "Create tags directory" \
  5801. svn://olio/wibble/tags
  5802. Committed revision 50.
  5803. wibble > svn mkdir -m "Create branches directory" \
  5804. svn://olio/wibble/branches
  5805. Committed revision 51.
  5806. Your project is now checked in. You should check it out using
  5807. svn checkout , and, if everything is okay, you can delete the
  5808. original directory tree you used for the import.
  5809. Manually Creating Directories
  5810. If you don’t already have files for your project, an easy way to
  5811. get started is to create a skeletal directory structure and then
  5812. flesh things out by adding files.
  5813. We can use the svn mkdir command to create directories in the
  5814. repository. For a Java project, you might want something like
  5815. Figure 10.1 on the following page. Helpfully, svn mkdir allows
  5816. you to create multiple directories with a single command.
  5817. S TRUCTURE WITHIN THE P ROJECT 131
  5818. Å
  5819. Æ
  5820. ÇÇ
  5821. È
  5822. É
  5823. Ê
  5824. Ë Ì Í
  5825. Ê
  5826. Î
  5827. Ï
  5828. ÐÑ Ò
  5829. Ó
  5830. Ô
  5831. Ï
  5832. Í
  5833. Ê
  5834. ÕÉ
  5835. Ñ
  5836. ËÌ
  5837. Ï
  5838. Ê
  5839. Figure 10.1: Wibble Project Layout
  5840. work > svn mkdir -m "Creating initial structure" \
  5841. svn://olio/wibble \
  5842. svn://olio/wibble/trunk \
  5843. svn://olio/wibble/trunk/src \
  5844. svn://olio/wibble/trunk/doc \
  5845. svn://olio/wibble/trunk/vendor
  5846. Committed revision 54.
  5847. The Wibble project is now ready to check out into a local work-
  5848. ing copy. You’ll be able to add source code, documentation,
  5849. and libraries in the same way you’d add files during regular
  5850. development, using the svn add command.
  5851. 10.2 Structure within the Project
  5852. Your company may well already have standards that dictate
  5853. how to organize the source code and directories within your
  5854. projects. If you’re developing with Java, for example, you
  5855. might be using the Jakarta conventions for laying out directo-
  5856. ries. 1 If you don’t currently use a standard, what follows are
  5857. some basic suggestions.
  5858. 1 http://jakarta.apache.org/site/dirlayout.html
  5859. S TRUCTURE WITHIN THE P ROJECT 132
  5860. Top-Level Files
  5861. These are the typical files you’ll find at the top-level of each
  5862. project:
  5863. README
  5864. Incredible though it seems, a couple of years from now
  5865. the latest red-hot project will have faded down to a dull
  5866. gray, and you’ll have a hard time remembering exactly
  5867. what the Wibble project was all about. So create a file
  5868. called README in the top-level project directory. Write
  5869. a small paragraph describing the project: the business
  5870. problems it is solving, the basic technologies used, and
  5871. so on. This isn’t meant to be a full description; it’s just
  5872. an aide-memoir intended to trigger those long-dormant
  5873. neurons when you come back after along absence.
  5874. BUILDING
  5875. Create another top-level file called BUILDING , containing
  5876. simple hints to future code archaeologists who have the
  5877. unenviable task of rebuilding this project from source.
  5878. Because you’ll be automating the build, this document
  5879. will be short; Figure 10.2 on the next page shows an
  5880. example.
  5881. GLOSSARY
  5882. Create one more top-level file called GLOSSARY . Make it a
  5883. habit to document all project-specific jargon in this file.
  5884. Not only will this make it easier for future developers
  5885. when they’re trying to work out what a “wibble channel”
  5886. is, but it will also guide the project team when it comes
  5887. to naming classes, methods, and variables.
  5888. Top-Level Directories
  5889. Most projects have at least the following top-level directories:
  5890. doc/
  5891. Check all project documentation into doc and its sub-
  5892. directories. Don’t forget to add memos and e-mails that
  5893. describe decisions reached. It’s normal to have directo-
  5894. ries under doc that contain different document types or
  5895. for different phases of the project.
  5896. S TRUCTURE WITHIN THE P ROJECT 133
  5897. Prerequisites:
  5898. * Oracle 9.6i (perhaps later versions but
  5899. that configuration ' s not tested)
  5900. * GCC 2.96
  5901. Building:
  5902. ./configure [--with-oracle= < dir > ]
  5903. make
  5904. make test
  5905. make install
  5906. More info:
  5907. docs/building.html
  5908. Figure 10.2: Sample BUILDING file
  5909. If your project needs external documentation (for exam-
  5910. ple, the description of an algorithm or a third-party file
  5911. format), consider copying this and storing it under the
  5912. doc directory tree (copyright permitting, of course). This
  5913. will make it easier for future maintainers if the external
  5914. site has since gone away. If you can’t copy this material
  5915. into your project, create a file in doc called BIBLIOGRAPHY
  5916. and add links and a brief description in it.
  5917. data/
  5918. Many projects carry along data (for example, information
  5919. needed to populate lookup tables in the database). Keep
  5920. this data in a single location (if for no other reason that
  5921. someone, at sometime, will urgently need to find out why
  5922. we’re charging 127 percent sales tax in Guam).
  5923. db/
  5924. If your project uses a database, store all the schema-
  5925. related stuff here. Work hard not to fall into the habit of
  5926. modifying schemas online. Have your database admin-
  5927. istrator create SQL scripts for each update—scripts that
  5928. both update the schema and migrate the data. By keep-
  5929. ing these in the repository, you’ll be able to migrate any
  5930. version of the database to any other version.
  5931. src/
  5932. The project’s source code should be stored under this
  5933. directory. You might want subdirectories to separate
  5934. different types of source code, for example, src/java and
  5935. src/eiffel .
  5936. S TRUCTURE WITHIN THE P ROJECT 134
  5937. Ö
  5938. ×
  5939. ØÙ Ú
  5940. Û
  5941. ÜÝÞßàÝ
  5942. áâ
  5943. ã
  5944. äß
  5945. ã
  5946. åæ
  5947. æä ç èè Þ Üé
  5948. Ø
  5949. Ö
  5950. ê
  5951. ë
  5952. Û
  5953. ì
  5954. ì
  5955. ì
  5956. í
  5957. ×
  5958. î
  5959. Û
  5960. ï
  5961. Ø
  5962. ê
  5963. ë
  5964. ð
  5965. ì
  5966. ñò
  5967. ë
  5968. ðó î
  5969. Û
  5970. ì
  5971. ì
  5972. ì
  5973. ôõ
  5974. Ùðó
  5975. ×
  5976. Û
  5977. ôõ
  5978. Ùð ó
  5979. ×
  5980. í
  5981. ×
  5982. î
  5983. Û
  5984. î
  5985. ë
  5986. ê
  5987. õ
  5988. Ù
  5989. Ö
  5990. Û
  5991. Þ
  5992. ì
  5993. ö
  5994. ÷
  5995. ô
  5996. ÷
  5997. á
  5998. ì
  5999. ö
  6000. ÷
  6001. ô
  6002. ÷
  6003. í õ
  6004. ×
  6005. ôõ
  6006. ×
  6007. Û
  6008. é
  6009. ì
  6010. ö
  6011. ÷
  6012. ô
  6013. ÷
  6014. ø
  6015. ì
  6016. ö
  6017. ÷
  6018. ô
  6019. ÷
  6020. ë
  6021. ê
  6022. ï
  6023. Û
  6024. ö
  6025. ØÙ
  6026. ê
  6027. Ö
  6028. ì
  6029. ö
  6030. ÷
  6031. ×
  6032. íù
  6033. ×
  6034. ê
  6035. Ù ú
  6036. ì
  6037. ö
  6038. ÷
  6039. ×
  6040. ö
  6041. Ø Ù
  6042. ê
  6043. Ö
  6044. Û
  6045. ì
  6046. ì
  6047. í
  6048. óØ
  6049. ×
  6050. î
  6051. õ
  6052. í ù
  6053. ×
  6054. ê
  6055. Ùú
  6056. Û
  6057. ì
  6058. ì
  6059. í
  6060. ó Ø
  6061. ×
  6062. î
  6063. õ
  6064. û
  6065. ê
  6066. ïï
  6067. ë
  6068. õ
  6069. Û
  6070. Ö
  6071. ÷
  6072. ú
  6073. í
  6074. Û
  6075. ì
  6076. ì
  6077. ì
  6078. ï
  6079. ×
  6080. ÷
  6081. Ùî ü
  6082. õí
  6083. Û
  6084. ì
  6085. ì
  6086. ì
  6087. Figure 10.3: Wibble Project Layout
  6088. util/
  6089. A directory to hold various project-specific utility pro-
  6090. grams, tools, and scripts. Some teams have a directory
  6091. called tools instead.
  6092. vendor/
  6093. If your project uses third-party libraries or header files
  6094. that you want to archive along with your own code, do it
  6095. under a top-level vendor directory.
  6096. vendorsrc/
  6097. Sometimes a project will import and include code from
  6098. a third party (for example, if it is using an open-source
  6099. library and needs to ensure that it will have access to a
  6100. particular version of the source for the life of the appli-
  6101. cation). You’ll include the binary libraries (and possibly
  6102. the header files) in the vendor directory, but you’ll also
  6103. want to retain the source from which these libraries were
  6104. built. Store these sources under the vendorsrc directory.
  6105. We have more to say about vendor source code in Chap-
  6106. ter 11, Third-Party Code, on page 141.
  6107. A possible file layout for the Wibble project is shown in Fig-
  6108. ure 10.3 . In this project we have our own source code (divided
  6109. into client and server components) along with some imported
  6110. open-source code (the JUnit and Spring frameworks).
  6111. S HARING C ODE BETWEEN P ROJECTS 135
  6112. In addition, many projects will have a standard set of direc-
  6113. tories that are used during the build or release of the project.
  6114. These directories do not contain files that should be stored in
  6115. the repository (as their contents are generated on the fly), but
  6116. some teams still find it convenient to have these directories
  6117. appear in every developer’s workspace. To do this, you can
  6118. add these empty directories to the repository; they’ll appear
  6119. in the working copy when developers check out.
  6120. An equally valid alternative is not to store these directories in
  6121. Subversion. Instead, have your build scripts create them as
  6122. needed, and then tidy them up when you’re done with them.
  6123. If you use this scheme, you can add the directory names to
  6124. the svn:ignore property on your project’s top-level directory to
  6125. stop Subversion cluttering your screen with question marks.
  6126. You’ll also want to keep your test code somewhere, but opin-
  6127. ions vary wildly on where this should be. Some teams like
  6128. keeping it in parallel directories to their source tree; others
  6129. put the tests in subdirectories of the source files being tested.
  6130. To some extent the “correct” answer depends on the language
  6131. being used. For example, the Java package naming rules
  6132. mean that if you want to test protected methods you’ll need to
  6133. construct parallel trees (or put your tests in the same direc-
  6134. tory as the source being tested). We cover this in more detail
  6135. in the companion book Pragmatic Unit Testing [HT03], [HT04].
  6136. There are no hard-and-fast rules for structuring directories
  6137. in a project. However, being consistent across projects will
  6138. greatly help people who come along in future and will give you
  6139. the flexibility to move between projects without experiencing
  6140. that “I’m totally lost” feeling.
  6141. 10.3 Sharing Code between Projects
  6142. Projects rarely exist in a vacuum, instead being surrounded
  6143. by other work in an organization. Once a set of projects begins
  6144. to mature, you’ll often find that there are common areas of
  6145. functionality that could be reused across projects. In a large
  6146. enterprise it’s common to have teams specifically working on
  6147. reusable frameworks and libraries.
  6148. S HARING C ODE BETWEEN P ROJECTS 136
  6149. ý
  6150. þ ÿ ?
  6151. ?
  6152. ?
  6153. ?
  6154. ?
  6155. ý
  6156. ?
  6157. ? ??
  6158. ?
  6159. ???? ?
  6160. ?
  6161. ?
  6162. ?
  6163. ?
  6164. þ ?
  6165. ???
  6166. ?
  6167. ?
  6168. ??
  6169. ?
  6170. ?
  6171. ?
  6172. ?
  6173. ???? ?
  6174. ?
  6175. ?
  6176. ?
  6177. ???
  6178. ?
  6179. ?
  6180. ý
  6181. ?
  6182. ?
  6183. ?
  6184. ?
  6185. ?
  6186. ?
  6187. ?
  6188. ?
  6189. þ
  6190. ý
  6191. þ þ
  6192. ? ??
  6193. ??
  6194. ?
  6195. ?
  6196. ?
  6197. ?
  6198. ??
  6199. ?
  6200. ?
  6201. ?
  6202. þ
  6203. ?
  6204. ý
  6205. þ
  6206. ?
  6207. !"#$%"
  6208. ?
  6209. ?
  6210. ?
  6211. ?
  6212. &
  6213. ?
  6214. ? ?
  6215. '
  6216. ?
  6217. ?
  6218. ?
  6219. ?
  6220. ?
  6221. ??
  6222. ?
  6223. ?
  6224. ?
  6225. þ
  6226. ý
  6227. þ þ
  6228. ? ??
  6229. ??
  6230. ?
  6231. ?
  6232. þ
  6233. ?
  6234. ý
  6235. þ
  6236. ?
  6237. ?
  6238. &
  6239. ?
  6240. ? ?
  6241. '
  6242. ?
  6243. ?
  6244. ?
  6245. ?
  6246. ?
  6247. ?
  6248. ?
  6249. ?
  6250. ?
  6251. ?
  6252. ?
  6253. ?
  6254. ?
  6255. ?
  6256. ? ( )
  6257. ?
  6258. ?
  6259. ?
  6260. ?
  6261. ?
  6262. ?????
  6263. ?
  6264. ?
  6265. ?
  6266. þ
  6267. ý
  6268. þ þ
  6269. ? ??
  6270. ??
  6271. ?
  6272. ?
  6273. þ
  6274. ?
  6275. ý
  6276. þ
  6277. ?
  6278. ?
  6279. &
  6280. ?
  6281. ??
  6282. '
  6283. ?
  6284. ?
  6285. ?
  6286. ?
  6287. ?
  6288. ?
  6289. ?
  6290. ?
  6291. ?
  6292. ?
  6293. ?
  6294. Figure 10.4: Repository Layout with an
  6295. ¨
  6296. Uber-project
  6297. The Subversion “everything is a directory” approach means
  6298. that your common code will need to live in a shared directory
  6299. in the repository. There are two main ways to accomplish this:
  6300. • Store all your projects in a single “über-project” and use
  6301. a build script to manage dependencies between projects.
  6302. • Use svn:externals to pull the dependencies for each project
  6303. into your working copy before you build.
  6304. Both approaches can work, but using svn:externals is more flex-
  6305. ible with respect to project organization and branching.
  6306. Code Sharing with an
  6307. ¨
  6308. Uber-project
  6309. The repository directory structure when using an über-project
  6310. is shown in Figure 10.4 .
  6311. Directly beneath the trunk/ directory are directories for each of
  6312. the shared projects, in this case common and dataaccess . The
  6313. directories maitai and wibble store the actual project code for
  6314. the MaiTai and Wibble projects.
  6315. S HARING C ODE BETWEEN P ROJECTS 137
  6316. A developer would check out this über-project into a single
  6317. working copy containing all the projects. What to call this
  6318. working copy requires creativity and inspiration, neither of
  6319. which comes cheap, so we’ll go with uber-project :
  6320. work > svn checkout svn://olio/trunk/ uber-project
  6321. A uber-project/wibble
  6322. A uber-project/wibble/doc
  6323. A uber-project/wibble/doc/UserRequirements.doc
  6324. A uber-project/wibble/src
  6325. A uber-project/wibble/src/WibbleTest.java
  6326. : : :
  6327. A uber-project/dataaccess/lib/neo-1.3.0.dll
  6328. A uber-project/dataaccess/src
  6329. A uber-project/dataaccess/src/DataMapper.cs
  6330. A uber-project/dataaccess/README
  6331. Checked out revision 17.
  6332. When a developer comes to build the MaiTai project, they’d
  6333. (quite rightly) expect the build script to first build the projects
  6334. on which MaiTai depends. In this case it might first build the
  6335. data access project. Once all the dependencies are built—and
  6336. assuming the data access project produces a library as part
  6337. of its build—the MaiTai project can use that library and build
  6338. happily.
  6339. This strategy has a couple of drawbacks. First, developers
  6340. have to check out all the code for all the projects in your
  6341. repository. This might not be desirable if you have a large
  6342. repository or if some of the source is sensitive and requires
  6343. stricter access controls. Second, the branching options are
  6344. limited—you pretty much have to branch all the code at once,
  6345. rather than on a project-by-project basis.
  6346. Code Sharing with Externals
  6347. A special Subversion directory property, svn:externals , lets you
  6348. include the contents of another repository in your working
  6349. copy. Subversion properties and how to manipulate them are
  6350. covered more fully in Section 6.4, Properties, on page 66.
  6351. The svn:externals property is set on a directory and specifies
  6352. a list of repository URLs to include when checking out. You
  6353. can use any Subversion repository you like in an externals
  6354. definition—the client will do the work of checking out for you.
  6355. This means that it is possible to include code from Subversion
  6356. repositories that aren’t under your direct control, for example,
  6357. open-source projects hosted on the Internet.
  6358. S HARING C ODE BETWEEN P ROJECTS 138
  6359. *+
  6360. ,
  6361. ++ - - .//
  6362. 0
  6363. ,
  6364. 1
  6365. 2 34
  6366. 5
  6367. 6 78
  6368. 5
  6369. 9
  6370. +
  6371. :
  6372. ,
  6373. +
  6374. :
  6375. 0
  6376. ,
  6377. 1
  6378. 23 4
  6379. 5
  6380. 1
  6381. .;</
  6382. :
  6383. ,
  6384. <
  6385. 1
  6386. =
  6387. 0
  6388. >
  6389. ?
  6390. 8
  6391. 5
  6392. @
  6393. A
  6394. B
  6395. 5
  6396. 6 78
  6397. 5
  6398. >
  6399. ?
  6400. 8
  6401. 5
  6402. CD E
  6403. 67
  6404. ?
  6405. 5
  6406. 6F
  6407. G
  6408. FF88
  6409. D>>
  6410. 5
  6411. HIJ
  6412. K
  6413. LM
  6414. N
  6415. L
  6416. O
  6417. JP
  6418. Q
  6419. C DE
  6420. 67
  6421. ?
  6422. 5
  6423. 678
  6424. 5
  6425. >
  6426. ?
  6427. 8
  6428. 5
  6429. @
  6430. A
  6431. B
  6432. 5
  6433. C DE
  6434. 67
  6435. ?
  6436. 5
  6437. Figure 10.5: Repository Layout Using Externals
  6438. Figure 10.5 and Figure 10.6 on the next page show views
  6439. of a repository that uses externals to link shared code into
  6440. particular projects. There’s a lot going on here, so we’ll cover
  6441. it piece by piece.
  6442. Let’s look at the MaiTai project first. It is stored in /maitai/trunk
  6443. (shown in Figure 10.5 ). This has a dependency on the data
  6444. access project, in particular on /dataaccess/trunk . The file-
  6445. names in boxes show where these files are imported to the
  6446. MaiTai tree using externals. In order to set up the depen-
  6447. dency, we check out a working copy of the MaiTai project and
  6448. set the svn:externals property:
  6449. work > svn checkout svn://olio/maitai/trunk maitai
  6450. A maitai/lib
  6451. A maitai/src
  6452. Checked out revision 19.
  6453. work > svn propset svn:externals \
  6454. "dataaccess svn://olio/dataaccess/trunk" \
  6455. maitai
  6456. property ' svn:externals ' set on ' maitai '
  6457. Here we’ve set the svn:externals property to include just a single
  6458. external. You can use svn propedit to bring up an editor if you
  6459. have multiple dependencies, which should each be listed on a
  6460. different line.
  6461. S HARING C ODE BETWEEN P ROJECTS 139
  6462. RST T S U
  6463. V
  6464. W
  6465. X
  6466. Y
  6467. UZ
  6468. [
  6469. \]^
  6470. [
  6471. _
  6472. `
  6473. a a
  6474. b
  6475. c
  6476. V
  6477. W
  6478. X
  6479. Y
  6480. UZ
  6481. [
  6482. W
  6483. de f
  6484. V
  6485. g
  6486. h
  6487. i
  6488. [
  6489. X
  6490. cjS
  6491. f
  6492. `
  6493. W
  6494. S
  6495. X
  6496. k
  6497. V
  6498. l
  6499. m
  6500. ^
  6501. [
  6502. W
  6503. de f
  6504. [
  6505. g
  6506. h
  6507. i
  6508. [
  6509. \]^
  6510. [
  6511. l
  6512. m
  6513. ^
  6514. [
  6515. \ ] ^
  6516. [
  6517. l
  6518. m
  6519. ^
  6520. [
  6521. n op
  6522. \ ]
  6523. m
  6524. [
  6525. ^ ]q q]
  6526. p
  6527. [
  6528. \]^
  6529. [
  6530. l
  6531. m
  6532. ^
  6533. [
  6534. \] ^
  6535. [
  6536. l
  6537. m
  6538. ^
  6539. [
  6540. nop
  6541. \ ]
  6542. m
  6543. [
  6544. ^]q q ]
  6545. p
  6546. [
  6547. \]^
  6548. [
  6549. l
  6550. m
  6551. ^
  6552. [
  6553. rs t
  6554. u
  6555. vw
  6556. x
  6557. v
  6558. y
  6559. t z
  6560. {
  6561. r st
  6562. u
  6563. v w
  6564. x
  6565. v
  6566. y
  6567. tz
  6568. {
  6569. Figure 10.6: Repository Layout Using Externals
  6570. The externals definition has two parts: first we name the
  6571. directory inside the MaiTai project where Subversion should
  6572. include /dataaccess/trunk , and then we provide the repository
  6573. URL we’d like to include. Performing an update on the work-
  6574. ing copy will cause the Subversion client to pull in the data
  6575. access project:
  6576. work > cd maitai
  6577. maitai > svn update
  6578. Fetching external item into ' dataaccess '
  6579. A dataaccess/lib
  6580. A dataaccess/src
  6581. Updated external to revision 19.
  6582. Updated to revision 19.
  6583. We still need to commit the property change on the maitai
  6584. directory to let other developers see this new external item.
  6585. maitai > svn commit -m "Added dataaccess project as an external"
  6586. Sending .
  6587. Committed revision 20.
  6588. S HARING C ODE BETWEEN P ROJECTS 140
  6589. Externals provide much more flexibility when working with
  6590. branches. Figure 10.6 on the page before shows that the Wib-
  6591. ble project depends on common . Furthermore, the trunk of
  6592. Wibble depends on the trunk of common , but the 1.0 branch
  6593. of Wibble depends on the 1.0 branch of common . We can
  6594. do this by changing the svn:externals definition for the Wibble
  6595. project after we branch it. Externals also allow you to be very
  6596. precise about the dependencies each project has—developers
  6597. don’t have to check out every piece of code in the repository
  6598. in order to start working.
  6599. An important point to note is that Subversion will not auto-
  6600. matically commit changes you make to a checked-out external
  6601. when you commit changes to the project that included it. You
  6602. need to explicitly commit changes to each external by chang-
  6603. ing to the directory in which it’s included and running svn
  6604. commit , or by naming each of the externals directories during
  6605. a commit.
  6606. We recommend treating dependencies as “read-only” in each
  6607. project—if a developer working on MaiTai needs to fix a bug in
  6608. the data access project, he should check out /dataacess/trunk ,
  6609. fix the bug, check in, and then do an update in his MaiTai
  6610. working copy to get the fix.
  6611. Chapter 11
  6612. Third-Party Code
  6613. All projects rely to some extent on external libraries: Java
  6614. programs use rt.jar , .NET programs use mscorlib.dll , and so on.
  6615. Should these libraries form part of your working copy when
  6616. you check out from the repository?
  6617. To answer that question, ask yourself another. You need to
  6618. be able to rebuild a working program at some arbitrary time
  6619. in the future. Will you be able to use the versions of these
  6620. libraries that will be available then?
  6621. 11.1 Binary Libraries
  6622. If you feel comfortable that the libraries used by your code will
  6623. be available (and compatible) over the life of your application,
  6624. then there’s no need to do anything special with them; just
  6625. use them as installed on your machine.
  6626. Looking beyond standard language facilities, many projects
  6627. include other, less stable libraries in their projects. For exam-
  6628. ple, many .NET developers will use the NUnit 1 framework to
  6629. test their code. Compared to the standard libraries, these
  6630. frameworks are fairly volatile (as of May 2006, NUnit is up
  6631. to version 2.2.8). Although the changes between versions are
  6632. mostly compatible, changes can affect your application. As
  6633. a result, we recommend you include these libraries in your
  6634. project’s repositories.
  6635. 1 http://www.nunit.org/
  6636. B INARY L IBRARIES 142
  6637. Having made the decision you want to include a third-party
  6638. library in your workspace and repository, you now have to
  6639. decide what to include and where to put it.
  6640. The first decision is what files to include. This is relatively
  6641. easy. If you use the library in the form distributed by the
  6642. maker, and you feel confident that the library will continue
  6643. to work unmodified through the life of the application, then
  6644. storing the binary form of the library is all that is needed. We
  6645. suggest putting all these libraries in subdirectories of a top-
  6646. level vendor/ directory inside your project.
  6647. If the library is architecture independent (for example, a Java
  6648. . jar file), then it can simply sit in a subdirectory called lib . If
  6649. the file as packaged by the vendor has a version number in the
  6650. name, such as junit-3.8.1.jar , we suggest giving it a more generic
  6651. name. In this case, you’d add junit.jar to your repository. This
  6652. makes upgrading easy—just copy over a new version of the
  6653. library and check in. You won’t need to change your build
  6654. scripts or include files. In any case, you should state the
  6655. version number of the library in your commit message so later
  6656. you can figure out what version you’re using.
  6657. If instead you have libraries that depend on the target archi-
  6658. tecture (assuming your application is targeted at more than
  6659. one architecture), you’ll need to have subdirectories below
  6660. vendor for each architecture and operating system combina-
  6661. tion. A common naming scheme for these subdirectories is to
  6662. use arch - os where arch is the target architecture ( i586 for an
  6663. Intel Pentium, ppc for a PowerPC, and so on) and os is the
  6664. operating system ( linux , win2k , osx , and so on).
  6665. Languages such as C and C++ require that you include source
  6666. header files in application code that uses a particular library.
  6667. These header files are supplied with the library and should
  6668. also be stored in the repository. We suggest storing them in
  6669. an include subdirectory beneath vendor . Structure the direc-
  6670. tories beneath vendor/include in such a way that the compilers
  6671. can find the libraries’ include files naturally. As an example,
  6672. consider a C library called datetime, which performs date and
  6673. timecalculations. It comes with a binary library archive, lib-
  6674. datetime.a , and two header files, datetime.h and extras.h . The
  6675. datetime.h header library is intended to be installed at the top
  6676. B INARY L IBRARIES 143
  6677. |
  6678. } ~
  6679. 
  6680. €€
  6681. 
  6682. }
  6683. ‚
  6684. ~
  6685. ƒ
  6686. }
  6687. „
  6688. €
  6689. |
  6690. †
  6691. ‡
  6692. ˆ
  6693. ‰
  6694. Š
  6695. ‹ŒŽ
  6696. ˆ
  6697. ‡
  6698. 
  6699. 
  6700. ‘
  6701. ’
  6702. 
  6703. ‘
  6704. “”
  6705. 
  6706. • – —
  6707. 
  6708. – ˜
  6709. ™
  6710. —
  6711. ™
  6712. ‘
  6713. š—
  6714. ›
  6715. œ
  6716. –
  6717. ™
  6718. 
  6719. —
  6720. ™
  6721. ž
  6722. ˜Ÿ
  6723. ›
  6724. œ
  6725. 
  6726. ‘
  6727. ’– ˜
  6728. ™
  6729. —
  6730. ™
  6731. ‘
  6732. š—
  6733. ›
  6734. ˜
  6735. Figure 11.1: Sample Repository with Third-Party Library
  6736. level of the include hierarchy, extras.h is expected to be in a
  6737. subdirectory called dt . That is, a program that used both
  6738. header files would normally start like this:
  6739. #include < datetime >
  6740. #include < dt/extras >
  6741. // . . .
  6742. In this case, we’d organize our repository (and our working
  6743. copy) as shown in Figure 11.1 .
  6744. Integrating with the Build Environment
  6745. If you include vendor libraries or header files in your repos-
  6746. itory, you’ll need to make sure your compilers, linkers, and
  6747. IDEs can get to them. There’s a minor problem: you need
  6748. to make sure you don’t check anything into the repository
  6749. that contains absolute path names (as this might not work on
  6750. some other developer’s machine). Instead, you have a couple
  6751. of options:
  6752. • Arrange your build tools so that all path names are rela-
  6753. tive to (say) the top-level project directory. This is work-
  6754. able if you’re using an external build tool such as make
  6755. or ant , but it can get tricky.
  6756. • Set up some external environment variable to point to
  6757. the top of the project tree, and make all references in the
  6758. L IBRARIES WITH S OURCE C ODE 144
  6759. build relative to this variable. This allows each developer
  6760. to have different values in the external variable but then
  6761. to share a common build environment layout.
  6762. The external variable need not be a true operating sys-
  6763. tem environment variable. The Eclipse IDE, for example,
  6764. allows each user to set internal variables and then to
  6765. have a common shared build structure that references
  6766. these variables. This means all developers can share a
  6767. common Eclipse build definition but that developers can
  6768. still install the source in different locations.
  6769. We recommend the second approach.
  6770. 11.2 Libraries with Source Code
  6771. Sometimes a library comes with source code (or is distributed
  6772. only as source code). If you have both source and binary
  6773. versions of the library available, which should you store in the
  6774. repository, and how should you set up your working copy?
  6775. The answer is an exercise in risk management. Having the
  6776. source available means you are always in the position (tech-
  6777. nically, at least) to fix bugs and add features, something you
  6778. can’t do with a binary library. This is clearly a good thing. At
  6779. the same time, including the source code for all the libraries
  6780. used by your project can slow down builds and complicate
  6781. the structure of your project. It also gives future maintainers
  6782. a headache. If there’s a bug, do they need to consider poten-
  6783. tial changes to the library source, or can they concentrate on
  6784. the code written by your organization?
  6785. Our recommendation is to add vendor source to your reposi-
  6786. tory, but to treat it specially. To do this you have to do a bit
  6787. of role playing.
  6788. Imagine for a minute that you are the writer of this particular
  6789. library and that every now and then you release an updated
  6790. version of the code to your user base. Being a high-quality
  6791. library writer, you naturally put all your source in a version
  6792. control system and practice all the necessary release control
  6793. procedures.
  6794. L IBRARIES WITH S OURCE C ODE 145
  6795. Now come back from the role play (remember, breathe in,
  6796. breathe out, breathe in, breathe out). In an ideal world, we
  6797. should be able to hook straight into our vendor’s repository
  6798. and extract releases directly from there. But we can’t, so we
  6799. have to do the work ourselves. Whenever we receive code,
  6800. bug fixes, and new releases from a vendor, we have to pre-
  6801. tend that we generated the code and handle it in our version
  6802. control system as if we were the vendor handling it in theirs.
  6803. Importing Vendor Source for the First Time
  6804. When we first receive the source code for a third-party library,
  6805. we need to import it into our repository. Vendor code is stored
  6806. on a vendor branch, and each time we receive code and import vendor branch
  6807. it it’s called a vendor drop. We recommend keeping vendor
  6808. vendor drop
  6809. branches separate from the code of your project. If you antici-
  6810. pate importing code from multiple sources over time, it proba-
  6811. bly makes sense to keep it all under a common top-level direc-
  6812. tory; we suggest calling it /vendorsrc .
  6813. Each library or product you want to track will live in its own
  6814. vendor branch beneath /vendorsrc , such as /vendorsrc/sun/jdbc .
  6815. Within the vendor branch directory we’ll have a current direc-
  6816. tory storing the most recent vendor drop (kind of like the trunk
  6817. directory for a regular project). Alongside this we’ll have direc-
  6818. tories containing tags for each vendor drop.
  6819. To make this more concrete, let’s assume we’ve decided to
  6820. use version 1.0.0 of the jMock 2 mock objects library (after
  6821. checking the license terms, of course).
  6822. Start by downloading the latest release from the jMock web
  6823. site. Save jmock-1.0.0-src.jar to a temporary directory, and then
  6824. use WinZip (or plain old jar ) to extract the contents. This
  6825. should leave you with a folder called jmock-1.0.0 containing all
  6826. the jMock source code, documentation, and examples.
  6827. Now we can import the drop into the repository. We’ll store
  6828. it under /vendorsrc/codehaus/jmock/current . In this case, the
  6829. vendor is CodeHaus, and the “product” is jMock. Run svn
  6830. import from the directory above jmock-1.0.0 :
  6831. 2 http://jmock.codehaus.org/
  6832. L IBRARIES WITH S OURCE C ODE 146
  6833. tmp > svn import --no-auto-props -m "Import jMock 1.0.0" \
  6834. jmock-1.0.0 \
  6835. svn://olio/vendorsrc/codehaus/jmock/current
  6836. Adding jmock-1.0.0/extensions
  6837. Adding jmock-1.0.0/extensions/cglib
  6838. Adding jmock-1.0.0/extensions/cglib/acceptance-tests
  6839. Adding jmock-1.0.0/extensions/cglib/acceptance-tests/atest
  6840. Adding jmock-1.0.0/extensions/cglib/acceptance-tests/atest/jmock
  6841. : : : :
  6842. Adding (bin) jmock-1.0.0/examples/classes/.../Calculator.class
  6843. Adding (bin) jmock-1.0.0/examples/classes/.../ParseException.class
  6844. Adding (bin) jmock-1.0.0/examples/classes/.../InfixParser.class
  6845. Committed revision 3.
  6846. Next, tag the vendor drop, marking it as version 1.0.0. If
  6847. CodeHaus releases a new version of jMock, you’ll be able track
  6848. the two versions effectively:
  6849. tmp > svn copy -m "Tag 1.0.0 vendor drop" \
  6850. svn://olio/vendorsrc/codehaus/jmock/current \
  6851. svn://olio/vendorsrc/codehaus/jmock/1.0.0
  6852. Committed revision 4.
  6853. Updating to a New Vendor Release
  6854. When jMock 1.0.1 comes along, we’d like to be able to incor-
  6855. porate it into our repository. To do this, think back to our
  6856. role play—we are pretending to be CodeHaus, maintaining our
  6857. code in /vendorsrc/codehaus/jmock/current . When we released
  6858. 1.0.0, we tagged the code by copying it to jmock/1.0.0 . We con-
  6859. tinue to develop our code, working on our “trunk.” Once we
  6860. reach our next release, we make another tag to mark 1.0.1.
  6861. Outside of the role play, we don’t actually get to see any of
  6862. the changes that are made to the jMock code. We see only
  6863. the result, jmock-1.0.1-src.jar . In order to emulate what’s going
  6864. on in the jMock repository, we need to update the contents of
  6865. our directory /vendorsrc/codehaus/jmock/current so that it looks
  6866. like the new release. We update our copy of the jMock code so
  6867. that it looks like we did all the work to get us to 1.0.1.
  6868. How do we get our copy to look like the new release? Well,
  6869. since the last release CodeHaus will have modified some files,
  6870. added some new files, maybe moved a few files around, and
  6871. occasionally deleted files. We need to perform all these opera-
  6872. tions in current .
  6873. L IBRARIES WITH S OURCE C ODE 147
  6874. Whilst this synchronization could be done by hand, it’s all
  6875. pretty labor intensive and prone to mistakes. Fortunately,
  6876. Subversion has a utility to import new vendor drops automat-
  6877. ically, performing the adds and deletes for you. The magic is
  6878. provided by a Perl script called svn load dirs.pl . 3
  6879. The script requires Perl to be installed on your system, along
  6880. with a few modules (such as the URI module for manipulating
  6881. URLs). When run, it requires three arguments:
  6882. Base URL
  6883. The base URL of the Subversion repository to work with.
  6884. It expects to find all the drops for a particular product
  6885. beneath this directory. In our example so far, this would
  6886. be svn://olio/vendorsrc/codehaus/jmock .
  6887. “Current” Directory
  6888. The directory beneath the base URL in which the latest
  6889. vendor drop can be found. We’re using current in this
  6890. example.
  6891. Directory to Import
  6892. The directory on the local machine from which to import
  6893. the new vendor drop.
  6894. You can also specify a -t tagname option to automatically
  6895. tag the new vendor drop.
  6896. Download the new release of jMock, storing it in jmock-1.0.1 in
  6897. your temporary directory. Now run svn load dirs.pl to load the
  6898. new release and tag it:
  6899. tmp > svn load dirs.pl -t 1.0.1 \
  6900. svn://olio/vendorsrc/codehaus/jmock current jmock-1.0.1
  6901. Directory jmock-1.0.1 will be tagged as 1.0.1
  6902. Please examine identified tags. Are they acceptable? (Y/n) y
  6903. We’re being asked if tagging the new source from jmock-1.0.1
  6904. as “1.0.1” is okay. That’s what we want to do, so type y and
  6905. hit Enter. The rest of the process is hands free:
  6906. Checking that the base URL is a Subversion repository.
  6907. Running /usr/local/bin/svn log -r HEAD svn://olio/vendorsrc/codehaus/jmock
  6908. Finding the root URL of the Subversion repository.
  6909. Running /usr/local/bin/svn log -r HEAD svn://olio
  6910. Determined that the svn root URL is svn://olio.
  6911. 3 http://svn.collab.net/repos/svn/trunk/contrib/client-side
  6912. L IBRARIES WITH S OURCE C ODE 148
  6913. Native EOL on this system is \ 012.
  6914. Finding if any directories need to be created in repository.
  6915. Running /usr/local/bin/svn log -r HEAD svn://olio/.../jmock/current
  6916. No directories need to be created to prepare repository.
  6917. Checking out svn://olio/.../jmock/current into /tmp/...
  6918. Running /usr/local/bin/svn checkout svn://olio/.../jmock/current my import wc
  6919. Loading jmock-1.0.1 and will save in tag 1.0.1.
  6920. U build.properties
  6921. U VERSION
  6922. U CHANGELOG
  6923. U core/src/test/jmock/core/InvocationTest.java
  6924. U core/src/test/jmock/core/testsupport/MockInvocationMatcher.java
  6925. U core/src/test/jmock/core/matcher/InvokedRecorderTest.java
  6926. U core/src/org/jmock/core/matcher/InvokeAtLeastOnceMatcher.java
  6927. : : :
  6928. Running /usr/local/bin/svn propget svn:eol-style VERSION
  6929. Running /usr/local/bin/svn propget svn:eol-style CHANGELOG
  6930. : : :
  6931. Running /usr/local/bin/svn commit --file /tmp/svn load ...
  6932. Running /usr/local/bin/svn update
  6933. : : :
  6934. Cleaning up /tmp/svn load dirs ZH6k9TLxFM
  6935. Examining the Subversion log, we can see that the changes
  6936. between jMock 1.0.0 and 1.0.1 have been applied to our copy
  6937. of the code:
  6938. tmp > svn log -v svn://olio/vendorsrc/codehaus/jmock/current
  6939. ---------------------------------------------------------
  6940. r5 | mike | 2004-11-18 17:03:06 -0700 (Thu, 18 Nov 2004)
  6941. Changed paths:
  6942. M /vendorsrc/codehaus/jmock/current/CHANGELOG
  6943. M /vendorsrc/codehaus/jmock/current/VERSION
  6944. M /vendorsrc/codehaus/jmock/current/build.properties
  6945. : : :
  6946. Load jmock-1.0.1 into vendorsrc/codehaus/jmock/current.
  6947. ----------------------------------------------------------
  6948. We can follow the same process to import new releases of
  6949. jMock, as they become available.
  6950. Using Vendor Code in a Project
  6951. All this fancy importing is great so far—you’ve got your own
  6952. copy of the jMock source code and have tagged it for posterity.
  6953. Now we need to actually use that source in a project. To do
  6954. this, copy the vendor branch into your project, storing it in
  6955. vendor/jmock :
  6956. work > svn mkdir -m "" svn://olio/maitai/trunk/vendor
  6957. work > svn copy -m "MaiTai needs jMock" \
  6958. svn://olio/vendorsrc/codehaus/jmock/1.0.0 \
  6959. svn://olio/maitai/trunk/vendor/jmock
  6960. Committed revision 12.
  6961. When we check out MaiTai, we’ll get a copy of the jMock code:
  6962. L IBRARIES WITH S OURCE C ODE 149
  6963. work > svn checkout svn://olio/maitai/trunk maitai
  6964. A maitai/doc
  6965. A maitai/src
  6966. A maitai/vendor
  6967. A maitai/vendor/jmock
  6968. A maitai/vendor/jmock/extensions
  6969. : : : :
  6970. A maitai/vendor/jmock/build.xml
  6971. Checked out revision 12.
  6972. Modifying Vendor Code
  6973. Now that you have the vendor’s source code, you’re free to
  6974. make modifications to it, safe in the knowledge that you’ll be
  6975. able to easily incorporate new releases whilst preserving your
  6976. custom changes.
  6977. Let’s say we want to make some tweaks to jMock’s excep-
  6978. tion handling and expectation framework. Make your changes
  6979. within the MaiTai working copy, and commit them as normal:
  6980. maitai > svn status
  6981. M vendor/jmock/core/src/org/jmock/expectation/ExpectationList.java
  6982. M vendor/jmock/core/src/org/jmock/util/NotImplementedException.java
  6983. maitai > svn commit -m "Made some custom changes to jMock"
  6984. Sending vendor/jmock/core/src/org/jmock/expectation/ExpectationList.java
  6985. Sending vendor/jmock/core/src/org/jmock/util/NotImplementedException.java
  6986. Transmitting file data ..
  6987. Committed revision 13.
  6988. Subversion tracks the change you’ve made just like regular
  6989. changes to code you authored yourself.
  6990. Updating Modified Code
  6991. Life is good. The MaiTai project is doing well and is a suc-
  6992. cess for your company. The guys at CodeHaus release a new
  6993. version of jMock, and you’d like to incorporate that into the
  6994. MaiTai project. After loading and tagging the new vendor
  6995. drop, you’re ready to upgrade MaiTai.
  6996. We need to merge the changes made to jMock between 1.0.0
  6997. and 1.0.1. To do this, use the svn merge command:
  6998. maitai > svn merge svn://olio/vendorsrc/codehaus/jmock/1.0.0 \
  6999. svn://olio/vendorsrc/codehaus/jmock/1.0.1 \
  7000. vendor/jmock
  7001. U vendor/jmock/VERSION
  7002. U vendor/jmock/CHANGELOG
  7003. : : :
  7004. U vendor/jmock/build.properties
  7005. K EYWORD E XPANSION DURING I MPORTS 150
  7006. Subversion applies the changes to your working copy. If any
  7007. conflicts arise between your custom modifications and the
  7008. 1.0.1 changes, you’ll need to fix them as you would a conflict
  7009. between two developers. Once any conflicts are resolved, and
  7010. you’ve run the tests to make sure everything’s still working,
  7011. commit the changes to the repository:
  7012. maitai > svn commit -m "Updated MaiTai with jMock 1.0.1"
  7013. Sending vendor/jmock/CHANGELOG
  7014. Sending vendor/jmock/VERSION
  7015. Sending vendor/jmock/build.properties
  7016. : : :
  7017. Transmitting file data ......................
  7018. Committed revision 14.
  7019. 11.3 Keyword Expansion during Imports
  7020. In these examples, we’re importing third-party code (probably
  7021. from a version control system other than Subversion) into our
  7022. repository. If we’re importing code from CVS, for example,
  7023. the authors may have included $ Author $ or $ Id $ keywords.
  7024. We discussed keywords more fully in Section 6.4, Keyword
  7025. Expansion, on page 68.
  7026. The problem is that the keywords are expanded every time
  7027. the file is checked out. If the vendor has used these tags,
  7028. then the source you receive will have the vendor’s informa-
  7029. tion in these fields. However, if you just import these files as
  7030. they stand and check them back out, Subversion will update
  7031. the tags, and suddenly your name will appear in the author
  7032. field. While this may be vaguely satisfying, it will cause prob-
  7033. lems later when you come to merge in changes with the next
  7034. vendor release. Subversion will notice that these tag lines
  7035. have changed, and you’ll get conflicts when merging with the
  7036. vendor’s code.
  7037. Fortunately, keyword expansion isn’t switched on for new files
  7038. by default. However, if you’ve enabled autoprops as described
  7039. in Section 6.4, Automatic Property Setting, on page 74, and
  7040. are setting svn:keywords automatically, keyword expansion
  7041. might occur. Use the --no-auto-props switch when import-
  7042. ing to disable any potential keyword expansion.
  7043. The SCM Pattern for handling third party code using branches
  7044. is, unsuprisingly, named “third party codeline.”
  7045. Appendix A
  7046. Install, Network, Secure, and
  7047. Administer Subversion
  7048. Subversion client installation is pretty straightforward, often
  7049. just requiring the right download for your operating system.
  7050. Running a server is a little more complicated, and many peo-
  7051. ple, especially those migrating from CVS, will want to run a
  7052. Subversion server on a Unix platform. Subversion’s database
  7053. backend also requires a different backup strategy than a plain
  7054. file-based version control system. This chapter includes Win-
  7055. dows and Linux instructions for installing Subversion, getting
  7056. your repository on the network, and backing it up in case the
  7057. worst should happen. There’s also a discussion on securing
  7058. your repository so prying eyes can’t get at your data.
  7059. A.1 Installing Subversion
  7060. Subversion comes packaged for a variety of operating sys-
  7061. tems. 1 If you’re using a Unix-based system, Subversion might
  7062. be available as an official package, so check first using your
  7063. package manager.
  7064. Windows Installation
  7065. The friendly Windows installer makes short work of installing
  7066. Subversion, even putting the binaries in your path. If you’re
  7067. 1 Go to
  7068. http://subversion.tigris.org/project_packages.html for
  7069. the full set of packages.
  7070. I NSTALLING S UBVERSION 152
  7071. planning on installing Apache as well, install it before Sub-
  7072. version. That way, the Subversion installer will automatically
  7073. copy Subversion’s Apache modules to the right places.
  7074. Linux Installation
  7075. Here we’ll cover installation on Fedora Core 5, which happens
  7076. to include Subversion 1.3 as a standard package. You can
  7077. either use the Fedora Package Manager to install the packages
  7078. or download them by hand.
  7079. To use the GUI package manager, choose Applications > Add/
  7080. Remove Software. In the “Servers” category, make sure “Web
  7081. Server” is selected. Under “Development,” check “Develop-
  7082. ment Tools” then click the Optional Packages button to make
  7083. sure Subversion is selected. Hit the Update button to apply
  7084. the changes.
  7085. To install from the command line, use the yum package man-
  7086. ager:
  7087. root > yum install httpd subversion mod dav svn
  7088. Dependencies Resolved
  7089. =================================================================
  7090. Package Arch Version Repository Size
  7091. =================================================================
  7092. Installing:
  7093. httpd i386 2.2.0-5.1.2 core 1.1 M
  7094. mod dav svn i386 1.3.0-4.2 core 65 k
  7095. subversion i386 1.3.0-4.2 core 2.1 M
  7096. Transaction Summary
  7097. =================================================================
  7098. Install 3 Package(s)
  7099. Update 0 Package(s)
  7100. Remove 0 Package(s)
  7101. Total download size: 3.3 M
  7102. Is this ok [y/N]:
  7103. yum lets you know it’s going to install the requested packages,
  7104. along with apr and apr-util which are required for Subver-
  7105. sion to work. After downloading the packages you should see
  7106. something like this:
  7107. Running Transaction
  7108. Installing: httpd ######################### [1/3]
  7109. Installing: subversion ######################### [2/3]
  7110. Installing: mod dav svn ######################### [3/3]
  7111. Installed: httpd.i386 0:2.2.0-5.1.2 mod dav svn.i386
  7112. 0:1.3.0-4.2 subversion.i386 0:1.3.0-4.2
  7113. Complete!
  7114. Subversion is now installed and ready to go.
  7115. N ETWORKING WITH SVNSERVE 153
  7116. A.2 Networking with svnserve
  7117. svnserve is a simple network server for Subversion. It’s fast
  7118. and lightweight, and it’s suitable for use on a corporate LAN
  7119. where traffic is safe from eavesdroppers.
  7120. svnserve on Windows
  7121. To start svnserve on Windows, go to your command prompt
  7122. and type
  7123. C: \> start svnserve --daemon --root c: \ svn-repos
  7124. A new window will pop open with the title svnserve.exe . If
  7125. you’re using Windows XP or have other firewalling software
  7126. installed, you may be asked whether the server should be
  7127. allowed to accept network connections, in which case choose
  7128. to unblock svnserve . We’ve asked svnserve to start in daemon
  7129. mode with the --daemon option (Windows doesn’t actually run
  7130. it as a daemon; this option is a quirk needed to get svnserve to
  7131. start), and we’re allowing access to the repository named with
  7132. the --root argument.
  7133. Popping open a new window isn’t great, since you might close
  7134. it accidentally. You can add a /B just after the start command
  7135. if you want svnserve to run without its own window, but in this
  7136. case you’ll need to use Task Manager to kill it off when you’re
  7137. done.
  7138. If you’d like svnserve to run whenever your Windows server
  7139. boots, you’ll need to install it as a service. Magnus Norddahl
  7140. maintains a simple service wrapper called svnservice , available
  7141. from http://dark.clansoft.dk/˜mbn/svnservice/ .
  7142. svnserve on Unix
  7143. Starting svnserve is very similar on Unix:
  7144. home > svnserve --daemon --root /home/mike/svn-repos
  7145. Your command prompt returns immediately leaving svnserve
  7146. running as a daemon. Running ps should show the process
  7147. still running.
  7148. Try accessing the repository from a different machine on your
  7149. network. The example server for this book is called olio , so
  7150. you’d run
  7151. N ETWORKING WITH SVN + SSH 154
  7152. work > svn co svn://olio/sesame/trunk vizier
  7153. A vizier/Number.txt
  7154. A vizier/Day.txt
  7155. Checked out revision 7.
  7156. If this doesn’t work, you might need to check if there’s a
  7157. firewall between the two machines. If there is (for example,
  7158. ZoneAlarm, Windows XP’s built-in firewall, or a Unix firewall),
  7159. you’ll need to make sure the machine running svnserve can
  7160. accept connections on TCP port 3690.
  7161. Once set up, you should secure your repository, because by
  7162. default svnserve allows read-only anonymous access to every-
  7163. thing. Refer to Section A.5, svnserve, on page 163 for more
  7164. details.
  7165. A.3 Networking with svn+ssh
  7166. Windows doesn’t usually support incoming SSH connections,
  7167. so this section covers Unix configuration only. You might be
  7168. able to get Putty working as a Windows SSH server, but it’s
  7169. definitely not for the faint of heart!
  7170. When a user specifies a svn+ssh scheme to access the repos-
  7171. itory, the Subversion client runs SSH to connect to the server.
  7172. This means each user needs an account on the server, and the
  7173. password they’re asked for is their Unix account password.
  7174. If your users have public/private key pairs or are running
  7175. an SSH agent, Subversion automatically takes advantage of
  7176. those features.
  7177. Subversion tries to run svnserve -t on the server in order to
  7178. access the repository. If Subversion complains it can’t find
  7179. svnserve , make sure the default path on the server contains the
  7180. svnserve binary. Because Subversion starts svnserve using
  7181. the -t (tunnel) option, you don’t need to have it running as a
  7182. daemon like you do with plain svn connections.
  7183. Once the SSH connection is established and svnserve is run-
  7184. ning in tunnel mode, Subversion will attempt to access the
  7185. repository’s files. It does this as the same user who authen-
  7186. ticated via SSH, which means all the users of your repository
  7187. need read and write access to the repository files. Further-
  7188. N ETWORKING WITH SVN + SSH 155
  7189. more, any new files that are created need to be readable and
  7190. writable for all the other users. 2
  7191. In order for multiple Unix users to access the repository, they
  7192. should all be in a single Unix group and have a umask of 002
  7193. when running svnserve via SSH. You also need to set the group
  7194. “sticky bit” on the repository directories. Here’s a step-by-step
  7195. guide to setting this up.
  7196. First create a Unix group for everyone using Subversion, and
  7197. add each user to the group. These commands are Linux spe-
  7198. cific, so you might need to tweak them a bit for your flavor of
  7199. Unix:
  7200. root > /usr/sbin/groupadd subversion
  7201. root > /usr/sbin/usermod -G subversion mike
  7202. root > /usr/sbin/usermod -G subversion ian
  7203. Next, change the ownership of your repository directory and
  7204. files to the new group, and set the group sticky bit for the
  7205. repository db directory:
  7206. root > chgrp -R subversion /home/svn-repos
  7207. root > chmod -R 770 /home/svn-repos
  7208. root > chmod g+S /home/svn-repos/db # g+t on BSD systems
  7209. Now try checking out from the repository. Here we’ll specify
  7210. an exact username for the remote machine, and the password
  7211. we’re asked for is our Unix password:
  7212. work > svn checkout \
  7213. svn+ssh://mike@olio/home/svn-repos/sesame/trunk \
  7214. sesame
  7215. mike@olio ' s password:
  7216. A sesame/Number.txt
  7217. A sesame/Day.txt
  7218. Checked out revision 7.
  7219. This is all a bit complicated, but well worth it if you’d like to
  7220. take advantage of SSH for securing your connections. More
  7221. information is available online. 3
  7222. 2 Getting this part wrong is the most common cause for “wedged” reposito-
  7223. ries. During the commit BDB might decide to create new files that are part of
  7224. the repository. If these aren’t writable by other users their Subversion clients
  7225. will hang trying to access the repository.
  7226. 3 http://svnbook.red-bean.com/en/1.1/ch06s03.html#
  7227. svn-ch-6-sect-3.4
  7228. N ETWORKING WITH SVN + SSH 156
  7229. Troubleshooting an SSH Connection
  7230. Connecting to a repository using svn+ssh requires quite a few
  7231. programs to be working and configured correctly. Unfortu-
  7232. nately, Subversion’s error messages are sometimes less infor-
  7233. mative than they could be. Here’s a rough guide to things that
  7234. can go wrong and how to fix them.
  7235. svn: The system cannot find the file specified. (Windows)
  7236. Subversion is complaining that it can’t find “the file speci-
  7237. fied.” In this case it’s looking for ssh in order to make a secure
  7238. connection (the svn command is being found just fine). The
  7239. usual fix for this is to edit your Subversion configuration as
  7240. described back in Section 5.1, svn+ssh, on page 57 and make
  7241. sure that plink.exe is available in your path.
  7242. svn: No such file or directory (Unix)
  7243. Similar to the Windows “cannot find file specified” problem,
  7244. Subversion is unable to find the ssh command on your system.
  7245. This might mean ssh isn’t installed on your computer.
  7246. Subversion just seems to hang (Windows)
  7247. Bring up Task Manager, and see if plink.exe is running. If it’s
  7248. running but Subversion isn’t displaying any output, it could
  7249. be because plink is waiting for user input. This can happen
  7250. when you connect to an SSH server for the first time and need
  7251. to accept the server key. Try running plink on its own, saying
  7252. “yes” when asked to store the key in Putty’s cache:
  7253. work > plink mike@olio.mynetwork.net echo hello
  7254. The server ' s host key is not cached in the registry. You
  7255. have no guarantee that the server is the computer you
  7256. think it is.
  7257. The server ' s rsa2 key fingerprint is:
  7258. ssh-rsa 1024 c3:82:fd:a6:b4:5d:23:f2:1a:f8:8b:04:be:c3
  7259. If you trust this host, enter "y" to add the key to
  7260. PuTTY ' s cache and carry on connecting.
  7261. : : :
  7262. Store key in cache? (y/n) y
  7263. mike@olio.mynetwork.net ' s password:
  7264. hello
  7265. N ETWORKING WITH A PACHE 157
  7266. svnserve: command not found
  7267. svn: Connection closed unexpectedly
  7268. Either or both of these lines is printed by the Subversion client
  7269. when it can’t find svnserve on the server. The SSH connection
  7270. has been established and you’ve authenticated as a Unix user,
  7271. but svnserve isn’t in the user’s path.
  7272. Subversion always attempts to run svnserve -t on the remote
  7273. server, so unfortunately you can’t fix the problem by telling
  7274. the client where Subversion is installed. You’ll need to change
  7275. the default path on the server, perhaps by editing /etc/profile .
  7276. Once you’ve got svnserve in the path, you should be able to
  7277. test from the client like this:
  7278. work > ssh mike@olio.mynetwork.net svnserve -t
  7279. ( success ( 1 2 ( ANONYMOUS EXTERNAL ) ( edit-pipeline ) ) )
  7280. The success message with all the brackets is the start of the
  7281. svn protocol between the Subversion client and server and
  7282. means svnserve has been found correctly.
  7283. svn: No repository found in
  7284. ’svn+ssh://myserver/home/svn-repos’
  7285. Subversion has successfully connected using SSH and started
  7286. svnserve . However, svnserve can’t find the repository. Check
  7287. that you’re using the correct path to the repository and that
  7288. you have sufficient permissions to read and create files in the
  7289. repository directory.
  7290. A.4 Networking with Apache
  7291. In this section we’ll show how to install Apache and configure
  7292. it to host a Subversion repository. Unix installation instruc-
  7293. tions vary a bit depending on the exact flavor of Unix, but
  7294. good instructions are available online. We’ll again be using
  7295. Fedora Core 5 as our example Unix platform.
  7296. The Subversion book from the Subversion developers them-
  7297. selves is probably the best complete reference and is available
  7298. at http://svnbook.red-bean.com/ [CSFP].
  7299. N ETWORKING WITH A PACHE 158
  7300. The “How-To” section on the Subversionary web site 4 includes
  7301. networking instructions for a number of operating systems,
  7302. including RedHat and Windows.
  7303. Apache on Windows
  7304. Download and Install Apache
  7305. Apache is open-source software, and you can download it for
  7306. free from http://httpd.apache.org/download.cgi .
  7307. For a Windows installation, you can download either an . exe
  7308. or an . msi . The MSI is a Windows Installer package and is a
  7309. smaller download, so that’s probably your best bet. Subver-
  7310. sion requires at least Apache 2.0.48—in this example we’re
  7311. using 2.0.50.
  7312. Run the installer, read the first couple of screens including
  7313. the license agreement and installation notes, and you should
  7314. get to a screen similar to that in Figure A.1 on the next page.
  7315. It’s important to get the info on this screen correct, or users
  7316. might have trouble connecting to Apache. If you’re not sure of
  7317. the settings to use, ask a network administrator to help you.
  7318. We’ll install Apache for the current user only, on port 8080.
  7319. Windows machines often already have a web server enabled
  7320. using the normal HTTP port 80, and we don’t want our new
  7321. Apache server to conflict. If you’re setting up a Subversion
  7322. repository and want to use port 80, make sure Internet Infor-
  7323. mation Services (IIS) has its web server switched off.
  7324. At the next step choose Typical Installation, and stick with
  7325. the default directory for installing Apache. You’ll see a few
  7326. command windows pop open as Apache installs, followed by
  7327. a message informing you that installation was successful.
  7328. At the moment, Apache isn’t running because we selected the
  7329. “just for the current user” option when installing. To start
  7330. Apache, choose Start > All Programs > Apache HTTP Server
  7331. 2.0.50 > Control Apache Server > Start Apache in Console. A
  7332. command prompt window will appear, which means Apache is
  7333. 4 http://www.subversionary.org/
  7334. N ETWORKING WITH A PACHE 159
  7335. Figure A.1: Apache Server Name Configuration
  7336. running. 5 Open a web browser to http://localhost:8080
  7337. and you should see a test page like the one in Figure A.2 on
  7338. the following page.
  7339. Install Subversion’s Apache Modules
  7340. Subversion integrates with Apache using a number of binary
  7341. modules that need to be installed in the right places for every-
  7342. thing to work properly.
  7343. If you’re using Windows, open C:\Program Files\Subversion\httpd
  7344. and copy mod authz svn.so and mod dav svn.so into the direc-
  7345. tory C:\Program Files\Apache Group\Apache2\modules . Then go
  7346. to C:\Program Files\Subversion\bin , and copy the file libdb42.dll
  7347. into C:\Program Files\Apache Group\Apache2\bin . If you already
  7348. 5 We were going to include a screenshot of the Apache console window,
  7349. but Dave decided it looked like one of those “Bournemouth by Night” joke
  7350. postcards, so it got the boot. Don’t worry when the Apache window comes up
  7351. and there’s no output—this is how it’s supposed to look.
  7352. N ETWORKING WITH A PACHE 160
  7353. Figure A.2: Apache Test Page
  7354. have Apache installed, the Subversion installer will do this
  7355. copying for you when you install Subversion.
  7356. Configuring Apache
  7357. Configuring Apache requires editing . conf files inside your
  7358. Apache install. The files you need to edit vary a little between
  7359. systems—Windows uses a single httpd.conf , as do many fla-
  7360. vors of Unix, and Red Hat Linux uses a number of smaller
  7361. files within a conf.d directory.
  7362. Choose Start > All Programs > Apache HTTP Server 2.0.50 >
  7363. Configure Apache Server > Edit the Apache httpd.conf Config-
  7364. uration file. This will open Notepad, everyone’s favorite editor,
  7365. with the main Apache configuration file.
  7366. Scroll down to the section of the file that reads “Dynamic
  7367. Shared Object (DSO) Support.” You’ll see a large number of
  7368. LoadModule commands, each of which activates extra func-
  7369. tionality in Apache. At the bottom of the list, add the following
  7370. two lines:
  7371. N ETWORKING WITH A PACHE 161
  7372. Joe Asks...
  7373. DAV, WebDAV, DeltaV??
  7374. As part of its integration with Apache, Subversion uses
  7375. WebDAV as the protocol between client and server.
  7376. WebDAV stands for “Web-based Distributed Author-
  7377. ing and Versioning” and is an extension of the HTTP
  7378. protocol. Instead of rolling their own network proto-
  7379. col, the Subversion developers decided to leverage
  7380. WebDAV.
  7381. Reuse brings a number of advantages, in both speed
  7382. of development and compatibility with other clients.
  7383. For example, both Windows and Mac OS X can con-
  7384. nect to a WebDAV server and make it available as a
  7385. network drive.
  7386. For further information on WebDAV, including client
  7387. configuration, see http://www.webdav.org/ .
  7388. LoadModule dav svn module modules/mod dav svn.so
  7389. LoadModule authz svn module modules/mod authz svn.so
  7390. Next, scroll up a little, and uncomment the existing line for
  7391. dav module :
  7392. LoadModule dav module modules/mod dav.so
  7393. Finally, scroll down to the bottom of the file, and add the
  7394. following section:
  7395. < Location /svn-repos >
  7396. DAV svn
  7397. SVNPath c: \ svn-repos
  7398. < /Location >
  7399. This tells Apache that URLs starting with /svn-repos should
  7400. use the Subversion DAV module and that the repository is in
  7401. c:\svn-repos .
  7402. If Apache is still running, stop it by closing its command
  7403. window. Then start Apache by using the Start Apache in
  7404. Console menu item. Now open your web browser, and hit
  7405. http://localhost:8080/svn-repos/ . If Subversion and
  7406. Apache are configured correctly, you’ll see your repository
  7407. N ETWORKING WITH A PACHE 162
  7408. Figure A.3: Subversion Repository Browsing
  7409. and the Sesame project, as in Figure A.3 . Try browsing
  7410. around the repository—clicking any file will display the lat-
  7411. est checked-in version of that file, and clicking a directory will
  7412. navigate you around.
  7413. Apache on Red Hat Linux
  7414. Fedora Core 5 usually comes with Apache installed as stan-
  7415. dard. If you’re following the installation instructions in this
  7416. chapter, you probably already installed Apache, Subversion,
  7417. and the Apache integration module mod dav svn . If not, fire
  7418. up your package manager and get those installed.
  7419. Configure Apache
  7420. On Red Hat Linux, Apache uses a number of conf files within
  7421. /etc/httpd/conf.d . Installing mod dav svn adds a new subver-
  7422. sion.conf file to that directory, which you’ll need to edit in order
  7423. to point at your repository. Other flavors of Unix stick with a
  7424. single httpd.conf file inside /etc/httpd .
  7425. S ECURING S UBVERSION 163
  7426. The contents of subversion.conf hint at security settings we’ll be
  7427. covering in Section A.5, Apache Security, on page 165, but for
  7428. now just uncomment enough that it points to your repository:
  7429. < Location /svn-repos >
  7430. DAV svn
  7431. SVNPath /home/svn-repos
  7432. < /Location >
  7433. Make sure the svn-repos directory is owned by the Apache user,
  7434. and restart the Apache web server:
  7435. root > chown -R apache /home/svn-repos
  7436. root > service httpd restart
  7437. Stopping httpd: [ OK ]
  7438. Starting httpd: [ OK ]
  7439. At this point your repository is unsecured, allowing read and
  7440. write access to anonymous users. Don’t leave it like this! Sec-
  7441. tion A.5, Apache Security, on page 165 details how to secure
  7442. your Apache hosted repository.
  7443. A.5 Securing Subversion
  7444. When it comes to accessing a Subversion repository, security
  7445. lies in two main areas: user authentication and path-based
  7446. permissions. User authentication is about making sure peo-
  7447. ple connecting to the repository are authorized to do so; it’s
  7448. basically password-protecting your data. Anyone supplying a
  7449. valid username and password is granted access to the reposi-
  7450. tory. Path-based security goes further, differentiating between
  7451. users and granting or denying access to individual directories
  7452. in the repository.
  7453. svnserve
  7454. By default, svnserve sets up a read-only repository. To get
  7455. read/write access, we’ll need to edit svnserve.conf , which lives
  7456. inside the svn-repos/conf directory. When you create a repos-
  7457. itory, svnserve.conf looks something like the one in Figure A.4
  7458. on the following page.
  7459. If you’re familiar with . conf files, you’ll see that the entire file
  7460. is commented out (lines starting with # are comments). Whilst
  7461. Subversion is trying to be helpful and give us some hints for
  7462. writing a config file, most people just end up confused by
  7463. S ECURING S UBVERSION 164
  7464. Figure A.4: Defaultsvnserve.conf
  7465. the file. Let’s just ignore the defaults and create a simple
  7466. svnserve.conf :
  7467. [general]
  7468. anon-access = read
  7469. auth-access = write
  7470. password-db = passwd
  7471. svnrepos/conf/svnserve.conf
  7472. This tells svnserve to allow anonymous read-only access to the
  7473. repository and to allow read/write access for authenticated
  7474. users. We also tell svnserve to look for usernames and pass-
  7475. words in a file called passwd . In the same conf directory, create
  7476. a password file as follows:
  7477. [users]
  7478. mike=secret
  7479. dave=n1nja123
  7480. ian=b4n4n4
  7481. svnrepos/conf/passwd
  7482. We’ve defined three users, each with their own password. In
  7483. order to commit a change to the repository, a client will have
  7484. to provide a valid username and password.
  7485. If you are using Subversion 1.3, svnserve can provide path-
  7486. based security using the same security configuration file as
  7487. mod authz svn . If you’re using an earlier version of Subver-
  7488. S ECURING S UBVERSION 165
  7489. sion or have not configured path-based security, a user who
  7490. has read or write access can get to the whole repository.
  7491. To enable path-based security, add the following line to your
  7492. svnserve.conf file:
  7493. authz-db = authz
  7494. Next, create the authorization database authz as described in
  7495. Section A.5, Path-Based Security, on page 167.
  7496. svn+ssh
  7497. Connecting to a repository using svn+ssh uses Unix security
  7498. to determine if a user can access the repository. If they can
  7499. access the repository’s database files they have read/write
  7500. access to the repository.
  7501. As with svnserve , it’s possible to use a hook script to achieve
  7502. path-based security with svn+ssh . It’s also possible to host
  7503. more than one repository on the same Unix server, with dif-
  7504. ferent groups of users granted access to each one, using stan-
  7505. dard Unix permissions.
  7506. Apache Security
  7507. If you’ve been following the instructions in this chapter so far,
  7508. you’ll have a repository online using Apache with only a very
  7509. basic configuration. When set up like this, your repository will
  7510. have read/write access for everyone, including anonymous
  7511. users.
  7512. We’d better fix that up quickly.
  7513. Apache provides a wealth of authentication options for users.
  7514. Here we’ll just set up basic password authentication, but you
  7515. can do fancier stuff including authenticating against a Win-
  7516. dows domain. Basic authentication requires a password file
  7517. with all your usernames and passwords in it, and you need to
  7518. use the htpasswd utility that comes with Apache to create it.
  7519. If you’re on Windows, open a command prompt and change to
  7520. the C:\Program Files\Apache Group\Apache2\bin directory, and
  7521. then run
  7522. bin > htpasswd -c -m c: \ svn-repos \ conf \ htpasswd mike
  7523. New password: ******
  7524. Re-type new password: ******
  7525. Adding password for user mike
  7526. S ECURING S UBVERSION 166
  7527. On Unix, htpasswd should be in your path already, so run
  7528. home > htpasswd -c -m /home/svn-repos/conf/htpasswd mike
  7529. New password: ******
  7530. Re-type new password: ******
  7531. Adding password for user mike
  7532. Once the file is created, you can add new users to it by drop-
  7533. ping the -c flag:
  7534. bin > htpasswd -m c: \ svn-repos \ conf \ htpasswd dave
  7535. New password: ********
  7536. Re-type new password: ********
  7537. Adding password for user dave
  7538. Next we need to tell Apache to authenticate users before they
  7539. are allowed to access the repository. We can do this by requir-
  7540. ing a valid user for all operations, or just for those folks who
  7541. actually modify the repository (and thus leave anonymous
  7542. browsing enabled). To lock things down completely, modify
  7543. your Apache Location directive as follows:
  7544. < Location /svn-repos >
  7545. DAV svn
  7546. SVNPath c: \ svn-repos
  7547. AuthType Basic
  7548. AuthName "Subversion Repository"
  7549. AuthUserFile c: \ svn-repos \ conf \ htpasswd
  7550. Require valid-user
  7551. < /Location >
  7552. If instead you’d like anonymous read-only access, configure
  7553. Apache like this:
  7554. < Location /svn-repos >
  7555. DAV svn
  7556. SVNPath c: \ svn-repos
  7557. AuthType Basic
  7558. AuthName "Subversion Repository"
  7559. AuthUserFile c: \ svn-repos \ conf \ htpasswd
  7560. < LimitExcept GET PROPFIND OPTIONS REPORT >
  7561. Require valid-user
  7562. < /LimitExcept >
  7563. < /Location >
  7564. Your configuration changes will take effect once you restart
  7565. Apache.
  7566. If you have an SSL certificate for your Apache server, you can
  7567. require a secure connection when accessing the repository.
  7568. This will encrypt all traffic between the Subversion client and
  7569. the repository, including passwords and file contents, and is
  7570. S ECURING S UBVERSION 167
  7571. generally a good idea if you’re making your repository avail-
  7572. able over the Internet. Edit your Apache configuration once
  7573. more, and add SSLRequireSSL :
  7574. < Location /svn-repos >
  7575. DAV svn
  7576. SVNPath c: \ svn-repos
  7577. AuthType Basic
  7578. AuthName "Subversion Repository"
  7579. AuthUserFile c: \ svn-repos \ conf \ htpasswd
  7580. Require valid-user
  7581. SSLRequireSSL
  7582. < /Location >
  7583. Path-Based Security
  7584. Both svnserve and Apache can be configured to use path-based
  7585. security, which can restrict access to directories within the
  7586. repository. This is accomplished using mod authz svn (for
  7587. Apache) or the authz-db configuration setting (for svnserve ).
  7588. Both use a common file format for defining the authorization
  7589. database.
  7590. To enable the authorization database in Apache, edit your sub-
  7591. version.conf file and add the following section to your repository
  7592. definition:
  7593. AuthzSVNAccessFile c: \ svn-repos \ conf \ authz
  7594. The authorization database file contains group definitions and
  7595. path security definitions. The [groups] config section names
  7596. groups and the users within them. Path security definitions
  7597. associate repository paths with access permissions for users
  7598. or groups of users. The access granted can be read-only, read-
  7599. write, or no access, using “r”, “rw” or “”, respectively.
  7600. As an example, suppose we have developers Fred and Wilma
  7601. who should be able to read and write the Sesame project tree,
  7602. with everyone else just able to read the tree. The authz file
  7603. would look like this:
  7604. [groups]
  7605. developers = fred, wilma
  7606. [/projects/sesame]
  7607. @developers = rw
  7608. * = r
  7609. svnrepos/conf/authz
  7610. The new, top-secret “Project Blue” can only be accessed by
  7611. Barney, our smartest and most trustworthy developer. We’ll
  7612. need the following security definition:
  7613. S ECURING S UBVERSION 168
  7614. [/projects/blue]
  7615. barney = rw
  7616. * =
  7617. Security permissions are inherited from parent directories to
  7618. their children. You can tighten (or loosen) permissions by
  7619. including a more specific security definition. To provide the
  7620. test team write access to Sesame’s testing directory, the au-
  7621. thorization file should look like this:
  7622. [/projects/sesame]
  7623. @developers = rw
  7624. * = r
  7625. [/projects/sesame/testing]
  7626. @testers = rw
  7627. If you’re using the SVNParentPath directive to network mul-
  7628. tiple repositories, you can use [repository:path] syntax to
  7629. refer to a specific repository. If the administrators group
  7630. should get read-write access to documents stored under the
  7631. admin repository, use the following security definition:
  7632. [admin:/docs]
  7633. @administrators = rw
  7634. In the previous example the only people able to access the
  7635. docs directory will be the administrators. In fact, the only
  7636. path within the admin repository that anyone can access will
  7637. be docs because Subversion disables access to all directo-
  7638. ries unless explicitly instructed otherwise. It’s often useful to
  7639. specify read-only access everywhere in every repository, which
  7640. looks like this:
  7641. [/]
  7642. * = r
  7643. Access Control with Hook Scripts
  7644. Subversion can be configured with a number of hook scripts hook scripts
  7645. that are run on the server at certain times during a commit.
  7646. The pre-commit hook runs before a commit is allowed to pro-
  7647. ceed, and if it returns a nonzero exit status, Subversion dis-
  7648. allows the commit.
  7649. Pre-commit hooks have access to information about which
  7650. files are being changed, as well as the user attempting to
  7651. change them. We can use this information to set up path-
  7652. based security—if a user attempts to change a file or directory
  7653. S ECURING S UBVERSION 169
  7654. to which they have not been granted access, our hook script
  7655. exits with a one and Subversion stops the commit.
  7656. Subversion comes with commit-access-control.pl , which should
  7657. get installed somewhere on your machine when you install
  7658. Subversion. For Fedora Core 5, for example, it’s bundled with
  7659. the Subversion documentation in /usr/share/doc .
  7660. Copy commit-access-control.pl to the hooks directory in your
  7661. repository. Also copy commit-access-control.cfg.example , which
  7662. you should rename to ditch the . example extension.
  7663. Inside your hooks directory, rename pre-commit.tmpl and make
  7664. it executable:
  7665. hooks > mv pre-commit.tmpl pre-commit
  7666. hooks > chmod +x pre-commit
  7667. The pre-commit template does two things – it checks that the
  7668. log message being used contains some text (which you may or
  7669. may not be worried about) and then calls the access control
  7670. script to check the user’s permissions.
  7671. Configure the permissions in commit-access-control.cfg , and
  7672. you should be ready to go. Python fans might be interested
  7673. in svnperms.py , included in the Subversion distribution, which
  7674. works in a similar fashion.
  7675. Hook scripts that do more than simple read-only file access
  7676. may require you configure security settings on your system.
  7677. If you are using Apache to host your Subversion repository
  7678. the hook scripts will run as the Apache user, usually httpd or
  7679. nobody, rather than a regular user. This may mean that your
  7680. scripts cannot perform operations such as modifying files or
  7681. sending emails, depending on your exact configuration. Many
  7682. Linux distributions now include SELinux security enhance-
  7683. ments that make it impossible for particular programs—such
  7684. as the Apache web server—to access files outside of their
  7685. usual configuration and web site directories. In this case you
  7686. may need to relax the restrictions to get your hook scripts to
  7687. work properly. You can usually check the security log in order
  7688. to see whether your scripts are being blocked by SELinux or
  7689. other security settings.
  7690. B ACKING U P Y OUR R EPOSITORY 170
  7691. A.6 Backing Up Your Repository
  7692. Backing up your source code makes a lot of sense—after all,
  7693. your developers are assuming the repository is a safe place to
  7694. store all their hard work. Subversion uses either Berkeley DB
  7695. or the “fsfs” filesystem as the backend for your repository, and
  7696. these can’t be backed up like a regular file. If someone makes
  7697. a change to the repository during a backup, the repository
  7698. files may be in an inconsistent state, causing the backup to
  7699. be invalid. 6
  7700. Subversion provides the svnadmin dump command to extract
  7701. the contents of a repository into a portable dumpfile. A dump- dumpfile
  7702. file contains information about each revision in the repository
  7703. and can be backed up like a regular file. The svnadmin load
  7704. command takes the contents of a dumpfile and loads it into a
  7705. repository. This can be used to restore from a backup or to
  7706. copy a repository to another location.
  7707. Full Backups
  7708. Depending on how large your repository is, and how often you
  7709. want to make a backup, you might be able to get away with
  7710. just doing complete dumps of your repository. The following
  7711. command creates a complete dump of the repository:
  7712. mike > svnadmin dump
  7713. ˜ /svn-repos
  7714. > dumpfile.041113
  7715. * Dumped revision 0.
  7716. * Dumped revision 1.
  7717. : : :
  7718. * Dumped revision 48.
  7719. Subversion dumps every revision in the repository to the con-
  7720. sole, which we then save in dumpfile.041113 . The resulting file
  7721. contains everything the repository contains. A typical dump
  7722. is highly compressible and ready to back up.
  7723. Creating a dumpfile using svnadmin will always produce a con-
  7724. sistent snapshot of your repository, even if changes are being
  7725. committed whilst the dump is created. This means you don’t
  7726. 6 Using an “fsfs” repository
  7727. you’re more likely to get a consistent
  7728. backup, especially if you back up the files in a particular order.
  7729. See http://svn.collab.net/repos/svn/trunk/notes/fsfs for more
  7730. details.
  7731. B ACKING U P Y OUR R EPOSITORY 171
  7732. need to shut down access to the repository whilst svnadmin
  7733. dump is running.
  7734. To restore from the dumpfile into a new repository, use svnad-
  7735. min load . First we create a new repository (the old one might
  7736. not be totally corrupt, so don’t delete it), and then load the
  7737. dumpfile:
  7738. mike > svnadmin create svn-repos2
  7739. mike > svnadmin load svn-repos2 < dumpfile.041113
  7740. <<< Started new transaction, based on original revision 1
  7741. * adding path : sesame ... done.
  7742. * adding path : sesame/trunk ... done.
  7743. * adding path : sesame/trunk/Day.txt ... done.
  7744. * adding path : sesame/trunk/Number.txt ... done.
  7745. ------- Committed revision 1 >>>
  7746. : : :
  7747. <<< Started new transaction, based on original revision 48
  7748. * adding path : sesame/trunk/common/HibernateHelper.java COPIED... done.
  7749. * adding path : sesame/trunk/contacts/Contacts.hbm.xml COPIED... done.
  7750. * editing path : sesame/trunk/contacts/Contacts.java ... done.
  7751. ------- Committed revision 48 >>>
  7752. Subversion replays each revision from the dumpfile and com-
  7753. mits to the repository. Once the load is complete, the reposi-
  7754. tory is ready to go and looks exactly as it did when the dump
  7755. was created.
  7756. Incremental Backups
  7757. Doing full backups every day is going to eat disk space pretty
  7758. fast. Fortunately, svnadmin dump takes an --incremental option,
  7759. along with --revision specifying a revision range, to produce
  7760. smaller dump files.
  7761. Let’s say you already have a dump file containing revisions
  7762. 1 to 100, but the repository is up to revision 104. You can
  7763. create an incremental dump file by running
  7764. work > svnadmin dump --incremental --revision 100:104 \
  7765. /home/svn-repos
  7766. Combining weekly backups with daily incrementals should
  7767. give you peace of mind without requiring crazy amounts of
  7768. disk space. With a bit of scripting, we can create a weekly
  7769. and daily backup routine that remembers the revision num-
  7770. bers for each backup.
  7771. The program that follows is the weekly backup script. As pre-
  7772. sented it’s a very basic Perl script, but it does demonstrate
  7773. B ACKING U P Y OUR R EPOSITORY 172
  7774. how to use svnlook youngest to find out what revision your
  7775. repository is currently on.
  7776. #!/usr/bin/perl -w
  7777. #
  7778. # Perform a weekly backup of a Subversion repository,
  7779. # logging the most-recently-backed-up revision so an
  7780. # incremental script can be run other days.
  7781. $ svn repos = "/home/mike/svn-repos" ;
  7782. $ backups dir = "/home/mike/svn-backup" ;
  7783. $ next backup file = "weekly-full-backup." . ‘date +%Y%m%d‘ ;
  7784. $ youngest = ‘svnlook youngest $ svn repos‘ ;
  7785. chomp $ youngest;
  7786. print "Backing up to revision $ youngest \ n" ;
  7787. $ svnadmin cmd = "svnadmin dump --revision 0: $ youngest " .
  7788. " $ svn repos > $ backups dir/ $ next backup file" ;
  7789. ‘ $ svnadmin cmd‘ ;
  7790. print "Compressing dump file... \ n" ;
  7791. print ‘gzip -9 $ backups dir/ $ next backup file‘ ;
  7792. open(LOG, " >$ backups dir/last backed up" );
  7793. print LOG $ youngest;
  7794. close LOG;
  7795. svn-backup/weekly-backup.pl
  7796. Running this script dumps your repository into a file called
  7797. weekly-full-backup.yyyymmdd and compresses it using gzip . It
  7798. also saves the most recent revision to be backed up into a file
  7799. called last backed up :
  7800. svn-backup > ./weekly-backup.pl
  7801. Backing up to revision 638
  7802. * Dumped revision 0.
  7803. * Dumped revision 1.
  7804. * Dumped revision 2.
  7805. : : :
  7806. * Dumped revision 638.
  7807. Compressing dump file...
  7808. The daily backup script uses the revision number saved by the
  7809. weekly script to dump just what has changed, rather than the
  7810. whole repository:
  7811. #!/usr/bin/perl -w
  7812. #
  7813. # Perform a daily backup of a Subversion repository,
  7814. # using the previous most-recently-backed-up revision
  7815. # to create just an incremental dump.
  7816. $ svn repos = "/home/mike/svn-repos" ;
  7817. $ backups dir = "/home/mike/svn-backup" ;
  7818. $ next backup file = "daily-incremental-backup." . ‘date +%Y%m%d‘ ;
  7819. open(IN, " $ backups dir/last backed up" );
  7820. $ previous youngest = < IN > ;
  7821. chomp $ previous youngest;
  7822. close IN;
  7823. $ youngest = ‘svnlook youngest $ svn repos‘ ;
  7824. B ACKING U P Y OUR R EPOSITORY 173
  7825. chomp $ youngest;
  7826. if( $ youngest eq $ previous youngest) {
  7827. print "No new revisions to back up. \ n" ;
  7828. exit 0;
  7829. }
  7830. # We need to backup from the last backed up revision
  7831. # to the latest (youngest) revision in the repository
  7832. $ first rev = $ previous youngest + 1;
  7833. $ last rev = $ youngest;
  7834. print "Backing up revisions $ first rev to $ last rev... \ n" ;
  7835. $ svnadmin cmd = "svnadmin dump --incremental " .
  7836. "--revision $ first rev: $ last rev " .
  7837. " $ svn repos > $ backups dir/ $ next backup file" ;
  7838. ‘ $ svnadmin cmd‘ ;
  7839. print "Compressing dump file... \ n" ;
  7840. print ‘gzip -9 $ backups dir/ $ next backup file‘ ;
  7841. open(LOG, " >$ backups dir/last backed up" );
  7842. print LOG $ last rev;
  7843. close LOG;
  7844. svn-backup/daily-backup.pl
  7845. Running this script after some changes have been made will
  7846. dump just the new revisions:
  7847. svn-backup > ./daily-backup.pl
  7848. Backing up revisions 639:641
  7849. * Dumped revision 639.
  7850. * Dumped revision 640.
  7851. * Dumped revision 641.
  7852. Compressing dump file...
  7853. The daily incremental backups are much smaller than a full
  7854. backup but don’t contain enough information to restore your
  7855. repository if disaster strikes. To do a restore, you need to
  7856. first load your most recent full backup, followed by each daily
  7857. backup:
  7858. svn-backup > mkdir newrepos
  7859. svn-backup > svnadmin create newrepos
  7860. svn-backup > zcat weekly-full-backup.20041129.gz | \
  7861. svnadmin load newrepos
  7862. <<< Started new transaction, based on original revision 1
  7863. * adding path : branches ... done.
  7864. * adding path : tags ... done.
  7865. * adding path : trunk ... done.
  7866. : : : :
  7867. svn-backup > zcat daily-incremental-backup.20041130.gz | \
  7868. svnadmin load newrepos
  7869. <<< Started new transaction, based on original revision 639
  7870. * editing path : trunk/ccnet/lib/NetReflector.dll ... done.
  7871. ------- Committed new rev 639 (loaded from original rev 639) >>>
  7872. : : : :
  7873. Appendix B
  7874. Migrating to Subversion
  7875. So you’re sold on the benefits of using Subversion. You like
  7876. its support for atomic commits, its changesets, its speedy net-
  7877. work protocols, and its real branching and merging. You’ve
  7878. even convinced your boss that Subversion is right for your
  7879. team. The only minor problem standing between you and
  7880. a glorious subversive victory is the half-dozen projects and
  7881. years of history you have in your existing version control tool.
  7882. Fortunately, the Subversion developers thought people might
  7883. like to keep their old history around and have provided tools
  7884. to convert an existing CVS 1 repository to Subversion. You can
  7885. also find third-party tools to convert from ClearCase, Perforce,
  7886. and Visual SourceSafe.
  7887. Before jumping headfirst into the rest of this chapter, it’s
  7888. worth noting that not converting your old repository is also
  7889. a reasonable migration strategy. If you’re not too bothered
  7890. about being able to see historical information past the point
  7891. you started using Subversion, just export your source code
  7892. from the old version control tool, import it into Subversion,
  7893. and make the old repository read-only. If you really do need
  7894. that historical information it’s still there, albeit not in the new
  7895. Subversion repository.
  7896. In the rest of this chapter we’ll assume you want to convert all
  7897. your history and that we’re performing a migration from CVS
  7898. to Subversion.
  7899. 1 cvs2svn
  7900. will also convert an RCS repository to Subversion, since RCS is
  7901. the underlying format used by CVS.
  7902. G ETTING CVS 2 SVN 175
  7903. B.1 Getting cvs2svn
  7904. The cvs2svn project, along with the main Subversion project, is
  7905. hosted at Tigris. 2 Download the package corresponding to the
  7906. version of Subversion you’re using. As of this writing, cvs2svn
  7907. is only available for Subversion 1.2 or 1.3, the older versions
  7908. are no longer maintained.
  7909. cvs2svn is a Python script designed to run on Unix. Whilst you
  7910. might be able to get it to work on Windows, possibly using the
  7911. Cygwin 3 Linux emulation tools, we recommend using a real
  7912. Unix box. You’ll also need rcs installed because cvs2svn uses
  7913. it to access the contents of your CVS repository (you can get
  7914. away with having just CVS installed, but using “real” RCS is
  7915. a safer bet).
  7916. You can install cvs2svn on your system so everyone can see it
  7917. or just run it as a normal user. Both will work, but installing
  7918. system-wide is less work if you’re not Python savvy. Log in as
  7919. root, and run the following commands:
  7920. tmp > tar -xzf cvs2svn-1.2.1.tar.gz
  7921. tmp > cd cvs2svn-1.2.1
  7922. cvs2svn-1.2.1 > make install
  7923. ./setup.py install
  7924. running install
  7925. : : :
  7926. copying build/lib/cvs2svn rcsparse/compat.py - > ...
  7927. copying build/lib/cvs2svn rcsparse/debug.py - > ...
  7928. : : :
  7929. byte-compiling /usr/lib/python2.3/.../default.py to default.pyc
  7930. byte-compiling /usr/lib/python2.3/.../texttools.py to texttools.pyc
  7931. running install scripts
  7932. copying build/scripts-2.3/cvs2svn - > /usr/bin
  7933. changing mode of /usr/bin/cvs2svn to 775
  7934. B.2 Choosing How Much to Convert
  7935. cvs2svn will do a thorough job of converting your existing CVS
  7936. repository, including all your branches and tags. It will also
  7937. analyze the history, looking for files that were all changed at
  7938. about the same time with the same log message and con-
  7939. verting from CVS’s per-file revision history to Subversion’s
  7940. changeset style. All of this is quite a bit of work and will
  7941. take a while depending on the size of your CVS repository.
  7942. 2 http://cvs2svn.tigris.org/
  7943. 3 http://www.cygwin.com/
  7944. C ONVERTING Y OUR R EPOSITORY 176
  7945. If you don’t want to convert all of the history, you don’t have to
  7946. do so. Specifying which branches you’re interested in will save
  7947. both conversion time and space in the new Subversion repos-
  7948. itory. cvs2svn takes a whole bunch of command-line argu-
  7949. ments, but probably the most useful is --exclude , which
  7950. sets a regular expression for matching tags and branches
  7951. you’d like to skip during conversion.
  7952. It’s important to note that cvs2svn is designed for one-time
  7953. conversions from CVS to Subversion; it can’t be used to incre-
  7954. mentally sync changes between the two systems.
  7955. B.3 Converting Your Repository
  7956. Let’s assume you’d like a complete conversion of everything
  7957. in your CVS repository. The first step is to make sure every-
  7958. one has their changes checked into CVS and is aware you’re
  7959. about to do the conversion. Next take your CVS repository
  7960. offline so no more changes are committed to it. The final
  7961. preparation step, and the most important, is to make a copy
  7962. of your CVS repository. You need to copy the whole of your
  7963. CVSROOT because that’s what cvs2svn runs against. We’ll say
  7964. that again: make a copy of your CVS repository and use the
  7965. copy when converting.
  7966. cvs2svn works by creating a Subversion dumpfile, just like
  7967. those created with svnadmin dump . The dumpfile can then be
  7968. loaded into a Subversion repository with svnadmin load . You
  7969. can shortcut this process using cvs2svn ’s -s option, specifying
  7970. a directory in which you’d like to create the new Subversion
  7971. repository.
  7972. Here we’ll do a conversion of the Testsweet project, which is
  7973. hosted on SourceForge. The great thing about SourceForge
  7974. projects is the daily CVS snapshot where you can download a
  7975. compressed copy of the project’s repository, precisely the files
  7976. cvs2svn needs for conversion. 4 If you’d like to play with cvs2svn
  7977. but don’t want to use your own CVS repository to do so, this
  7978. might be just what you need.
  7979. 4 Testsweet’s daily CVS snapshot is at
  7980. http://cvs.sourceforge.net/
  7981. cvstarballs/testsweet-cvsroot.tar.bz2 .
  7982. C ONVERTING Y OUR R EPOSITORY 177
  7983. Copy your CVS repository to a scratch directory. In this exam-
  7984. ple we’ve put the Testsweet CVS repository into a local direc-
  7985. tory called testsweet , and we’re converting it to a Subversion
  7986. repository in testsweet-repos . cvs2svn will create the repository
  7987. directory and initialize it for us during the conversion:
  7988. tmp > cvs2svn -v -s testsweet-repos testsweet
  7989. ----- pass 1 -----
  7990. Examining all CVS ' ,v ' files...
  7991. testsweet/CVSROOT/checkoutlist,v
  7992. testsweet/CVSROOT/commitinfo,v
  7993. testsweet/CVSROOT/config,v
  7994. : : :
  7995. We asked for verboseness (the -v option), so cvs2svn produced
  7996. a whole bunch of output during the conversion. Testsweet is
  7997. a pretty small project so takes only a few seconds to convert.
  7998. When it’s done, cvs2svn prints a few statistics for us:
  7999. cvs2svn Statistics:
  8000. ------------------
  8001. Total CVS Files: 161
  8002. Total CVS Revisions: 218
  8003. Total Unique Tags: 1
  8004. Total Unique Branches: 0
  8005. CVS Repos Size in KB: 2716
  8006. Total SVN Commits: 10
  8007. First Revision Date: Fri Nov 21 18:12:21 2003
  8008. Last Revision Date: Thu Jun 24 12:35:29 2004
  8009. We can now use svn ls to browse the new repository, observing
  8010. how we have the usual trunk , tags , and branches directories:
  8011. tmp > svn ls file:///tmp/testsweet-repos
  8012. branches/
  8013. tags/
  8014. trunk/
  8015. tmp > svn ls file:///tmp/testsweet-repos/trunk
  8016. CVSROOT/
  8017. testsweet/
  8018. We now have the Testsweet project at the root level of the
  8019. repository, which might not be quite what you want. cvs2svn
  8020. allows us to specify the trunk , tags , and branches directories:
  8021. tmp > cvs2svn --trunk=testsweet/trunk \
  8022. --branches=testsweet/branches \
  8023. --tags=testsweet/tags \
  8024. -s testsweet-repos testsweet
  8025. Your newly converted repository is ready for use immediately.
  8026. Just fire up networking using svnserve or Apache, check out a
  8027. working copy, and carry on coding!
  8028. Appendix C
  8029. Third-Party Subversion Tools
  8030. Subversion comes as a set of command-line applications— svn ,
  8031. svnadmin , svnserve , etc. Whilst the command line is fairly easy
  8032. to use, most people like to use something a little more friendly.
  8033. Fortunately, Subversion provides a rich set of APIs to third-
  8034. party developers, so they can make add-on clients and tools.
  8035. C.1 TortoiseSVN
  8036. Tortoise is a front end for Subversion that integrates directly
  8037. with Windows Explorer. Once installed, you can see the state
  8038. of your files and directories just by browsing around your
  8039. computer. Tortoise puts little green ticks next to files that are
  8040. up-to-date and little red exclamation points next to files you’ve
  8041. modified. Tortoise also provides handy automation for tasks
  8042. such as resolving conflicts and managing tags and branches.
  8043. In this section we’ll use Tortoise to carry out some everyday
  8044. tasks that we’ve previously seen using the command line.
  8045. Downloading and Installing
  8046. Download TortoiseSVN, 1 and run the appropriate installer for
  8047. your version of Windows, which should pop up a welcome
  8048. screen. Pick a location to install to (or accept the default
  8049. directory C:\Program Files\TortoiseSVN ), and choose whether Tor-
  8050. toise should be available to every user on the computer or just
  8051. 1 TortoiseSVN can be found at
  8052. http://tortoisesvn.tigris.org/ .
  8053. T ORTOISE SVN 179
  8054. Figure C.1: The Tortoise Context Menu
  8055. yourself. That’s all you need to decide on; the installer will
  8056. take care of everything else.
  8057. The Tortoise installer will ask you to restart your computer.
  8058. Unlike most installers Tortoise is actually serious about this;
  8059. because it integrates with the Windows Explorer, it needs a
  8060. reboot to properly register itself.
  8061. Checking Out
  8062. Bring up an Explorer window, and change to a directory in
  8063. which you’d like to check out a working copy. Here we’ll be
  8064. using C:\work . Right-clicking in the directory will bring up a
  8065. menu including Tortoise’s Subversion integration, as shown
  8066. in Figure C.1 .
  8067. Choose Checkout... from the context menu, which will bring
  8068. up a dialog box asking what you’d like to check out. Use the
  8069. sandbox repository file:///C:/svn-repos/sesame/trunk , and check
  8070. T ORTOISE SVN 180
  8071. Figure C.2: The Freshly Checked-Out Sesame Project
  8072. out to C:\work\princess ( sesame is already a working copy, so
  8073. we’ll be starting fresh as Princess).
  8074. Tortoise will flash a progress box as it checks out the Sesame
  8075. project, leaving you with a new princess directory. Looking in
  8076. the directory, you’ll see Day.txt , Number.txt , and the rest of the
  8077. Sesame project. Since all the files are up-to-date, Tortoise
  8078. flags them with a little green check mark, as shown in Fig-
  8079. ure C.2 .
  8080. Making Changes
  8081. Make some changes to Number.txt , maybe capitalizing three.
  8082. After you save the file, Tortoise will flag it with a red exclama-
  8083. tion point. 2 The parent directory princess will also be flagged
  8084. red. Right-click Number.txt , and choose TortoiseSVN > Diff.
  8085. 2 You might need to hit F5 to get Windows to refresh the screen and display
  8086. the new icon.
  8087. T ORTOISE SVN 181
  8088. Figure C.3: Examining Your Changes
  8089. This will display a TortoiseMerge window showing the changes
  8090. you’ve made, similar to Figure C.3 .
  8091. Adding a new file is equally straightforward. Create a new file
  8092. called Year.txt , and save it in your working copy. Subversion
  8093. doesn’t know anything about this file yet, so Tortoise leaves
  8094. it undecorated. Right-click the new file, and choose Tortoise-
  8095. SVN > Add. Tortoise will pop up a window asking you to con-
  8096. firm the addition, which is more useful when you’re adding
  8097. a bunch of files at once. Click the OK button, and Tortoise
  8098. will add the file. Since Subversion now knows about Year.txt ,
  8099. it displays it with a blue “plus” icon.
  8100. Checking In
  8101. Right-click on the princess directory, and choose Commit....
  8102. Tortoise will show you all the files you’ve changed and prompt
  8103. you for a commit message, as shown in Figure C.4 on the next
  8104. page. At this point, you can decide not to commit a particular
  8105. file by unchecking its tickbox. If you’re not sure what you’ve
  8106. changed, double-clicking a file will pop up a diff window so
  8107. you can review your changes.
  8108. T ORTOISE SVN 182
  8109. Figure C.4: The TortoiseSVN Commit Window
  8110. Enter a commit message describing your changes (and more
  8111. important why you made those changes) and hit OK. Tortoise
  8112. will flash a window as it commits your changes to the reposi-
  8113. tory.
  8114. Resolving Conflicts
  8115. As part of our lightning-fast tour through Tortoise, let’s see
  8116. how it helps us when a conflict arises. Check out another
  8117. copy of the Sesame project, this time to C:\work\aladdin . We’ll
  8118. use this directory to simulate the actions of Aladdin, another
  8119. developer on our team. Edit Number.txt , changing five to cinco,
  8120. and then commit the changes.
  8121. T ORTOISE SVN 183
  8122. Figure C.5: Number.txt in Conflict
  8123. Now go back to the princess working copy, and edit the same
  8124. file, changing five to cinq, this time to keep our French cus-
  8125. tomers happy. Right-click the princess directory, choose Com-
  8126. mit, enter a log message, and hit OK. Tortoise will tell you that
  8127. Number.txt is out-of-date and the commit has failed. Tortoise
  8128. will also suggest you update your working copy in order to
  8129. commit.
  8130. Follow Tortoise’s suggestion, and run an update on princess by
  8131. right-clicking and choosing Update. The Tortoise update win-
  8132. dow will pop up whilst Tortoise gets the latest revision from
  8133. the repository, and depending on how fast your machine is
  8134. you might notice a line in red as it gets to Number.txt , denoting
  8135. a conflict. Tortoise will leave both Number.txt and princess dec-
  8136. orated with a warning triangle, as shown in Figure C.5 , to let
  8137. you know there’s a conflict.
  8138. Tortoise also saves some extra copies of Number.txt to help
  8139. resolve the conflict. You’ll notice . mine , . r9 , and . r10 in our
  8140. T ORTOISE SVN 184
  8141. Figure C.6: The Tortoise Merge Window
  8142. example so far. The first, . mine , is your version of the file,
  8143. including your modifications. The second, . r9 , contains the
  8144. base revision on which your changes are based—this is the
  8145. revision of the file before Princess started editing it. Finally,
  8146. . r10 contains the revision that conflicts with your changes.
  8147. These are the changes that Aladdin committed.
  8148. Fortunately, Tortoise comes with a three-way 3 merge tool that
  8149. makes it easy to resolve the conflicts. Right-click on the file
  8150. Number.txt , and choose TortoiseSVN > Edit Conflicts. Tortoise
  8151. will pop up a merge window like that in Figure C.6 .
  8152. TortoiseMerge displays the two sets of changes side by side,
  8153. along with a merge result in the bottom half of the window.
  8154. In this particular case we’re sure that cinq is correct, so we’re
  8155. going to pick our changes (the Princess’s changes rather than
  8156. Aladdin’s). Right-click the word cinq, and choose Use this text
  8157. block. Tortoise will update the merge result in the bottom
  8158. half of the window to show the result. If you have more than
  8159. 3 Three-way merging is so called because it merges an original version of
  8160. a file with two people’s changes.
  8161. IDE I NTEGRATION 185
  8162. one conflict, you can pick and choose between the two sets
  8163. of changes until you’re happy. Now just close the merge win-
  8164. dow. Tortoise will ask you if you’d like to save your changes;
  8165. say “yes” since you’re happy with the merge, and Tortoise will
  8166. close the merge window.
  8167. You’ll notice Tortoise is still decorating the file with a little
  8168. warning triangle. Now that we’ve resolved the conflict, we
  8169. need to tell Tortoise everything is okay. Right-click Number.txt ,
  8170. and choose TortoiseSVN > Resolved. Tortoise will clean up the
  8171. . mine , . r9 , and . r10 files and mark Number.txt with an exclama-
  8172. tion point showing you’ve modified it. Now finish checking in
  8173. as normal.
  8174. TortoiseSVN provides shortcuts for branching, tagging, and
  8175. merging, and whilst we don’t have space here to detail every-
  8176. thing, we do suggest you try it. We do just about have room
  8177. to plug the excellent repository browser, which you can get
  8178. to by choosing TortoiseSVN > Repo-Browser. This nifty little
  8179. tool enables you to nose around a repository without needing
  8180. a working copy. This comes in handy if you’re trying to figure
  8181. out where all the branches are for a project or where exactly
  8182. they’ve imported vendor source code. Figure C.7 on the fol-
  8183. lowing page shows us perusing the Subversion repository at
  8184. http://svn.collab.net .
  8185. C.2 IDE Integration
  8186. Subversion’s IDE integration has greatly matured since Sub-
  8187. version 1.0, and many popular IDEs now include official sup-
  8188. port. It’s possible to use just the command line or Tortoise,
  8189. but many users are used to tight integration between their
  8190. editor and version control, so do investigate Subversion sup-
  8191. port if you can.
  8192. Eclipse, the popular open-source Java IDE, has a plug-in
  8193. called Subclipse that integrates with Subversion, available
  8194. from http://subclipse.tigris.org/ .
  8195. IntelliJ IDEA, another popular Java IDE, has full support for
  8196. Subversion as of release 5.0. IDEA is available from http://www.jetbrains.com/ .
  8197. Ankhsvn provides integration with Visual Studio and is avail-
  8198. able from http://ankhsvn.tigris.org/ . Note that if you’re
  8199. O THER T OOLS 186
  8200. Figure C.7: Tortoise Repo-Browser in action
  8201. using Visual Studio web projects, they may be incompatible
  8202. with Subversion’s .svn administrative directories. TortoiseSVN
  8203. has a special “directory hack” option that will use svn as a
  8204. directory name instead. Bear in mind that a working copy cre-
  8205. ated like this will be incompatible with a normal working copy,
  8206. so you might need to re-checkout after enabling the hack.
  8207. C.3 Other Tools
  8208. SVN::Notify sends colored HTML e-mails when a developer
  8209. checks changes into your repository. This can be a great com-
  8210. munication tool for your team. SVN::Notify is available from
  8211. CPAN: http://search.cpan.org/dist/SVN-Notify/ .
  8212. If you’re using XCode on the Mac, you might need a key man-
  8213. ager to get SSH connections to work. SSHKeychain provides
  8214. “painless key management for Mac OS X” and is available
  8215. from http://www.sshkeychain.org/ .
  8216. The Putty suite of SSH client tools for Windows 4 also works
  8217. 4 http://www.chiark.greenend.org.uk/˜sgtatham/putty/
  8218. O THER T OOLS 187
  8219. great for getting an svn+ssh connection working and includes
  8220. Pageant, a key management agent. Chapters 8 and 9 of the
  8221. Putty Manual 5 are worth reading if you’d like to avoid typing
  8222. passwords everytime you access an svn+ssh repository.
  8223. 5 http://the.earth.li/˜sgtatham/putty/0.56/htmldoc/Chapter9.html
  8224. Appendix D
  8225. Advanced Topics
  8226. D.1 Programmatic Access to Subversion
  8227. Subversion features a number of language bindings, allowing
  8228. you to access the Subversion API through your favorite pro-
  8229. gramming language. The language bindings use Swig, the
  8230. Simplified Wrapper and Interface Generator, and essentially
  8231. expose the original C APIs to other languages. Swig bindings
  8232. exist for C, C++, C#, Java, Perl, Python and Ruby. Of these
  8233. the Python bindings are probably the most popular and def-
  8234. initely the most mature, but expect bindings to improve over
  8235. time.
  8236. Installing language bindings will be different depending on
  8237. your operating system, but tends to be best supported on
  8238. Unix. For Fedora Core 5, installing the Perl bindings is as
  8239. simple as yum install subversion-perl .
  8240. As an alternative to wrapping the C API, a group of program-
  8241. mers decided to implement a Subversion client in pure Java.
  8242. When they started the advice from the Subversion developers
  8243. was “don’t bother, just use the Swig bindings,” but they per-
  8244. severed and have produced an excellent implementation. The
  8245. JavaSVN library is used by JetBrains as the basis of their IDE
  8246. integration with Subversion, which is as good a recommenda-
  8247. tion as they could ever wish for.
  8248. The TMate JavaSVN library is available from http://tmate.org/svn/
  8249. and we’ll be using it for examples in the next section.
  8250. P ROGRAMMATIC A CCESS TO S UBVERSION 189
  8251. A Simple Subversion Client
  8252. Download the standalone version of JavaSVN from the TMate
  8253. website and unzip it to your hard drive. You’ll find . jar files
  8254. used for development and a doc subdirectory containing full
  8255. JavaDoc documentation for the library. To use JavaSVN in a
  8256. project simply include javasvn.jar in your classpath.
  8257. The JavaSVN library contains a rich assortment of functions
  8258. for talking to a Subversion repository and manipulating a
  8259. local working copy. As a first example we’ll connect to the
  8260. Subversion repository at CollabNet and print out a directory
  8261. listing.
  8262. Remote operations are conducted through instances of SVN-
  8263. Repository . Since we’re using the http scheme to access the
  8264. repository we must initialize the DAV repository factory before
  8265. we use it:
  8266. String reposUrl = "http: //svn.collab.net/repos/svn";
  8267. SVNURL url = SVNURL.parseURIEncoded(reposUrl);
  8268. DAVRepositoryFactory.setup();
  8269. SVNRepository repository = SVNRepositoryFactory.create(url);
  8270. Now that we have a repository instance we can perform func-
  8271. tions against the remote repository. For instance, to retrieve
  8272. a directory listing we can use the getDir () method:
  8273. Map < String, String > dirProps = new HashMap < String, String > ();
  8274. List < SVNDirEntry > dirEntries = new ArrayList < SVNDirEntry > ();
  8275. repository.getDir("/trunk/subversion", -1, dirProps, dirEntries);
  8276. We provide a path within the repository, /trunk/subversion , and
  8277. a revision number, in this case -1 to indicate we’re inter-
  8278. ested in the HEAD revision. We also provide an empty map
  8279. into which JavaSVN will place the properties for the directory
  8280. being listed, and an empty list into which the actual directory
  8281. entries will be fetched.
  8282. Each SVNDirEntry represents a file or directory within the direc-
  8283. tory being listed. Entries have a wealth of properties such as
  8284. name, size, revision, creation date, last-changed-by, and so
  8285. on. Here’s an example program listing files within the Collab-
  8286. Net Subversion repository:
  8287. import org.tmatesoft.svn.core.*;
  8288. import org.tmatesoft.svn.core.io.*;
  8289. import org.tmatesoft.svn.core.internal.io.dav.*;
  8290. import java.util.*;
  8291. P ROGRAMMATIC A CCESS TO S UBVERSION 190
  8292. public class ListDirectory
  8293. {
  8294. public static void main(String[] args)
  8295. throws SVNException
  8296. {
  8297. String reposUrl = "http: //svn.collab.net/repos/svn";
  8298. SVNURL url = SVNURL.parseURIEncoded(reposUrl);
  8299. DAVRepositoryFactory.setup();
  8300. SVNRepository repository = SVNRepositoryFactory.create(url);
  8301. Map < String, String > dirProps = new HashMap < String, String > ();
  8302. List < SVNDirEntry > dirEntries = new ArrayList < SVNDirEntry > ();
  8303. repository.getDir("/trunk/subversion", -1, dirProps, dirEntries);
  8304. for (SVNDirEntry dirEntry : dirEntries) {
  8305. printEntry(dirEntry);
  8306. }
  8307. }
  8308. private static void printEntry(SVNDirEntry entry) {
  8309. if(entry.getKind() == SVNNodeKind.DIR) {
  8310. System.out.println("Directory: " + entry.getName());
  8311. } else {
  8312. System.out.println("File: " + entry.getName()
  8313. + ", size " + entry.getSize()
  8314. + ", last modified by " + entry.getAuthor());
  8315. }
  8316. }
  8317. }
  8318. java/ListDirectory.java
  8319. Watching a Repository for Changes
  8320. Subversion’s hook scripts allow you to intercept interesting
  8321. events (such as changes being committed), but you might not
  8322. always want to use a hook script. In some cases you may
  8323. be unable to use hooks due to security or access restrictions
  8324. on your repository. Many Continuous Integration tools use
  8325. a “polling” strategy to check whether anything has changed
  8326. within a repository, and if it has, to automatically do some-
  8327. thing useful like building the latest code and running tests.
  8328. The JavaSVN library can be used to poll a repository and look
  8329. for changes using the getLatestRevision () method.
  8330. The following example program watches a given repository
  8331. and prints out the log message when someone commits a
  8332. change. It only checks once per minute, so it creates a very
  8333. light load on a Subversion server.
  8334. import org.tmatesoft.svn.core.*;
  8335. import org.tmatesoft.svn.core.io.*;
  8336. import org.tmatesoft.svn.core.internal.io.dav.*;
  8337. import java.util.*;
  8338. P ROGRAMMATIC A CCESS TO S UBVERSION 191
  8339. public class DetectChanges
  8340. {
  8341. public static void main(String[] args)
  8342. throws SVNException
  8343. {
  8344. String reposUrl = "http: //svn.collab.net/repos/svn";
  8345. SVNURL url = SVNURL.parseURIEncoded(reposUrl);
  8346. DAVRepositoryFactory.setup();
  8347. SVNRepository repository = SVNRepositoryFactory.create(url);
  8348. long lastSeenRevision = repository.getLatestRevision();
  8349. while(true) {
  8350. long latestRevision = repository.getLatestRevision();
  8351. if(latestRevision != lastSeenRevision) {
  8352. displayChanges(lastSeenRevision + 1,
  8353. latestRevision, repository);
  8354. lastSeenRevision = latestRevision;
  8355. }
  8356. pause(60);
  8357. }
  8358. }
  8359. private static void displayChanges(long startRev, long endRev,
  8360. SVNRepository repository)
  8361. throws SVNException {
  8362. String[] targetPaths = { "/" } ;
  8363. List < SVNLogEntry > entries = new ArrayList < SVNLogEntry > ();
  8364. repository.log(targetPaths, entries, startRev,
  8365. endRev, false, false);
  8366. for (SVNLogEntry entry : entries) {
  8367. System.out.println("New revision " + entry.getRevision()
  8368. + " by " + entry.getAuthor());
  8369. System.out.println("Log message: " + entry.getMessage());
  8370. }
  8371. }
  8372. private static void pause(int seconds) {
  8373. try {
  8374. Thread.sleep(seconds * 1000);
  8375. } catch (InterruptedException e) {
  8376. // Do nothing
  8377. }
  8378. }
  8379. }
  8380. java/DetectChanges.java
  8381. Instead of simply printing the log message, you could modify
  8382. the program to send emails, run build scripts, or whatever
  8383. else is useful.
  8384. Managing a Working Copy
  8385. JavaSVN lets you access a working copy in the same way
  8386. as the svn command-line tool. In particular, the SVNWCClient
  8387. class provides doXYZ () methods that mirror the command line
  8388. P ROGRAMMATIC A CCESS TO S UBVERSION 192
  8389. client. For example, we can use the doInfo () method to mimic
  8390. the svn info command:
  8391. import org.tmatesoft.svn.core.*;
  8392. import org.tmatesoft.svn.core.wc.*;
  8393. import java.io.File;
  8394. public class WorkingCopyInfo
  8395. {
  8396. public static void main(String[] args)
  8397. throws SVNException
  8398. {
  8399. File workingCopyRoot = new File("c: \\ work \\ subversion");
  8400. SVNWCClient wcClient = new SVNWCClient(null, null);
  8401. SVNInfo info = wcClient.doInfo(workingCopyRoot,
  8402. SVNRevision.WORKING);
  8403. System.out.println("Working Copy Info for " +
  8404. workingCopyRoot);
  8405. System.out.println("URL: " +
  8406. info.getURL());
  8407. System.out.println("Repository root: " +
  8408. info.getRepositoryRootURL());
  8409. System.out.println("Last Changed Author: " +
  8410. info.getAuthor());
  8411. System.out.println("Last Changed Rev: " +
  8412. info.getCommittedRevision());
  8413. System.out.println("Last Changed Date: " +
  8414. info.getCommittedDate());
  8415. System.out.println("URL: " +
  8416. info.getURL());
  8417. }
  8418. }
  8419. java/WorkingCopyInfo.java
  8420. Running this example will produce output similar to the reg-
  8421. ular svn info :
  8422. Working Copy Info for c: \ work \ subversion
  8423. URL: http://svn.collab.net/repos/svn/trunk/subversion
  8424. Repository root: http://svn.collab.net/repos/svn
  8425. Last Changed Author: mbk
  8426. Last Changed Rev: 19040
  8427. Last Changed Date: Sun Mar 26 08:26:13 MST 2006
  8428. URL: http://svn.collab.net/repos/svn/trunk/subversion
  8429. SVNWCClient will let you perform operations including add,
  8430. delete, lock and unlock, but you need to use the SVNCom-
  8431. mitClient class to commit changes from a working copy to the
  8432. repository.
  8433. Hopefully this tour of some of JavaSVN’s functionality will give
  8434. you ideas for embedding Subversion support into your own
  8435. applications. If you’re not coding in Java, remember there are
  8436. plenty of other language options too.
  8437. A DVANCED R EPOSITORY M ANAGEMENT 193
  8438. D.2 Advanced Repository Management
  8439. When setting up Subversion within an organization, a com-
  8440. mon question is “How many repositories should I create?”
  8441. Our advice is to create only one repository until you have a
  8442. concrete need for more. We take this approach because it’s
  8443. easy to split an existing repository into two should the need
  8444. arise. The more repositories you have, the more administra-
  8445. tion will be required backing them up, managing users, and
  8446. so on. Remember that it’s not the end of the world if you cre-
  8447. ate multiple repositories and eventually need to merge them,
  8448. because Subversion has good support for splitting, merging,
  8449. and reorganizing repositories. This section covers exactly how
  8450. to perform these advanced repository operations.
  8451. Splitting a Repository
  8452. First, make sure you tell everyone you’re going to split the
  8453. repository. The ideal situation is one in which everyone can
  8454. check in, go home for the night, leave you to organize stuff,
  8455. and then come in the next day and start on something fresh.
  8456. If people can’t commit all their changes you may need to help
  8457. them relocate 1 their working copy once you’ve finished the
  8458. split. Once everyone’s committed their changes, close down
  8459. network access to your repository to be sure no one can com-
  8460. mit further changes. This might be overkill depending on your
  8461. situation, but it’s nice to be safe.
  8462. Next, back up your repository using svnadmin dump to create a
  8463. dump file, as described in Section A.6, Backing Up Your Repos-
  8464. itory, on page 170. Make sure you perform a complete dump,
  8465. not an incremental. A dump file is a portable representation
  8466. of the Subversion repository which we can use to recreate the
  8467. repository elsewhere.
  8468. home > svnadmin dump /home/svnroot/log4rss > log4rss.dump
  8469. * Dumped revision 0.
  8470. * Dumped revision 1.
  8471. : : :
  8472. * Dumped revision 37.
  8473. * Dumped revision 38.
  8474. 1 The
  8475. svn switch command includes the --relocate option that can match up
  8476. an old working copy with a new server location.
  8477. A DVANCED R EPOSITORY M ANAGEMENT 194
  8478. We’re going to load the dump file into a new repository, which
  8479. you should create and initialize:
  8480. home > mkdir tools-repos
  8481. home > svnadmin create tools-repos
  8482. The dump file contains complete history of all files within your
  8483. repository. For the new tools repository we’re only interested
  8484. in a particular path within the repository, log4rss/trunk/tools .
  8485. Use the svndumpfilter command to select just the directories
  8486. you wish to move to the new repository, then pipe its output
  8487. into the svnadmin load command.
  8488. home > cat log4rss.dump \
  8489. | svndumpfilter include log4rss/trunk/tools \
  8490. | svnadmin load tools-repos
  8491. Including prefixes:
  8492. ' /log4rss/trunk/tools '
  8493. Revision 0 committed as 0.
  8494. Revision 1 committed as 1.
  8495. Revision 2 committed as 2.
  8496. : : :
  8497. <<< Started new transaction, based on original revision 38
  8498. ------- Committed revision 38 >>>
  8499. svndumpfilter will be quite verbose, listing information about
  8500. the items included in the filter and the items which were
  8501. dropped. Now the new tools-repos repository contains just
  8502. the tools directory.
  8503. At this point you can make the new repository available and
  8504. tell developers where to find it. It’s probably also wise to
  8505. delete the log4rss/trunk/tools directory from the original reposi-
  8506. tory, just so people can’t accidentally use the old stuff. Sub-
  8507. version doesn’t have an “obliterate” command so the tools
  8508. directory is still using space in the old repository—if this is
  8509. an issue you’ll need to consider loading your dump file into
  8510. a new repository using an “exclude” command to weed out
  8511. the directory you no longer want. In most cases this isn’t an
  8512. issue, but if your repository contains lots of large files it might
  8513. pay to do a little housekeeping.
  8514. Merging Two Repositories
  8515. In some cases you might wish to merge two existing reposito-
  8516. ries. An example of this could be two separate project teams
  8517. merging into one, or a new project team taking over an exist-
  8518. A DVANCED R EPOSITORY M ANAGEMENT 195
  8519. ing codebase and wanting to use their own repository to man-
  8520. age the code.
  8521. Merging one repository into another is as simple as creating
  8522. a dump of the “donor” repository and using svnadmin load to
  8523. load the dump into the target repository. The load process
  8524. will replay each action that took place in the old repository
  8525. and although revision numbers won’t match your history will
  8526. be preserved.
  8527. This kind of merging will only work when the two reposito-
  8528. ries have different directory structures—if any directories are
  8529. shared by the two repositories the load will fail. To get around
  8530. this, use the --parent-dir option to load into a different location.
  8531. For example, we can load a dump of the Log4RSS repository
  8532. into itself in a new merged directory:
  8533. svnroot > svn mkdir file:///home/svnroot/log4rss/merge \
  8534. -m "Create merge directory"
  8535. Committed revision 36.
  8536. svnroot > svnadmin load --parent-dir merge log4rss < log4rss.dump
  8537. <<< Started new transaction, based on original revision 1
  8538. * adding path : merge/trunk ... done.
  8539. ------- Committed new rev 37 (loaded from original rev 1) >>>
  8540. : : :
  8541. <<< Started new transaction, based on original revision 25
  8542. * editing path : merge/trunk/build.xml ... done.
  8543. ------- Committed new rev 61 (loaded from original rev 25) >>>
  8544. In the above session snippet, you can see that the load com-
  8545. mand created revision 61 from an original revision 25, and
  8546. that instead of editing trunk/build.xml , merge/trunk/build.xml was
  8547. used instead, thus avoiding a conflict with the files already in
  8548. the repository.
  8549. Organizing a Repository
  8550. After merging two repositories you’ll probably want to reor-
  8551. ganize, especially if you used the --parent-dir option to avoid
  8552. conflicts. You might also want to rearrange a repository for
  8553. other reasons—maybe the repository has been around for a
  8554. while and isn’t really structured as you’d like. Fortunately
  8555. Subversion is great at moving things around.
  8556. Before moving directories in Subversion, make sure all your
  8557. users have checked in their changes. After a significant repos-
  8558. itory reorganization it’s often easier to check out a fresh work-
  8559. A DVANCED R EPOSITORY M ANAGEMENT 196
  8560. ing copy than try to update to the latest version. For this rea-
  8561. son you might want to reorganize at the weekend or after work
  8562. one evening.
  8563. Using repository URLs rather than working copy paths as
  8564. arguments to svn mv means the moves occur instantly on the
  8565. server. This is often important if you’re juggling large directo-
  8566. ries full of files.
  8567. We recommend using a graphical client such as TortoiseSVN
  8568. for large repository reorganizations, simply because it’s much
  8569. easier to keep track of the directory structure. The Tortoise
  8570. repository browser allows you to drag and drop files and direc-
  8571. tories to move them—very convenient indeed!
  8572. Appendix E
  8573. Command Summary and
  8574. Recipes
  8575. E.1 Subversion Command Summary
  8576. Most Subversion commands have common options, which we
  8577. list first in order to avoid repeating them for each command.
  8578. If you’re unsure which options a particular command accepts,
  8579. just run svn help command for a quick summary.
  8580. Common options:
  8581. --targets list Read in list and interpret it as a list of argu-
  8582. ments on which to operate.
  8583. --non-recursive, -N Operate on a single directory only; don’t try to
  8584. process subdirectories.
  8585. --verbose, -v Print additional information.
  8586. --quiet, -q Print as little as possible.
  8587. --username name Specify the name to be used when connecting
  8588. and authorizing.
  8589. --password pswd Specify the password to be used.
  8590. --no-auth-cache Do not cache authentication tokens.
  8591. --non-interactive Do not prompt for extra information.
  8592. --config-dir dir Read user configuration from dir.
  8593. --editor-cmd cmd Use cmd as log message editor.
  8594. S UBVERSION C OMMAND S UMMARY 198
  8595. svn add
  8596. Add names of files and directories to version control. They will be
  8597. added to the repository in the next commit.
  8598. svn add path...
  8599. Options:
  8600. --auto-props Automatically set properties on files when adding them.
  8601. --no-auto-props Disable automatic property setting.
  8602. svn blame (also known as ann, annotate, praise)
  8603. Show revision and author information for each line of a file
  8604. svn blame target...
  8605. Options:
  8606. --revision, -r rev If specified as a single revision rev, shows blame informa-
  8607. tion for the targets at revision rev. If specified as a revi-
  8608. sion range rev1:rev2, shows blame information for the
  8609. targets at revision rev2, but examines revisions only as
  8610. far back as rev1 (for this to be useful, rev1 should be less
  8611. than rev2).
  8612. svn cat
  8613. Output the contents of specified files or URLs.
  8614. svn cat target...
  8615. Options:
  8616. --revision, –r rev Output the contents of target at revision rev.
  8617. svn checkout (also known as co)
  8618. Check out a working copy from a repository.
  8619. svn checkout url... path
  8620. Checks out the given URLs. With no path argument, checks out into
  8621. local directories named using the base names of the URLs. If path is
  8622. given with one URL argument, checks out into path. If path is given
  8623. with multiple URL arguments, checks out into subdirectories of path
  8624. named for the base names in the urls.
  8625. Options:
  8626. --revision, -r rev The revision to check out.
  8627. S UBVERSION C OMMAND S UMMARY 199
  8628. svn cleanup
  8629. Clean up the working copy, removing locks, resuming unfinished
  8630. operations, etc.
  8631. svn cleanup path...
  8632. svn commit (also known as ci)
  8633. Send changes from your working copy to the repository.
  8634. svn commit path...
  8635. Options:
  8636. --message, –m msg Use msg as the commit log message.
  8637. --file, –F file Use the contents of file as the commit log message.
  8638. --no-unlock Do not release locks during the commit.
  8639. svn copy (also known as cp)
  8640. Duplicate something in working copy or repository, remembering
  8641. history.
  8642. svn copy src dest
  8643. src and dest can each be either a working copy (WC) path or a URL.
  8644. src dest Effect...
  8645. WC WC Copy and schedule for addition (with history).
  8646. WC URL Immediately commit a copy of WC to URL.
  8647. URL WC Check out URL into WC, schedule for addition.
  8648. URL URL Complete server-side copy; used to branch and tag.
  8649. Options:
  8650. --revision, -r rev The revision of src to copy. Only makes sense if src is a
  8651. repository URL.
  8652. svn delete (also known as del, remove, rm)
  8653. Remove files and directories from version control.
  8654. svn delete target...
  8655. Deletes files and directories from the repository. If target is a work-
  8656. ing copy file or directory, it is removed from the working copy and
  8657. scheduled for deletion at the next commit. If target is a repository
  8658. URL, it is deleted from the repository via an immediate commit.
  8659. Options:
  8660. --message, –m msg Use msg as the commit log message.
  8661. --file, –F file Use the contents of file as the commit log message.
  8662. S UBVERSION C OMMAND S UMMARY 200
  8663. svn diff (also known as di)
  8664. Display the differences between two paths.
  8665. svn diff -r rev1 : rev2 target...
  8666. svn diff oldurl newurl
  8667. In the first form, display changes made to target between revisions
  8668. rev1 and rev2. Targets may be working copy paths or URLs.
  8669. In the second form, display the differences between the HEAD revi-
  8670. sions of oldurl and newurl.
  8671. Options:
  8672. --old arg Use arg as the older target.
  8673. --new arg Use arg as the newer target.
  8674. svn export
  8675. Create an unversioned copy of a tree.
  8676. svn export -r rev URL path
  8677. Exports a clean directory tree from the repository specified by URL,
  8678. at revision rev if it is given, otherwise at HEAD, into path. If path is
  8679. omitted the last component of the URL is used as the local directory
  8680. name.
  8681. Options:
  8682. --revision, -r rev Export from the repository at revision rev.
  8683. --native-eol style Use a different end-of-line marker than the standard
  8684. system marker for files with a native svn:eol-style prop-
  8685. erty. style must be one of LF , CR , or CRLF .
  8686. svn import
  8687. Commit an unversioned file or tree into the repository.
  8688. svn import path URL
  8689. Recursively commit a copy of path to URL. If path is omitted, the
  8690. current directory is assumed. Parent directories are created as nec-
  8691. essary in the repository.
  8692. Options:
  8693. --auto-props Automatically set properties on files when importing
  8694. them.
  8695. --no-auto-props Disable automatic property setting on imported files.
  8696. S UBVERSION C OMMAND S UMMARY 201
  8697. svn info
  8698. Display information about a file or directory.
  8699. svn info path...
  8700. Print information about each path.
  8701. Options:
  8702. --recursive, -r Descend recursively.
  8703. svn list (also known as ls)
  8704. List directory entries in the repository.
  8705. svn list target...
  8706. List each target file and the contents of each target directory as they
  8707. exist in the repository. If target is a working copy path, the corre-
  8708. sponding repository URL will be used.
  8709. Options:
  8710. --verbose, -v Show extra information about each directory entry.
  8711. svn lock
  8712. Lock files so that other users cannot commit changes.
  8713. svn lock target
  8714. Communicates with the repository server to obtain a lock on one or
  8715. more working copy files. Once locked, other users cannot commit
  8716. changes to the files unless the lock is released or broken.
  8717. Options:
  8718. --message, –m msg Use msg as the lock information message.
  8719. --force Force the lock to succeed by stealing the lock from
  8720. another user or working copy.
  8721. svn log
  8722. Show the log messages for a set of revisions and/or files.
  8723. svn log target
  8724. Print the log messages for a local path or repository URL. For a local
  8725. path the default revision range is BASE:1, and for a URL the default
  8726. revision range is HEAD:1.
  8727. S UBVERSION C OMMAND S UMMARY 202
  8728. Options:
  8729. --revision, -r rev If rev is a single revision, show the log entry only for
  8730. that revision. If rev is a revision range, show only the
  8731. log entries for those revisions.
  8732. --verbose, -v Print all affected paths with each log message.
  8733. --stop-on-copy Do not cross copies while traversing history (useful
  8734. for determining the start point of a branch).
  8735. svn merge
  8736. Apply the differences between two sources to a working copy path.
  8737. svn merge sourceURL1 @rev1 sourceURL2 @rev2 wcpath
  8738. svn merge sourceWCPATH1@ rev1 sourceWCPATH2@ rev1 wcpath
  8739. svn merge -r rev1 : rev2 SOURCE wcpath
  8740. In the first form, the source URLs are specified at revisions rev1
  8741. and rev2. These are the two sources to be compared. The revisions
  8742. default to HEAD if omitted.
  8743. In the second form, the URLs corresponding to the source working
  8744. copy paths define the sources to be compared. The revisions must
  8745. be specified.
  8746. In the third form, SOURCE can be a URL or working copy item, in
  8747. which case the corresponding URL is used. This URL is compared as
  8748. it existed between revisions rev1 and rev2.
  8749. wcpath is the working copy path that will receive the changes. If
  8750. wcpath is omitted, a the current directory is assumed, unless the
  8751. sources have identical basenames that match a file within the cur-
  8752. rent directory, in which case the differences will be applied to that
  8753. file.
  8754. Options:
  8755. --diff3-cmd cmd Use cmd as merge command.
  8756. --ignore-ancestry Ignore ancestry when calculating merges.
  8757. svn mkdir
  8758. Create a new directory under version control.
  8759. svn mkdir target...
  8760. Each directory specified by a working copy path is created locally and
  8761. scheduled for addition upon the next commit. Each directory speci-
  8762. fied by a URL is created in the repository via an immediate commit.
  8763. In both cases, all the intermediate directories must already exist.
  8764. S UBVERSION C OMMAND S UMMARY 203
  8765. svn move (also known as mv, rename, ren)
  8766. Move and/or rename something in working copy or repository.
  8767. svn move src dest
  8768. src and dest must both be either working copy paths or repository
  8769. URLs. In the working copy, the move is performed and the new
  8770. location scheduled for addition. For repository URLs, a complete
  8771. server-side rename is performed immediately.
  8772. Options:
  8773. --revision, -r rev Use revision rev of the source when performing the move.
  8774. svn propdel (also known as pdel, pd)
  8775. Remove property from files or directories.
  8776. svn propdel propname path...
  8777. Delete property propname from path in the local working copy.
  8778. svn propedit (also known as pedit, pe)
  8779. Edit property from files or directories.
  8780. svn propedit propname path...
  8781. Start an external editor, and edit propname on path in the local work-
  8782. ing copy.
  8783. svn propget (also known as pget, pg)
  8784. Print property values from files or directories.
  8785. svn propget propname path...
  8786. Print the contents of propname from each path. By default, Subver-
  8787. sion will add an extra newline to the end of the property values so
  8788. that the output looks pretty. Also, whenever there are multiple paths
  8789. involved, each property value is prefixed with the path with which it
  8790. is associated.
  8791. Options:
  8792. --strict Disable extra newlines and other beautifications (useful when
  8793. redirecting binary property values to a file).
  8794. S UBVERSION C OMMAND S UMMARY 204
  8795. svn proplist (also known as plist, pl)
  8796. List all properties on files or directories.
  8797. svn proplist path...
  8798. List properties on path.
  8799. Options:
  8800. --verbose, -v Print extra information.
  8801. --recursive, -R Descend recursively.
  8802. --revision, -r rev List properties defined in revision rev of path.
  8803. svn propset (also known as pset, ps)
  8804. Set a propery on files or directories.
  8805. svn propset propname propval path...
  8806. Set property propname to value propval on path. If propval is not
  8807. specified, you must use the -F option to specify a file whose contents
  8808. should be used as the property value.
  8809. Options:
  8810. --file, -F file Read the contents of file and use it as the property
  8811. value.
  8812. --recursive, -R Descend recursively.
  8813. --encoding enc Treat value as being in character set encoding enc.
  8814. svn resolved
  8815. Remove conflicted state on working copy files or directories.
  8816. svn resolved path...
  8817. Mark a file that previously contained conflicts as “resolved.” Note
  8818. that this command does not semantically resolve conflicts or remove
  8819. conflict markers; it merely removes the conflict-related artifact files
  8820. and allows path to be committed.
  8821. Options:
  8822. --recursive, -R Descend recursively.
  8823. S UBVERSION C OMMAND S UMMARY 205
  8824. svn revert
  8825. Restore pristine working copy file (undo most local edits).
  8826. svn revert path...
  8827. This command does not require network access and undoes any
  8828. changes you have made to path. It does not restore removed direc-
  8829. tories.
  8830. Options:
  8831. --recursive, -R Descend recursively.
  8832. svn status (also known as stat, st)
  8833. Print the status of working copy files and directories.
  8834. svn status path...
  8835. With no args, print only locally modified items (no network access).
  8836. With -u , add working revision and server out-of-date information.
  8837. With -v , print full revision information on every item.
  8838. The first six columns in the output are each one character wide.
  8839. First column: Says if item was added, deleted, or otherwise changed.
  8840. “ ” No modifications.
  8841. A Added.
  8842. C Conflicted.
  8843. D Deleted.
  8844. G Merged.
  8845. I Ignored.
  8846. M Modified.
  8847. R Replaced.
  8848. X Item is unversioned, but is used by an externals definition.
  8849. ? Item is not under version control.
  8850. ! Item is missing (removed by non- svn command) or incomplete.
  8851. ˜
  8852. Versioned item obstructed by some item of a different kind.
  8853. Second column: Modifications of a file’s or directory’s properties.
  8854. “ ” No modifications.
  8855. C Conflicted.
  8856. M Modified.
  8857. Third column: Whether the working copy directory is locked.
  8858. “ ” Not locked.
  8859. L Locked.
  8860. S UBVERSION C OMMAND S UMMARY 206
  8861. Fourth column: Scheduled commit will contain addition with his-
  8862. tory.
  8863. “ ” No history scheduled with commit.
  8864. + History scheduled with commit.
  8865. Fifth column: Whether the item is switched relative to its parent.
  8866. “ ” Normal.
  8867. S Switched.
  8868. Sixth column: Lock token information (to show repository informa-
  8869. tion, use -u ).
  8870. “ ” No lock token present, not locked in the repository.
  8871. K Lock token present, item locked in the repository.
  8872. O Item locked in the repository, lock token present in some other
  8873. working copy.
  8874. T Item locked in the repository, lock token present in working copy
  8875. but stolen by some other working copy.
  8876. B Item not locked in the repository, but broken lock token present
  8877. in working copy.
  8878. The out-of-date information appears in the eighth column (with -u ).
  8879. * A newer revision exists on the server.
  8880. “ ” The working copy is up-to-date.
  8881. The remaining fields are variable width and delimited by spaces: the
  8882. working revision (with -u or -v ), the last-committed revision, and last-
  8883. committed author (with -v ). The working copy path is always the final
  8884. field, so it can include spaces.
  8885. Options:
  8886. --show-updates, -u Contact the server to display update information.
  8887. --verbose, -v Print extra information.
  8888. --non-recursive, -N Operate on single directory only.
  8889. --no-ignore Disregard default and svn:ignore property ignores.
  8890. S UBVERSION C OMMAND S UMMARY 207
  8891. svn switch (also known as sw)
  8892. Update the working copy to a different URL.
  8893. svn switch URL path
  8894. Update the working copy to mirror a new URL within the repository.
  8895. This behavior is similar to svn update and is the way to move a work-
  8896. ing copy to a branch or tag within the same repository.
  8897. Options:
  8898. --revision, -r rev Switch to revision rev.
  8899. --non-recursive, -N Operate on single directory only.
  8900. --diff3-cmd cmd Use cmd as merge command.
  8901. svn unlock
  8902. Unlock working copy files or repository URLs.
  8903. svn unlock target...
  8904. Release locks currently held on target so other users can commit
  8905. changes.
  8906. Options:
  8907. --force Break an existing lock on target, even if it is not owned by the
  8908. current working copy.
  8909. svn update (also known as up)
  8910. Bring changes from the repository into the working copy.
  8911. svn update path...
  8912. If no revision given, bring working copy up-to-date with HEAD revi-
  8913. sion. Otherwise synchronize working copy to revision given by -r .
  8914. For each updated item a line will start with a character reporting the
  8915. action taken. These characters have the following meaning:
  8916. A Added.
  8917. D Deleted.
  8918. U Updated.
  8919. C Conflict.
  8920. M Merged.
  8921. A character in the first column signifies an update to the actual file,
  8922. and updates to the file’s properties are shown in the second column.
  8923. R ECIPES 208
  8924. Options:
  8925. --revision, -r rev Update to revision rev.
  8926. --non-recursive, -N Operate on single directory only.
  8927. --diff3-cmd cmd Use cmd as merge command.
  8928. E.2 Recipes
  8929. Checking out............................................... Page 63
  8930. svn checkout URL path
  8931. Checking out a specific revision ........................ Page 63
  8932. svn checkout -r rev URL
  8933. Checking out a specific date............................. Page 63
  8934. svn checkout -r " { date } " URL
  8935. Finding out where a working copy came from......... Page 63
  8936. svn info path
  8937. Updating a working copy................................. Page 64
  8938. svn update
  8939. Updating specific items in a working copy............. Page 64
  8940. svn update path...
  8941. Adding files to the repository............................ Page 66
  8942. svn add path...
  8943. Setting a property on a file or directory ............... Page 67
  8944. svn propset propname propvalue path...
  8945. Editing a property on a file or directory ............... Page 67
  8946. svn propedit propname path...
  8947. Listing the properties on a file or directory ........... Page 67
  8948. svn proplist path...
  8949. Printing the contents of a property..................... Page 67
  8950. svn propget propname path...
  8951. Deleting a property ....................................... Page 68
  8952. svn propdel propname path...
  8953. Enabling keyword expansion for a file.................. Page 69
  8954. svn propset svn:keywords " keywords " file...
  8955. Ignoring certain files in a directory..................... Page 71
  8956. svn propedit svn:ignore path...
  8957. R ECIPES 209
  8958. Setting end-of-line style for a file....................... Page 72
  8959. svn propset svn:eol-style style path...
  8960. Setting the mime-type of file............................ Page 73
  8961. svn propset svn:mime-type mime-type path...
  8962. Marking a file executable................................. Page 74
  8963. svn propset svn:executable true path...
  8964. Copying a file or directory ............................... Page 76
  8965. svn copy source destination
  8966. Renaming a file or directory............................. Page 77
  8967. svn rename oldname newname
  8968. Moving a file or directory ................................ Page 77
  8969. svn move source destination
  8970. Showing changes to a file or directory ................. Page 80
  8971. svn diff path...
  8972. Comparing two revisions of a file ....................... Page 81
  8973. svn diff -r rev1 : rev2 file
  8974. Showing changes between a file and the latest revision in
  8975. the repository.............................................. Page 83
  8976. svn diff -r HEAD file...
  8977. Showing the most recent change to a file.............. Page 84
  8978. svn diff -r PREV:BASE file...
  8979. Creating a patch file ...................................... Page 85
  8980. svn diff > patchfile
  8981. Applying a patch file...................................... Page 85
  8982. patch -p0 -i patchfile
  8983. Discarding your changes in the face of a conflict..... Page 88
  8984. svn revert file...
  8985. svn update file...
  8986. Discarding someone else’s changes in the face of a con-
  8987. flict ......................................................... Page 90
  8988. cp file .mine file
  8989. svn resolved file
  8990. Marking a conflict resolved.............................. Page 90
  8991. svn resolved file...
  8992. R ECIPES 210
  8993. Checking in changes...................................... Page 91
  8994. svn commit -m " message "
  8995. Showing history for a file ................................ Page 91
  8996. svn log file
  8997. Showing recent activity in a directory ................. Page 93
  8998. svn log path | more
  8999. Showing detailed history for a file ...................... Page 93
  9000. svn log -v file...
  9001. Annotating files with author information.............. Page 94
  9002. svn blame file...
  9003. Reverting an already committed change............... Page 96
  9004. svn merge -r rev : rev-1 path...
  9005. Checking the working copy status...................... Page 98
  9006. svn status
  9007. Showing updates pending from the repository ........ Page 98
  9008. svn status --show-updates
  9009. Enabling locking on a file ............................... Page 101
  9010. svn propset svn:needs-lock true file...
  9011. svn commit -m "Enabled locking" file...
  9012. Obtaining a lock on a file................................ Page 102
  9013. svn lock file... -m " lock comment "
  9014. Examining lock information for a file ................. Page 103
  9015. svn info file... | grep Lock
  9016. Breaking another user’s lock on a file ................. Page 104
  9017. svn unlock --force URL
  9018. Stealing another user’s lock on a file.................. Page 105
  9019. svn lock --force file... -m " lock message "
  9020. Creating a release branch ............................... Page 116
  9021. svn copy \
  9022. svn://myserver/ project /trunk \
  9023. svn://myserver/ project /branches/ RB-x.y
  9024. R ECIPES 211
  9025. Checking out a release branch.......................... Page 117
  9026. cd work
  9027. svn checkout \
  9028. svn://myserver/ project /branches/ RB-x.y
  9029. Switching a working copy to a release branch........ Page 118
  9030. cd myproj
  9031. svn switch \
  9032. svn://myserver/ project /branches/RB- x.y
  9033. Switching a working copy back to the trunk ......... Page 118
  9034. cd myproj
  9035. svn switch svn://myserver/ project /trunk
  9036. Creating a release tag.................................... Page 119
  9037. svn copy \
  9038. svn://myserver/ project /branches/RB- x.y \
  9039. svn://myserver/ project /tags/REL- x.y
  9040. Checking out a release................................... Page 120
  9041. svn checkout \
  9042. svn://myserver/ project /tags/REL- x.y
  9043. Merging a simple bug fix from a release branch to the
  9044. trunk....................................................... Page 122
  9045. cd project
  9046. svn update
  9047. svn merge -r rev-1 : rev \
  9048. svn://myserver/ project /branches/RB- x.y
  9049. Creating a branch for a complex bug fix............... Page 123
  9050. svn copy \
  9051. svn://myserver/ project /branches/RB- x.y \
  9052. svn://myserver/ project /branches/BUG- track
  9053. svn copy \
  9054. svn://myserver/ project /branches/BUG- track \
  9055. svn://myserver/ project /tags/PRE- track
  9056. Checking out a bug fix branch.......................... Page 123
  9057. svn checkout \
  9058. svn://myserver/ project /branches/BUG- track
  9059. Tagging the end of a bug fix............................. Page 124
  9060. svn copy \
  9061. svn://myserver/ project /branches/BUG- track \
  9062. svn://myserver/ project /tags/POST- track
  9063. R ECIPES 212
  9064. Merging a complex bug fix to a release branch ....... Page 124
  9065. cd RB x.y
  9066. svn merge \
  9067. svn://myserver/ project /tags/PRE- track \
  9068. svn://myserver/ project /tags/POST- track
  9069. Creating experimental branches........................ Page 125
  9070. svn copy \
  9071. svn://.../trunk \
  9072. svn://.../branches/TRY- initials - mnemonic
  9073. Using an experimental branch.......................... Page 125
  9074. svn switch \
  9075. svn://.../branches/TRY- initials - mnemonic
  9076. Returning to the trunk .................................. Page 125
  9077. svn switch svn://.../trunk
  9078. Finding out when a branch was created............... Page 126
  9079. svn log --stop-on-copy \
  9080. svn://.../branches/ branch
  9081. Merging an experimental branch....................... Page 127
  9082. svn log --stop-on-copy \
  9083. svn://.../branches/TRY- initials - mnemonic
  9084. cd trunk-working-copy
  9085. svn merge \
  9086. -r branch-start-revision :HEAD \
  9087. svn://.../branches/TRY- initials - mnemonic
  9088. svn commit
  9089. Importing a project into the repository ............... Page 130
  9090. cd project
  9091. svn import svn://myserver/ project /trunk
  9092. Manually creating directories for a project ........... Page 130
  9093. svn mkdir svn://myserver/ project /
  9094. svn mkdir svn://myserver/ project /trunk
  9095. svn mkdir svn://myserver/ project /tags
  9096. svn mkdir svn://myserver/ project /branches
  9097. Importing third-party code.............................. Page 145
  9098. svn import vendor-tree \
  9099. svn://.../vendorsrc/ vendor / product /current
  9100. R ECIPES 213
  9101. Tagging a vendor drop ................................... Page 146
  9102. svn copy \
  9103. svn://.../vendorsrc/ vendor / product /current \
  9104. svn://.../vendorsrc/ vendor / product / version
  9105. Loading a new vendor drop.............................. Page 147
  9106. svn load dirs.pl \
  9107. svn://.../vendorsrc/ vendor / product \
  9108. current vendor-tree
  9109. Using vendor code in a project ......................... Page 148
  9110. svn copy \
  9111. svn://.../vendorsrc/ vendor / product / ver \
  9112. svn://.../ project /trunk/vendor/ product
  9113. Upgrading vendor code in a project.................... Page 149
  9114. svn merge \
  9115. svn://.../vendorsrc/ vendor / product / oldver \
  9116. svn://.../vendorsrc/ vendor / product / newver \
  9117. vendor/ product
  9118. Starting svnserve on Windows.......................... Page 153
  9119. start svnserve --daemon --root repos-dir
  9120. Starting svnserve on Unix............................... Page 153
  9121. svnserve --daemon --root repos-dir
  9122. Creating a full backup of your repository ............. Page 170
  9123. svnadmin dump repos > dumpfile
  9124. Creating an incremental backup of your repository . Page 171
  9125. svnadmin dump --incremental \
  9126. --revision rev1 : rev2 repos
  9127. Appendix F
  9128. Other Resources
  9129. There are a wealth of Subversion and version control related
  9130. resources available out there—here are just a few to get you
  9131. started.
  9132. F.1 Online Resources
  9133. Subversion Home Page .... http://subversion.tigris.org/
  9134. The official Subversion web site is an excellent resource for anyone
  9135. getting started with Subversion. The site contains all sorts of doc-
  9136. umentation, including the excellent Subversion FAQ that contains
  9137. common questions and answers. The project links page is a great
  9138. place to find Subversion-related software, plug-ins, articles, and doc-
  9139. umentation.
  9140. You can also join the Subversion users’ mailing list; just send an
  9141. e-mail to users-subscribe@subversion.tigris.org . The list is
  9142. the place to ask questions and is populated by some very friendly
  9143. people, including Subversion’s core developers.
  9144. Pragmatic Programmers. ..
  9145. ... http://www.pragmaticprogrammer.com/titles/svn/
  9146. The companion web site for this book where you’ll find code samples,
  9147. errata, and links to other pragmatic things.
  9148. Subversion Book............. http://svnbook.red-bean.com/
  9149. The official Subversion book is available online and in print form
  9150. and contains in-depth discussion of even Subversion’s most esoteric
  9151. features.
  9152. Better SCM.................. http://better-scm.berlios.de/
  9153. The Better SCM project aims to promote alternatives to CVS and
  9154. includes a comparison between various version control systems.
  9155. B IBLIOGRAPHY 215
  9156. CM Crossroads............... http://www.cmcrossroads.com/
  9157. Configuration Management is a larger topic than version control but
  9158. usually requires decent version control to achieve its aims. Through-
  9159. out the book we’ve mentioned the various “SCM Patterns” by name,
  9160. so if you’d like to find out about the patterns in more detail or are
  9161. interested in how source code, builds, projects, and releases are
  9162. organized, this site contains articles and discussion groups that may
  9163. interest you.
  9164. F.2 Bibliography
  9165. [BA03] Stephen P. Berczuk and Brad Appleton. Soft-
  9166. ware Configuration Management Patterns: Effec-
  9167. tive Teamwork, Practical Integration. Addison-Wes-
  9168. ley, 2003.
  9169. [Cla04] Mike Clark. Pragmatic Project Automation. How to
  9170. Build, Deploy, and Monitor Java Applications. The
  9171. Pragmatic Programmers, LLC, Raleigh, NC, and
  9172. Dallas, TX, 2004.
  9173. [CSFP] Ben Collins-Sussman, Brian W. Fitzpatrick, and
  9174. C. Michael Pilato. Version Control with Subversion.
  9175. [HT03] Andrew Hunt and David Thomas. Pragmatic Unit
  9176. Testing In Java with JUnit. The Pragmatic Pro-
  9177. grammers, LLC, Raleigh, NC, and Dallas, TX,
  9178. 2003.
  9179. [HT04] Andrew Hunt and David Thomas. Pragmatic Unit
  9180. Testing In C# with NUnit. The Pragmatic Program-
  9181. mers, LLC, Raleigh, NC, and Dallas, TX, 2004.
  9182. Index
  9183. Symbols
  9184. <<<< conflict marker, 88
  9185. A
  9186. Access rights, 57, 59, 155
  9187. securing Subversion, 163
  9188. svnserve command, 163
  9189. svn add command, 66, 198
  9190. --non-recursive option, 66
  9191. Alias module, 16
  9192. svn ann command, 94
  9193. svn annotate command, 94
  9194. Ant script, 11
  9195. Apache web server
  9196. install on Linux, 162
  9197. mod authz svn , 159
  9198. mod dav svn , 59, 159, 162
  9199. security, 165–168
  9200. virtual directories, 110
  9201. on Windows, 151, 158
  9202. Appleton, Brad, vi, 26
  9203. Artifact (store or not), 13
  9204. Atomic commit, 7
  9205. Audit functionality, 1
  9206. $ Author $ keyword, 69
  9207. Autoprops, 74, 150
  9208. B
  9209. Backing up (repository), 170–173
  9210. BASE revision, 81
  9211. Berczuk, Stephen, 26
  9212. Binary vs. text files, 73
  9213. Binary files (locking), 99–106
  9214. Binary libraries, 141
  9215. svn blame command, 94, 198
  9216. -r option, 95
  9217. Branch, 19–22
  9218. to avoid code freeze, 19
  9219. as a copy, 76
  9220. creating, 113
  9221. creating retrospectively, 116n
  9222. experimental, 114, 124
  9223. and externals, 140
  9224. merge, 22, 122, 124
  9225. naming, 115f
  9226. release, 107, 114, 115
  9227. trunk, 19, 37, 107
  9228. Bug fix
  9229. identifying revision containing,
  9230. 121, 122
  9231. merging, 22, 122, 124
  9232. in release branch, 121
  9233. tagging, 114
  9234. Build
  9235. and environment variables,
  9236. 144
  9237. organizing paths for, 143
  9238. build.xml , 11
  9239. BUILDING file, 132
  9240. sample, 133f
  9241. C
  9242. Carriage return (EOL style), 72
  9243. svn cat command, 198
  9244. Check out, 12
  9245. svn checkout command, 39, 45,
  9246. 62, 198
  9247. -r option, 63
  9248. ˇ
  9249. Cibej, Branko, vi
  9250. svn cleanup command, 199
  9251. Client/server access to
  9252. repository, 10
  9253. Code freeze, avoiding, 19
  9254. CodeHaus, 85, 145, 145n
  9255. Command line, 29, 30
  9256. Commit, 14
  9257. atomic nature of, 7
  9258. e-mail notification on, 186
  9259. SVN COMMIT COMMAND 217 F ILE
  9260. sequence of commands to
  9261. follow, 91
  9262. svn commit command, 41, 66,
  9263. 76, 91, 199
  9264. -m option, 41, 91
  9265. COMMITTED revsion, 81
  9266. Compiler, finding header files,
  9267. 143
  9268. Configuration file, 58, 75
  9269. Configuration Management, 26
  9270. Conflict
  9271. during merge, 24, 48
  9272. graphical front end, 183
  9273. markers, 88
  9274. resolution, 23, 87
  9275. Conventions, typographic, viii
  9276. svn copy command, 75, 199
  9277. to create release branch, 119
  9278. svnadmin create command, 34
  9279. Creating a project, 34, 128–140
  9280. Creating a repository, 33
  9281. CVS
  9282. .cvsignore equivalent in
  9283. Subversion, 71
  9284. keywords ( $Log$ etc), 68, 70
  9285. migrating to Subversion,
  9286. 174–177
  9287. modules are Subversion
  9288. directories, 16
  9289. vs. Subversion, 6
  9290. version numbering, 17
  9291. cvs2svn command, 175
  9292. D
  9293. data/ directory, 133
  9294. $ Date $ keyword, 68
  9295. Date, accessing revision by, 81
  9296. DAV, 161
  9297. db/ directory, 133
  9298. svn delete command, 199
  9299. DeltaV, 161
  9300. Developers
  9301. experimenting in branches,
  9302. 114, 124
  9303. misunderstandings, 49
  9304. sharing code, 1, 24
  9305. svn diff command, 40, 80, 85,
  9306. 200
  9307. binary file, 73
  9308. --diff-cmd option, 41
  9309. -r option, 46, 82
  9310. --diff-cmd option
  9311. to svn diff , 41
  9312. Difference
  9313. conflict resolution, 23
  9314. determining, 80
  9315. and file type, 73
  9316. merging, 22, 122, 124
  9317. and patch, 85
  9318. stored in repository, 16
  9319. unified format, 40
  9320. between versions, 82
  9321. between working copy and
  9322. repository, 83
  9323. Directory
  9324. for branches and tags, 108
  9325. Jakarta conventions for laying
  9326. out, 131
  9327. linking with svn:externals , 137
  9328. in repository, 16
  9329. structure in project, 131, 134f
  9330. top-level in project, 132
  9331. versioning, 7
  9332. doc/ directory, 132
  9333. Download Subversion, 33
  9334. dumpfile, 170
  9335. E
  9336. Eclipse IDE, 144, 185
  9337. Editing, 23, 39
  9338. EDITOR environment variable, 43
  9339. Editor, choosing, 43
  9340. E-mail notification of commit,
  9341. 186
  9342. End-of-line style, 72
  9343. Environment variable
  9344. in build, 144
  9345. EDITOR , 43
  9346. SVN EDITOR , 43
  9347. VISUAL , 43
  9348. Executable file, 74
  9349. svn export command, 200
  9350. External repositories, 109, 137
  9351. F
  9352. File
  9353. adding to repository, 66
  9354. changing contents, 39
  9355. checked out read-only, 23
  9356. commiting changes, 91
  9357. copy, 75
  9358. difference with repository, 83
  9359. F ILE - SPECIFIC VERSION NUMBERING 218 L OCKING
  9360. editing, 23, 39
  9361. entity in repository, 15
  9362. executable, 74
  9363. generated, 13
  9364. header (include), 142
  9365. ignoring, 71
  9366. locking, 99–106
  9367. mime type of, 73
  9368. move (rename), 77
  9369. top-level in project, 132
  9370. unmergeable, 99
  9371. versioning, 7
  9372. File-specific version numbering,
  9373. 16
  9374. Firewall, 153, 154
  9375. using HTTP to minimize holes,
  9376. 61
  9377. Framework as separate project,
  9378. 129
  9379. Fred and Wilma, 2, 22
  9380. G
  9381. Gemkow, Steffen, vi
  9382. Generated file (store or not), 13
  9383. GLOSSARY file, 132
  9384. GUI front end, 178
  9385. H
  9386. HEAD revision, 81
  9387. Header (include) files, 142
  9388. $ HeadURL $ keyword, 69
  9389. Hook scripts, 168
  9390. http protocol, 59, 157
  9391. I
  9392. $ Id $ keyword, 69
  9393. IDE
  9394. configuration variables, 144
  9395. Eclipse, 144, 185
  9396. IntelliJ IDEA, 185
  9397. method-level check in, 15n
  9398. organizing libraries for, 143
  9399. Subversion integration, 185
  9400. Visual Studio, 185
  9401. Ignoring files, 71
  9402. svn import command, 36, 129,
  9403. 200
  9404. -m option, 36
  9405. --no-auto-props option, 150
  9406. Import into repository, 36
  9407. existing source, 129
  9408. manual directory creation, 130
  9409. third-party source, 145
  9410. svn info command, 63, 103,
  9411. 201
  9412. Install Subversion, 28, 151–173
  9413. firewall issues, 153, 154
  9414. HTTP protocol, 157
  9415. on Linux, 152
  9416. svn+ssh protocol, 154
  9417. svnserve , 153
  9418. on Windows, 151
  9419. as Windows service, 153
  9420. IntelliJ IDEA IDE, 185
  9421. Internet, access repository over,
  9422. 61
  9423. J
  9424. Java (Jakarta) conventions, 131
  9425. jMock library, 145, 149
  9426. K
  9427. Keyword
  9428. $ Author $, 69
  9429. $ Date $, 68
  9430. $ HeadURL $, 69
  9431. $ Id $, 69
  9432. $ LastChangedBy $, 69
  9433. $ LastChangedDate $, 68
  9434. $ LastChangedRevision $, 68
  9435. $ Rev $, 68
  9436. $ Revision $, 68
  9437. $ URL $, 69
  9438. Keyword expansion, 68
  9439. in third-party source, 150
  9440. L
  9441. $ LastChangedBy $ keyword, 69
  9442. $ LastChangedDate $ keyword, 68
  9443. $ LastChangedRevision $
  9444. keyword, 68
  9445. lib/ directory, 142
  9446. Line feed (EOL style), 72
  9447. Linker, finding libraries, 143
  9448. Linux installation, 152
  9449. and Apache, 157, 162
  9450. setting groups and sticky bits,
  9451. 155
  9452. svn list command, 201
  9453. svn lock command, 100, 201
  9454. Locked-out of repository, 155
  9455. Locking, 22, 99–106
  9456. L OG 219 P ROJECT
  9457. breaking, 104
  9458. enabling, 101–102
  9459. hook scripts, 105
  9460. importance of, 100–101
  9461. optimistic, 23
  9462. strict, 23, 86
  9463. token, 103, 104, 206
  9464. unmergeable files, 106
  9465. when to use, 106
  9466. Log
  9467. of changes, 1, 91
  9468. making messages meaningful,
  9469. 92
  9470. svn log command, 41, 91, 101,
  9471. 201
  9472. -r option, 93
  9473. --stop-on-copy option, 126
  9474. -v option, 94
  9475. --verbose option, 42
  9476. $Log$ keyword (not supported), 70
  9477. svn ls command, 177
  9478. M
  9479. -m option
  9480. to svn commit , 41, 91
  9481. to svn import , 36
  9482. Merge, 22, 64
  9483. automatic on update, 23
  9484. bug fix, 122, 124
  9485. changes, 44, 47
  9486. conflict, 24, 48, 87
  9487. graphical, 184
  9488. svn merge command, 97, 124,
  9489. 202
  9490. to revert changes, 96
  9491. Metadata
  9492. project, stored, 11
  9493. Method
  9494. IDE versioning of, 15n
  9495. Migrating CVS or RCS to
  9496. Subversion, 174–177
  9497. Mime type, 73
  9498. svn mkdir command, 130, 202
  9499. mod authz svn , 159
  9500. mod dav svn , 59, 159, 162
  9501. svn move command, 77, 203
  9502. refactor repository, 109
  9503. Multiple projects, 108, 128, 135
  9504. using externals, 137
  9505. über project technique, 136
  9506. Multiple repositories, 109
  9507. N
  9508. Naming projects, 128
  9509. Naming tags and branches, 115f,
  9510. 123
  9511. Network, 55–61
  9512. choosing right type, 60
  9513. firewall, 153, 154
  9514. offline access, 11
  9515. to access repository, 10
  9516. repository URLs, 79
  9517. scheme, 55
  9518. with syn+ssh , 154–157
  9519. with synserve, 153–154
  9520. VPN, 10
  9521. NFS (Network File System), 35
  9522. --no-auto-props option
  9523. to svn import , 150
  9524. --non-recursive option
  9525. to svn add , 66
  9526. Norddahl, Magnus, 153
  9527. Notepad editor, 43
  9528. NUnit (example of library), 141
  9529. O
  9530. Offline access, 11
  9531. Open-source
  9532. free repositories for, 85
  9533. Optimistic locking, 23
  9534. P
  9535. Password, 164
  9536. patch command, 85
  9537. Path names, relative in build, 143
  9538. philosophy, 53
  9539. plink.exe , 58
  9540. Pragmatic Starter Kit, vi, 53
  9541. svn praise command, 94
  9542. PREV revsion, 81
  9543. Project, 15
  9544. characteristics, 128
  9545. code freeze (avoiding), 19
  9546. communication, 49
  9547. creating, 34, 128–140
  9548. directory structure, 131, 132,
  9549. 134f
  9550. importing, 36
  9551. incorporate third-party code,
  9552. 148
  9553. multiple ˜ s, 108
  9554. release, 115, 119
  9555. P ROMPT 220 SSH
  9556. sharing code, 24
  9557. subprojects, 129
  9558. tagging latest build, 113
  9559. Prompt, 29, 31
  9560. svn propdel command, 68, 203
  9561. svn propedit command, 67,
  9562. 203
  9563. Properties, 66–75
  9564. naming, 67
  9565. setting automatically, 74, 150
  9566. svn:eol-style , 72
  9567. svn:executable , 74
  9568. svn:externals , 137
  9569. svn:ignore , 71, 135
  9570. svn:keywords , 68, 69, 150
  9571. svn:mime-type , 66, 73
  9572. versioning, 7
  9573. svn propget command, 68, 203
  9574. svn proplist command, 68,
  9575. 204
  9576. svn propset command, 67, 204
  9577. Putty (SSH on Windows), 58, 154,
  9578. 186
  9579. R
  9580. -r option
  9581. to svn blame , 95
  9582. to svn checkout , 63
  9583. to svn diff , 46, 82
  9584. to svn log , 93
  9585. r1:r2, 81
  9586. Rasmussen, Robert, vi
  9587. RCS, migrating to Subversion,
  9588. 174–177
  9589. README file, 132
  9590. Recipes, 208
  9591. Refactoring, 75, 77
  9592. Release
  9593. fixing bugs in, 121
  9594. generating, 119
  9595. Remote file system, 35
  9596. Removing a change, 95
  9597. svn rename command, 77
  9598. Repositories
  9599. directories in, 129
  9600. Repository
  9601. access rights, 57, 59
  9602. add file to, 66
  9603. backing up, 170–173
  9604. creating, 33
  9605. defined, 9
  9606. directories in, 16
  9607. external, 137
  9608. files stored in, 15
  9609. free for open-source, 85
  9610. importing into, 36, 145
  9611. over Internet, 61
  9612. locking, 22
  9613. migrating from CVS or RCS,
  9614. 174–177
  9615. multiple ˜ ies, 109
  9616. ˜ -wide numbering, 16, 41
  9617. projects in, 15, 108, 128
  9618. stores differences, 16
  9619. tag, 18
  9620. updating, 41
  9621. URL, 36, 37, 55, 79
  9622. wedged, 155
  9623. what to store in, 11–12
  9624. Reserved checkout (Subversion
  9625. 1.2), 86
  9626. svn resolved command, 90,
  9627. 204
  9628. $ Rev $ keyword, 68
  9629. svn revert command, 88, 95,
  9630. 205
  9631. Revision
  9632. BASE, 81
  9633. COMMITTED, 81
  9634. by date, 81
  9635. HEAD, 81
  9636. identifiers, 80
  9637. mixed, 42, 112
  9638. PREV, 81
  9639. range, 81
  9640. $ Revision $ keyword, 68
  9641. --revision option
  9642. to svn switch , 118
  9643. Roberts, Mike, vi
  9644. Rupp, David, vi
  9645. S
  9646. Secure Socket Layer (SSL), 61
  9647. Security, 163–169
  9648. Shell, 29
  9649. --show-updates option
  9650. to svn status , 46, 98
  9651. Source code, 11
  9652. importing third party, 144
  9653. src/ directory, 133
  9654. SSH, 57
  9655. SSL (S ECURE S OCKET L AYER ) 221 T AG
  9656. key manager (SSHKeychain),
  9657. 186
  9658. troubleshooting, 155
  9659. SSL (Secure Socket Layer), 61
  9660. Starter Kit, vi, 53
  9661. svn status command, 40, 45,
  9662. 98, 205
  9663. --show-updates option, 46,
  9664. 98
  9665. -u option, 46, 98
  9666. Sticky bit (Unix groups), 155
  9667. --stop-on-copy option
  9668. to svn log , 126
  9669. Strict locking, 23
  9670. Subversion
  9671. benefits, 6
  9672. command summary, 197–207
  9673. compared to CVS, 7
  9674. config file, 58, 75
  9675. download URL, 33
  9676. file locking, 99–106
  9677. free repositories, 85
  9678. hook scripts, 105
  9679. installation, 151–153
  9680. migrating from CVS or RCS,
  9681. 174–177
  9682. offline access to, 11
  9683. philosophy of using, 53
  9684. recipes, 208
  9685. security, 163
  9686. third-party clients, 178
  9687. troubleshooting, 156, 157
  9688. user name, 57
  9689. versions, 34
  9690. svn command
  9691. --version option, 32
  9692. svn commands
  9693. add , 66, 198
  9694. ann , 94
  9695. annotate , 94
  9696. blame , 94, 198
  9697. cat , 198
  9698. checkout , 39, 45, 62, 198
  9699. cleanup , 199
  9700. commit , 41, 66, 76, 91, 199
  9701. copy , 75, 119, 199
  9702. delete , 199
  9703. diff , 40, 73, 80, 85, 200
  9704. export , 200
  9705. import , 36, 129, 200
  9706. info , 63, 103, 201
  9707. list , 201
  9708. lock , 100, 201
  9709. log , 41, 91, 101, 201
  9710. ls , 177
  9711. merge , 96, 97, 124, 202
  9712. mkdir , 130, 202
  9713. move , 77, 109, 203
  9714. praise , 94
  9715. propdel , 68, 203
  9716. propedit , 67, 203
  9717. propget , 68, 203
  9718. proplist , 68, 204
  9719. propset , 67, 204
  9720. rename , 77
  9721. resolved , 90, 204
  9722. revert , 88, 95, 205
  9723. status , 40, 45, 98, 205
  9724. switch , 117, 118, 120, 207
  9725. unlock , 104, 207
  9726. update , 44, 49, 64, 87, 207
  9727. svn protocol, 56
  9728. svn+ssh protocol, 57, 154
  9729. svn:eol-style property, 72
  9730. svn:executable property, 74
  9731. svn:externals property, 137
  9732. svn:ignore property, 71, 135
  9733. svn:keywords property, 68, 69,
  9734. 150
  9735. svn:mime-type property, 66, 73
  9736. SVN EDITOR environment
  9737. variable, 43
  9738. svnadmin command
  9739. --version option, 32
  9740. svn load dirs.pl script, 147
  9741. SVN:Notify, 186
  9742. svnserve command, 56, 153, 163
  9743. --daemon option, 153
  9744. invoked by svn+ssh , 154
  9745. --root option, 110, 153
  9746. svn switch command, 117, 118,
  9747. 120, 207
  9748. --revision option, 118
  9749. T
  9750. Tag, 18, 107, 112–113
  9751. bug fix, 114
  9752. as a copy, 76
  9753. making read-only, 113
  9754. naming, 115f
  9755. release, 114, 119
  9756. T EST CODE 222 W ORKING COPY
  9757. as slice through repository,
  9758. 112
  9759. third-party source, 146
  9760. Test code, 135
  9761. Testsweet project, 176
  9762. Text vs. binary files, 73
  9763. Third-party, 141–150
  9764. binary libraries, 141
  9765. header (include) files, 142
  9766. import ˜ source, 145
  9767. including code in project, 148
  9768. modifying, 149
  9769. source code, 134, 144
  9770. tagging their release, 146
  9771. updating source, 146
  9772. version numbers, 142
  9773. what to include, 142
  9774. Time machine, 2
  9775. Tortoise
  9776. graphical merge, 184
  9777. TortoisePlink SSH client, 58
  9778. TortoiseSVN client, 178
  9779. Transactional commit, 7
  9780. Troubleshooting, 156, 157
  9781. Tunnel, 61
  9782. configuration, 58, 75
  9783. Tunnel over SSH, 57
  9784. Typographic conventions, viii
  9785. U
  9786. -u option
  9787. to svn status , 46, 98
  9788. ¨
  9789. Uber project technique, 136
  9790. umask, 155
  9791. UNDO button, 1, 18
  9792. Undoing a change, 95
  9793. svn unlock command, 104, 207
  9794. Update, 14, 41
  9795. svn update command, 44, 64,
  9796. 207
  9797. conflict and, 87
  9798. status flags, 49, 64
  9799. URL, 55
  9800. file://... , 37
  9801. http:// ..., 59
  9802. repository, 36, 37, 79
  9803. scheme, 55
  9804. svn:// ..., 56
  9805. svn+ssh:// ..., 57
  9806. $ URL $ keyword, 69
  9807. User name, 57, 164
  9808. connecting via SSH, 154
  9809. util/ directory, 134
  9810. V
  9811. -v option
  9812. to svn log , 94
  9813. vendor/ directory, 134, 142
  9814. vendorsrc/ directory, 134, 145
  9815. --verbose option
  9816. to svn log , 42
  9817. Version, 16
  9818. numbering, 16, 41
  9819. what gets ˜ ed, 7
  9820. --version option
  9821. to svn , 32
  9822. to svnadmin , 32
  9823. Version control
  9824. advantages, 1
  9825. philosophy, 53
  9826. Virtual Private Network (VPN), 10,
  9827. 61
  9828. VISUAL environment variable, 43
  9829. Visual Studio IDE, 185
  9830. W
  9831. WebDAV, 161
  9832. Wedged repository, 155
  9833. Wilma and Fred, 2, 22
  9834. Windows
  9835. installation, 151
  9836. Putty (SSH), 58, 154, 186
  9837. shell, 29
  9838. svnserve , 153
  9839. Visual Studio IDE, 185
  9840. Windows Explorer
  9841. adding Subversion to, 178
  9842. Working copy
  9843. checkout into, 62
  9844. definition, 12
  9845. difference with repository, 83
  9846. ignoring files, 71
  9847. location, 38
  9848. seeing what’s changed, 80
  9849. status of, 97
RAW Paste Data