Hands On SVN Tutorial http://www.nersc.gov/nusers/resources/servers/svn.php 1. Verify you have an active SVN account. SSH into your svn account with your NIM password. Beware you have a limited shell on this machine so you won't be able to do anything once you get in. > ssh username@svn.nersc.gov log out. 2. Make sure you are on a machine with an svn client. (Type 'which svn' to see if you have one.) If your lap top doesn't have a client, we can help you after the tutorial, for now, ssh to bassi or davinci. 3. (Optional) Setup SSH keys. Without keys you will have to type your password many times, for the initial checkout perhaps even 3 times in a row. 4. Checking out a working copy of an existing repository For this tutorial we have created a repository open to everyone, called "usg_tutorial" To check it out type: >> svn checkout svn+ssh://svn.nersc.gov/svn/usg_tutorial (returned output) A usg_tutorial/kantypas_newdir A usg_tutorial/kantypas_newdir/anotherfile.txt A usg_tutorial/zz2.txt A usg_tutorial/firstfile.txt A usg_tutorial/kantypas.txt A usg_tutorial/kantypasdir A usg_tutorial/kantypasdir/bs1 A usg_tutorial/kantypasdir/bs2 A usg_tutorial/kantypasdir/bs3 A usg_tutorial/hjw.bs A usg_tutorial/user1.txt A usg_tutorial/testdir A usg_tutorial/user2.txt Checked out revision 11. Running this command will create a directory called "usg_tutorial" which is your working copy of the svn repository stored on the svn server. You will only have to type out this long path name once to check out the working copy. Once you have a working copy checked out, SVN will keep track of the path to your repository. (This is an improvement from CVS where it was often recommended to set environment variables like $CVSHOME) Typing shortcut hint: 'co' is short for 'checkout' ie: svn co svn+ssh://svn.nersc.gov/svn/usg_tutorial 5. Create a file and check it into the repository >> cd usg_tutorial Create a file .txt >> vi .txt Type a few lines and close the file. Check on the 'status' of your working copy compared to the version you checked out of the repository. >> svn status ? kantypas.txt This means the svn repository doesn't know anything about the file kantypas.txt So we need to tell the repository we want to add it. >> svn add .txt A kantypas.txt Check on the status of your working copy against the what you checked out of the repo. >> svn status A kantypas.txt You have now added ('A' stands for add) the file to the repository but you still need to 'commit' it to the repository. The 'commit' command is used to send changes from your working copy to the repository. Typing shortcut hint: 'st' is short for 'status' ie: >> svn st >> svn commit -m "commit my first file to svn repo" .txt Adding kantypas.txt Transmitting file data . Committed revision 12. The '-m' flag is for a log message. This is required in svn. It is helpful to be as descriptive as possible. You can check on the status of your working copy against repo version you checked out again to verify everything has been checked into the repo >> svn status (empty return) You have successfully commited your first file. Typing shortcut hint: 'ci' is short for 'commit' ie: >> svn ci -m "log message" ... 6. Update your working copy from the repository. Assuming everyone in the room has committed a file named after his or her username, when we update the repo we should get a bunch of new files in the repo. >> svn update A user1.txt A user2.txt Updated to revision 13. The 'A' tells you the above files have been 'Added' to your repository. Typing shortcut hint: 'up' is short for 'update' ie: >> svn up 7. Edit the file your neighbor to the right created. (We will deal with 'conflicts' later, for now, let's really see if we can avoid them and have only one person editing a given file.) >> vi .txt Type a few lines or delete or edit the existing lines, close file. Then check on the status of the working copy against the repo version you checked out. >> svn status M user1.txt The 'M' tells you that the file 'user1.txt' has been modified, that is, it is different from the version you checked out of the repo. 'svn status' without any options is a 'local' function. (More on this later.) It compares your local working copy to the version you checked out of the repo, NOT the latest committed version in the repo. Another way to see how your working copy is different from the version you checked out of the repository is with the 'svn diff' command. >> svn diff Index: user1.txt =================================================================== --- user1.txt (revision 13) +++ user1.txt (working copy) @@ -1,3 +1,7 @@ This is user1 committing a file. blah blah blah + +Adding some comments to this file. + +SVN is great. The lines that were added or changed from the committed repository version have a '+' or a '-' in front of them. Note, you can do an 'svn diff' on the entire repo or just a single file like below. >> svn diff .txt Commit this file to the repo. (Hopefully we will have no conflicts!) >> svn commit -m "committing edits to right neighbor's txt file" Sending user1.txt Transmitting file data . Committed revision 14. Now you have committed this file to the repository. Note that everytime anyone commits a file or group of files to the repository, the repository revision number is incremented. 8. Update your working copy from the repo and check the svn 'logfile' First update your working copy. With many people committing changes you should see many updates. >> svn update U user1.txt Updated to revision 14. The 'U' stands for 'Updated'. Next check the logfile. This will show you all the log messages from each person's commit. >> svn log or probably more useful with verbose flag -v >> svn log -v | less or only examine a single file >> svn log -v .txt ------------------------------------------------------------------------ r5 | hjw | 2007-06-27 15:51:33 -0700 (Wed, 27 Jun 2007) | 1 line Changed paths: A /hjw.bs this update included hjw's file ------------------------------------------------------------------------ r4 | kantypas | 2007-06-27 15:44:58 -0700 (Wed, 27 Jun 2007) | 1 line Changed paths: M /firstfile.txt resolved conflict ------------------------------------------------------------------------ r3 | zz217 | 2007-06-27 15:40:33 -0700 (Wed, 27 Jun 2007) | 1 line Changed paths: A /zz2.txt zz2 addition ------------------------------------------------------------------------ r2 | wyang | 2007-06-27 15:39:17 -0700 (Wed, 27 Jun 2007) | 1 line Changed paths: M /firstfile.txt my addition --wyang ------------------------------------------------------------------------ r1 | kantypas | 2007-06-27 15:36:22 -0700 (Wed, 27 Jun 2007) | 1 line Changed paths: A /firstfile.txt committing first file ------------------------------------------------------------------------ 9. Manipulating files, creating directories, copying files Create a directory in svn >> mkdir Check the status of your working copy >> svn status ? kantypas The '?' tells you svn doesn't know anything about the directory kantypas. (Note, you also could do an 'svn mkdir '.) Next cd to that directory and create a file, and type something in it, close it. >> cd >> vi anotherfile.txt >> ls anotherfile.txt Try checking on the status of your working copy. >> pwd ~/usg_tutorial/kantypas >> svn status svn: '.' is not a working copy The repository doesn't know anything about the directory or the file 'anotherfile.txt' in it. We need to first add these to the repo. Go back one level and add directory to the repository. >> cd .. >> svn add A kantypas A kantypas/anotherfile.txt Note that the files in a directory get recursively added. This is different from CVS where a file and a directory were separate cases. Commit the directory and file within it. >> svn commit -m "committing the directory kantypas" kantypas Adding kantypas Adding kantypas/anotherfile.txt Transmitting file data . Committed revision 15. Both the directory and the file within it were committed with the same command and log message. 10. Moving and Renaming Files A big improvement over CVS is SVN's ability to move or rename files just as you would in unix. Take the directory and rename it to _newdir >> svn mv kantypas kantypas_newdir A kantypas_newdir D kantypas/anotherfile.txt D kantypas This command really does an 'svn add' and an 'svn rm' (see next) in the same command. The 'D' stands for Deleted. The change MUST still be committed! >> svn commit -m "changed name of directory" Deleting kantypas Adding kantypas_newdir Committed revision 21. 11. Deleting files When you delete a file, it will no longer be a part of the current revision, however its history is saved. You can always checkout an earlier version to recover a deleted file. Let's delete 'anotherfile.txt' under _newdir. >> cd kantypas_newdir >> ls anotherfile.txt >> svn rm anotherfile.txt D anotherfile.txt You MUST do an 'svn rm' not simply an 'rm'. You first schedule the file to be removed and then you commit the change to the repository. The 'D' here indicates the file is scheduled to be removed. BUT, you still MUST commit the change. To prove this, check the status of your working copy. >> svn status D anotherfile.txt Whenever 'svn status' comes back non-empty, it means your working copy has modifications. Commit the file >> svn commit -m "removing anotherfile.txt" anotherfile.txt Deleting kantypas_newdir/anotherfile.txt Committed revision 22. 12. Get information about the repository. This simple command gives you information about who made the last change, the path to the repo, the revision number, etc. >> svn info Path: . URL: svn+ssh://svn.nersc.gov/svn/usg_tutorial Repository UUID: 2b2a2b7a-7689-46cc-b653-01a84abd3c82 Revision: 16 Node Kind: directory Schedule: normal Last Changed Author: kantypas Last Changed Rev: 16 Last Changed Date: 2007-10-08 18:03:06 -0700 (Mon, 08 Oct 2007) 13. More on 'svn status' 'svn status' is a very useful command and one that was absent from CVS. CVS users will tend to want to use 'cvs update' when they want to see what modifications they have made to their local working copy. SVN does this with the 'status' command so that changes from the repository are not incorporated in a user's local working copy. So far we have only used 'svn status' to see how our local has changed since we checked out or updated from the repository. In this case 'svn status' is purely a 'local' command, meaning that the central repository is not contacted. But sometimes it is useful to know how your working copy is different from the repository. You can do this with the --show-updates (-u) option >> svn status -u * 54 user3.txt Status against revision: 55 This says that if you were to run an svn update from your local copy, user3.txt would get updated. Or stated another way, user3.txt has changed and before you can commit user3.txt to the repo, you would have to merge changes by updating the file. (More on merging later.) 14. Working with different revisions. In SVN whenever any file is committed the entire repository's revision number increases by one. So if your code is broken, but you know you had a working revision 2 weeks ago, you can get the repository revision number from 2 weeks ago and check out a working copy of the repository as it was then. (This is another major improvement over CVS, where revision numbers were based on individual files rather than the entire repo as a whole. For example, one file could be on revision 58 and another on revision 4 which made things more complicated for retrieving earlier revisions.) You can check out a working copy of an entire repository at a given revision, or only a single file. Let's check out a specific version of the file .txt. First, find out which version you want to check out. >> svn log kantypas.txt ------------------------------------------------------------------------ r16 | kantypas | 2007-10-08 18:03:06 -0700 (Mon, 08 Oct 2007) | 1 line update to file ------------------------------------------------------------------------ r12 | kantypas | 2007-10-08 16:30:39 -0700 (Mon, 08 Oct 2007) | 1 line my first file to svn repo ------------------------------------------------------------------------ In this example, I will update to an earlier revision, number 12. You should update to the revision number appropriate to your file. Update to revision number 12 >> svn update -r 12 U kantypas.txt Updated to revision 12. The '-r' flag specifies the revision number. Take a look at this file. You should now have the file as it was committed to the repo at the revision specified. There are additional ways to checkout or update certain revisions based on the date of a previous commit to the repository. (The -r flag can be used with a number of svn commands, update, checkout, diff.) You can always type the following for help. >> svn help update Now we have files in the repo which are at different version numbers and this can complicate things. A plain 'svn diff' or 'svn status' won't tell us anything because these calls are 'local' and compare our working copy to the repository revisions we checked out or updated. We have asked svn to update .txt to a specfic revision so 'svn diff' will come back empty. >> svn diff kantypas.txt (empty return, no differences) We need to ask the difference between our working copy and a specific revision. >> svn diff -r HEAD or >> svn diff -r HEAD kantypas.txt Index: kantypas.txt =================================================================== --- kantypas.txt (revision 16) +++ kantypas.txt (working copy) @@ -1,6 +1,3 @@ This is my first file in svn. Let's add another line here. - -I am going to add some more stuff to -this file here. We have asked for the difference between our working copy and the "HEAD" which is the latest committed version in the repository. "HEAD" is just defined to be the revision number of the last commit. This tells us that the file kantypas.txt is different from the latest (HEAD) version which in this example case was revision 16. You could also have typed the following for the same result. 'HEAD' is just a nice shortcut so you don't have to constantly look up the latest revision number. >> svn diff -r 16 Finally, let's bring .txt up to date with the latest revision of the repository. >> svn update .txt U kantypas.txt Updated to revision 16. Note this is really the same as >> svn update -r HEAD .txt The '-r HEAD' is implied for many svn commands. 15. Multiple people editing the same file The purpose of a version control system is to keep track of changes and edits made by users. Some systems do this by locking a file so only one person can edit it at a time. This is a solution, but for many cases, a clumsy one. This precludes two or more users from working on the same file at the same time. And if someone doesn't release the lock, you have to track that person down. Ideally a version control system should be able to intelligently merge changes into files. Where it can not resolve the conflict, it should notify the user and ask for help. If you really want to use locks see 'svn help lock' for more information. Partner up with a person next to you and choose one of your .txt files to edit. Make sure your working copy is updated >>svn update Each partner should open up his or her own local copy of the same file, let's call it, usernameA.txt. Make one partner Person A, the other Person B Person A add a line at the very beginning of the file and person B add a line at the very end of the file. For now, just don't edit the same line. Both people check on the status of the working copy >> svn status M kantypas.txt Now, person A commit the file to the repository >> svn commit -m "add new first line" .txt Sending kantypas.txt Transmitting file data . Committed revision 17. Now, person B commit the file to the repository >> svn commit -m "add new last line" .txt Sending kantypas.txt Transmitting file data .svn: Commit failed (details follow): svn: Out of date: 'kantypas.txt' in transaction '17-1' This 'commit' failed because person B does not have the most updated copy of kantypas.txt Person B must update before committing. >> svn update .txt G kantypas.txt Updated to revision 17. This says that the file was successfully merGed. 'G' is used because 'M' was already taken for the 'Modified' state. Person B, go ahead and look at the file. It should have Person A's edits in it as well as your own. Person B commit merged file >> svn commit -m "add last line" .txt Sending kantypas.txt Transmitting file data . Committed revision 18. Now Person A can update to get the latest revision. >> svn update .txt U kantypas.txt Updated to revision 18. 16. Conflicts Continue with your partner. Make sure both of your working copies are up to date by using the 'svn update' command. Now again, each person, open up the file .txt. This time edit the same line or the same few lines. Now Person B commit the changes >> svn commit -m "I bet this will make a conflict for Person A" .txt Sending kantypas.txt Transmitting file data . Committed revision 19. Now Person A commit the changes >> svn commit -m "trying to commit my changes" .txt Sending kantypas.txt Transmitting file data .svn: Commit failed (details follow): svn: Out of date: 'kantypas.txt' in transaction '19-1' The repo is out of date, so Person A must update to get the latest version. >> svn update .txt C kantypas.txt Updated to revision 19. But... we have a problem. The 'C' means we have a Conflict. SVN doesn't know how to resolve the differences between the working copy and committed repository version. But, SVN gives you some options. Person A type 'ls'. You will see 4 different files of .txt, in my case kantypas.txt >> ls kantypas.txt* kantypas.txt kantypas.txt.mine kantypas.txt.r18 kantypas.txt.r19 Take a look at each of these files. -kantypas.txt is the conflicted file and shows the difference between your version and the committed repo version with a diff like syntax -kantypas.txt.mine is your version -kantypas.txt.r19 is repo version, that is the version with person B's edits. -kantypas.txt.r18 is the repo version before any of this conflict stuff started So Person A, you have options. In this example, every member of the repo has equal 'power' so Person A is free to put in his or her changes over Person B's. Person A can choose he or she wants to commit, the 'mine', r19 or r18 versions. Or Person A can edit the conflicted file kantypas.txt merging the changes from Person B by hand. Either resolve conflicts by hand by editing the file, removing the diff like syntax. >> vi kantypas.txt or choose one of the revisions and copy it to kantypas.txt >> cp kantypas.txt.mine kantypas.txt Next, Person A, tell svn you have resolved the conflict >> svn resolved kantypas.txt Resolved conflicted state of 'kantypas.txt' Now if you type 'ls' you will see all the extra files have been cleaned up. >> ls kantypas.txt* kantypas.txt Finally, Person A, you still have to commit this file to the repository >> svn commit -m "resolved conflict" kantypas.txt Sending kantypas.txt Transmitting file data . Committed revision 20. 17. Overview You can get along fine in SVN by knowing just a handful of commands - svn checkout - svn update - svn commit - svn add - svn diff - svn status - svn mv - svn rm - svn help The next set of commands help with more advanced features - svn log - svn info - svn import Import an existing directory into an svn repository - svn export SVN leaves .svn directories in a repository. To have a cleaner version for say a software release or a tar ball to send someone else not using SVN you can use the 'export' command. - svn copy Create a copy of a file or entire repo, remembering history. SVN developers recommend repositories are setup with a main 'trunk' and then a separate area for 'branches' and 'tags' In software development it is common to work on a new risky feature in a 'branch' of the repository. When the developer is comfortable the new feature is working and tested the 'branch' can be merged back into the main 'trunk'. Alternatively, when a software version is release, it is necessary to keep track of the released version. In CVS terms, this used to be called a 'tag'. In SVN, use the 'svn copy' command to create a 'branch' or a 'tag' of a specific version. - svn merge Used to merge a file or directory of files together. See 'svn help merge' for more details - svn revert Removes local modifications of a file, reverting the file back to the revision of last update. This call has local symantics only. - svn cleanup If you ever run into problems with your svn repository you don't understand try this command. In this tutorial we have gone over user features, however we can also setup your repository to have different administrative features set. For example, you can use email notification so everyone in a group knows when a member has committed a file to the repository. You can also change priviledges so a person's commit to a repository must be reviewed first. The web documentation for svn is very good http://svnbook.red-bean.com/ For downloading an svn client http://subversion.tigris.org/