====== SVN getting started ====== The complete reference for SVN is the [[http://svnbook.red-bean.com|svn red book]]. ====== Basics ====== SVN is used from a terminal program and allows you to checkout a repository of code for use and editing locally on your machine. If you prefer a GUI you might try [[https://www.zennaware.com/cornerstone/index.php|Cornerstone]]. If you are simply using a repository without making any changes, you should at least be familiar with using the commands: checkout and update. If you are making changes, then you should be familiar with the commands: commit, status, log, diff, add and delete. ===== Checkout ===== To first checkout a repository, you will have used svn checkout, for example: svn checkout http://gru.brain.riken.jp/svn/mgl/trunk mgl This will create a directory containing all the files in the repository on your local machine. You may use and edit this repository as much as you like without affecting others. Note that you can put the repository into any directory name that you want, for example: svn checkout http://gru.brain.riken.jp/svn/mgl/trunk mymgldir ===== Update ===== To get updates from the repository, you can do: svn update You can choose to update the whole repository by using the above, or individual directories or files: svn update filetoupdate.m ===== Status ===== To see what you have changed in your working copy of the repository, you do: svn status This will give you a list of files that are changed, it will look something like this: ? task/someFileNotInTheRepository.m M mgllib/modifiedFile.m The ? means that the files is not in the repository. The M means that you have modified the file. These are the most common codes you will see, but there are other codes as well, to see them you can do (Note that you can get help on all commands this way): svn status --help If you want to get what changes have been made in the repository as well as your own changes in your working directory (i.e. this will let you know what files will be modified when you do an svn update): svn -u status ===== Diff ===== To see what your modifications are, you can do a diff between your version and the version in the repository: svn diff modifiedFile.m This will list all modifications -- I find it hard to read, but lines beginning with "-" are lines that are removed in your version and line beginning with "+" are lines you have added. ===== Commit ===== If you want to commit your changes to the repository (this will make them available to all others using the repository (or if you are the only one using the repository, will save that as a version that you can always retrieve): svn commit This will bring up whatever editor you have specified in your environment. It appears on MAC OS X it looks at the variable VISUAL (though one would think it should be EDITOR): setenv VISUAL /Applications/Emacs.app/Contents/MacOS/Emacs You can also commit without bringing up the editor by specifying the message in the commit command: svn commit -m "My commit message" ===== Log ===== To see a log of everything that has happened to a file, you can do: svn log filename.m ===== Add ===== To add a file to the repository: svn add newFilename.m Note that after you run this command, if you want the file to **actually** be added, you will have to svn commit. ===== Delete ===== To delete a file from the repository: svn delete filenameToDelete.m Again, svn commit to make the actual change. Note that it is possible to [[grupub:svn#retrieving_deleted_or_old_version_of_files|retrieve]] a deleted file from the repository if for some reason you need it later. SVN will take care of deleting the file in your directory as well, so no need to rm the file. ====== Resolving conflicts ====== ===== File conflicts ===== These happen when two people edit the same file and try to commit and svn does not know how to merge the changes (this only happens when changes in the text are in conflict with each other, for edits that are far away in the file, svn usually can merge the changes without conflict). If it can't you have to go into the file and edit which version you want. Look for areas with: <<<<<<< filename your changes ======= code merged from repository >>>>>>> revision and edit it so only the version you want exists. ===== Tree conflicts ===== ==== local delete, incoming edit upon update ==== These happen when you are deleting/moving files and there is a conflict with another file. You might get something like this: D C filename.m > local delete, incoming edit upon update It means that you are trying to delete a file that someone else has updated and svn does not know what to do. In this case, you might (after copying your local version somewhere else if you want to make sure to have a copy), try svn revert filename.m Which reverts all local changes to a status before you did anything. THen svn update and try doing the delete again if necessary. ==== working copy locked ==== Sometimes if you crash out while doing an svn commit or update, you can get "stale locks" with the message "working copy locked". To fix this, run: svn cleanup ===== Using FileMerge to resolve conflicts ===== You can use FileMerge to visually resolve conflicts. To set this up, you need to do the following: - Install the script below somewhere in your path and call it fmmerge #!/bin/sh # # Wrapper script to use FileMerge as a merge-tool-cmd in Subversion # FM="/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge" FMDIFF="$(basename $0)" GN="/usr/local/bin/growlnotify" while [ $# != 0 ]; do echo $1 case $1 in -*) echo "Unknown option: $1" 1>&2 exit 1 ;; *) if [ -z "$ancestorfile" ]; then ancestorfile="$1" elif [ -z "$leftfile" ]; then leftfile="$1" elif [ -z "$rightfile" ]; then rightfile="$1" elif [ -z "$mergefile" ]; then mergefile="$1" # else # echo "Too many files to start merge" 1>&2 # exit 2 fi esac shift done if [ -z "$ancestorfile" ] || [ -z "$leftfile" ] || [ -z "$rightfile" ] || [ -z "$mergefile" ]; then echo "Usage: $0 [options] oldfile yourfile myfile outputfile" 1>&2 exit 2 fi echo Starting FileMerge... 1>&2 [ -x "$GN" ] && "$GN" -a FileMerge -n "$FMDIFF" -m "$mergefile" "Starting FileMerge" exec "$FM" -left "$leftfile" -right "$rightfile" \ -ancestor "$ancestorfile" -merge "$mergefile" This is a slightly modified version of the [[http://www.defraine.net/~brunod/fmdiff/#heading_toc_j_5|original]] which did not work for me since svn mysteriously called it with five input arguments. - Edit your ~/.subversion/config file to have the following line (I think it can be anywhere in the file, but you may want to put at the end of the [helpers] section). merge-tool-cmd = /usr/local/bin/fmmerge Make sure to change the path correctly to the location of the function you created above. - When you get a conflict, you will see the following Select: (p) postpone, (df) diff-full, (e) edit, (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: l Choose l (launch) and it will now run FileMerge! - If you are happy with the changes that you have made in FileMerge, save and quit and then you will see Select: (p) postpone, (df) diff-full, (e) edit, (r) resolved, (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: r Choose r (resolve) and you are done. You will need to commit your changes. ====== Create a repository ====== To create a repository, go to the svn directory on the server: ssh -l justin gru.brain.riken.jp cd /Library/WebServer/svn Then make the repositiory svnadmin create repositoryName Then make sure it has permissions that are readable by the web server (you may need to be root to do this): chown -R www repositoryName That's it. To checkout the repository on another computer, do: svn checkout http://gru.brain.riken.jp/svn/repositoryName ====== Move a repository ====== To move a repository, you first move the repository on the server side. If you are just changing names or the directory of the repository, simply mv the repository. If you are moving from one server to another you dump the contents to a temporary file, create the new repository and restore the contents from the temp file: svnadmin dump /path/to/repository > repository-name.dmp cd /path/to/new-repository svnadmin create repository-name svnadmin load repository-name < repository-name.dmp After you have moved the repository, you will need to update any checked out repositories with the new path: svn switch --relocate oldRepositoryAddress newRepositoryAddress To make sure that the switch above worked you can either test it (modify file and try to commit), or get info: svn info Which will tell you the repository root (which should reflect the new repository location). ====== SVN branch & merge ====== To create a branch, you use the copy command. For all of our projects we have a trunk directory (main development -- this is the branch everyone is using, so be **very** careful when making changes here) and a branches directory (temporary development, good for when you want to make some local changes without affecting anyone else). If you want to make yourself a new branch, then you can issue an svn copy command (change dev to a name of your choice): svn copy https://cbi.nyu.edu/svn/mrTools/trunk https://cbi.nyu.edu/svn/mrTools/branches/dev Note the https, rather than the http. For some reason, for copies, you must use the https secure site, and it will ask you to accept a certificate. You should accept it permanently. Also, you will need to be a developer with write privileges (ask Valerio for mrTools). Once you have made a copy, check it out (again replace dev with the name of your choice) svn checkout https://cbi.nyu.edu/svn/mrTools/branches/dev mrTools-dev Now you can use this local repository like any other repository. Make edits, update and commit. When you are done making and committing your changes, you should merge the development branch back to the trunk (the main version of the repository). You do this by issuing an svn merge command. First cd to your local version of **trunk** (i.e. main development branch of mrTools that everyone is using). The merge command will then take all of your changes in the dev branch, compare them to what is in the trunk repository and merge them into your local working copy of the trunk: cd ~/proj/mrTools svn merge https://cbi.nyu.edu/svn/mrTools/trunk https://cbi.nyu.edu/svn/mrTools/branches/dev . Note that the command takes the main trunk version of the repository, then the changes that you want to apply from your development repository and then finally the local repository where you want the changes to be applied. You should see something like this: U mrLoadRet/mrGlobals.m If you had changed the mrGlobals.m file, for example. Your changes have not been committed yet though. They are still local changes. To commit them you simply do a commit svn commit But, if you decide something very bad happened, and you don't want to merge your changes in after all, you can always revert your local trunk repository (this will delete all of your local changes -- be careful! If you had other changes in your mrTools main repository that you wanted to keep, those will be lost): svn revert -R . Finally, when you are done with your branch, you can delete it: svn delete https://cbi.nyu.edu/svn/mrTools/branches/dev ====== Binary files ====== SVN should handle binary files just fine. However, sometimes the wrong property can be set on a binary file which causes the file to get munched. Usually this is because svn wrongly has the "eol-style" set. This should only be set for text files, it handles differences in EOL characters between PC, UNIX and Mac files, but will cause problems on binary files. To check whether it has been set, you do: svn proplist binaryfile.mexmac If it looks like this, you are good: Properties on 'binaryfile.mexmac': svn:executable svn:mime-type But, if it looks like this, you will need to svn delete/commit and then add/commit back the file: Properties on 'binaryfile.mexmac': svn:keywords svn:eol-style ====== Retrieving deleted or old version of files ====== First you need to go find what version, you want. Probably easiest is to go look at the log: svn log and then note which revision (rxx) number you want. Once you know that you can look at (but this won't add the version back!) a copy of that file, by doing e.g. (if you wanted revision 32): svn update -r32 fileToGetOldVersionOf.m Note that as soon as you update again (svn update) that local old copy will be removed and you will revert back to the latest version. To retrieve the file permanently, you will need to copy it from the repository: svn copy -r32 http://gru.brain.riken.jp/svn/mgl/trunk/mgllib/mglOpen.m mglOpen.m Then you will need to commit the changes. ====== Retrieving a single file ====== If you just want to get a single file out of the repository (this will not allow you to check the file back in): svn export http://gru.brain.riken.jp/svn/matlab/filename ====== SVN Setup ====== ===== svn vis ssh setup ===== In .ssh/config, add the following: host yoyodyne Hostname localhost Port 7777 ForwardAgent no ForwardX11 no To checkout over ssh: svn co svn+ssh://gru.brain.riken.jp/Library/WebServer/svn/mgl/trunk mgl To checkout over http: svn co http://gru.brain.riken.jp/Library/WebServer/svn/mgl/trunk mgl To checkout from file: svn co file://gru.brain.riken.jp/Library/WebServer/svn/mgl/trunk mgl ===== SVN setup ===== Add this line to load the svn module in httpd.conf LoadModule dav_svn_module libexec/apache2/mod_dav_svn.so And these lines to set up the svn hosting in /etc/apache2/httpd.conf DAV svn SVNParentPath /Library/WebServer/svn # how to authenticate a user AuthType Basic AuthName "Subversion repository" AuthUserFile /Library/WebServer/svn/.htaccess Require valid-user To test, go and make a repository in /Library/Webserver/svn: svnadmin --fs-type fsfs create deleteme chown -R www deleteme Then try to check it out: svn checkout http://gru.brain.riken.jp/svn/deleteme ===== HTTP service update on server ===== Sometimes mac software updates overwrite files relate to http and make svn malfunctioned. Last time, svn didn't work after the updating with giving an error as following,\\ >svn update grubin svn: OPTIONS of 'http://gru.brain.riken.jp/svn/grubin':​ 200 OK (​http://gru.brain.riken.jp)​ In this case, simply edit /etc/apache2/httpd.conf file as superuser. You will find that all svn set to "off", so change "off" to "svn" > DAV off ---> DAV svn and restart http service by following command as superuser (or with sudo). >/usr/sbin/apachectl restart ===== Passwords for SVN ===== Make a password file somewhere: htpasswd -cm .htaccess justin Subsequent passwords get added **without** the -c flag: htpasswd -m .htaccess user2