spot
With this exercize we’ll investigate:
You should have read the slides about subversion to be able to complete this exercize.
Warning
When issuing an svn commit command, always make sure to verify the commit was successful. A typical error is to run the command from the wrong directory. No modification is then committed but this isn’t considered as an error by subversion. For example:
$> svn commit -m "svn doc modification" .
Sending trunk/src/svn.rst
Transmitting file data .
Committed revision 666.
$>
# ==> the commit was successful
$> svn commit -m "svn doc modification" .
$>
# ==> no message nor ack. from svn: OOPSIE !
You can check the state of your repository in the Trac browser or directly via http .
The first step consists in creating your project in the Etudiants svn repository laying out it the right way Subversion Best Practices recommends to structure a repository with three subdirectories: /trunk, /branches, and /tags.
In this very first step we will act directly onto the svn directory getting an URL as argument for svn commands. Then in the later steps we will work in our local workarea getting local file arguments.
$> svn ls https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>
create your project Hello in your repository:
$> svn mkdir https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/Hello \
-m "Creation of Hello project"
create the standard layout:
$> svn mkdir https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/Hello/trunk \
https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/Hello/branches \
https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/Hello/tags \
-m "Proper layout for Hello project"
verify:
$> svn ls -R https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>
finally import your Hello code into the trunk directory:
$> cd ~/Project/Hello
$> svn import . https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/Hello/trunk \
-m "Initial import"
verify again:
$> svn ls -R https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>
The next step consists in initializing your workarea directory which will hold a copy of your previously imported project Hello.
go under your Project directory and rename your unversioned directory:
$> cd ~/Project
$> mv Hello Hello-unversioned
create a working copy (checkout) of the trunk branch of your previously imported project Hello - notice that the local name is your project name:
$> svn checkout https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/Hello/trunk Hello
verify that your workarea is well connected to the right repository and notice the svn metadata directories .svn at each level of your hierarchy project:
$> cd Hello
$> svn info
$> ls -alR
clean the directory:
$> rm -r ~/Project/Hello-unversioned
check the state of your workarea - you should be synchronized:
$> svn status .
During this exercize, we’ll modify one or more files and save (or commit in svn-speak) these modifications into the repository. We’ll first use the traditional cp and rm commands and then their svn counterparts in order to compare their different behaviours. This operation can be repeated many times to artificially increase the history of commands (for the next step.)
When we save the modifications to your repository, you have to fill in a message - with no accentual letters - justifying the modifications.
Go under the src directory which we just added to our svn repository.
modify an existing file (e.g. add a comment to hello.cpp), check its effect and save the modification into the repository:
$> # edit hello.cpp
$> svn status
M hello.cpp
$> svn commit -m "first modification applied to hello.cpp" hello.cpp
copy an already existing file (without using svn cp), check its effect and save the modification into the repository:
$> cp hello.cpp hello_world.cpp
$> svn status
? hello_world.cpp
$> svn add hello_world.cpp
$> svn commit -m "adding hello_world.cpp" hello_world.cpp
The ? means the file isn’t (yet) tracked or known to the repository but does exist in your local directory.
delete the file previously added (but without using svn rm), check its effect and save the modification in the repository:
$> rm hello_world.cpp
$> svn status
! hello_world.cpp
$> svn rm hello_world.cpp
$> svn commit -m "deleting hello_world.cpp" hello_world.cpp
The ! means the file exists in the repository but not in your local area.
copy an already existing file (using svn cp), compare its effect with previous commands and save the modification in the repository:
$> svn cp hello.cpp hello_world.cpp
$> svn status
A + hello_world.cpp
$> svn commit -m "adding hello_world.cpp with svn-cp" hello_world.cpp
delete the file (using svn rm), compare its effect with previous commands and save the modification in the repository:
$> svn rm hello_world.cpp
$> svn status
D hello_world.cpp
$> svn commit -m "deleting hello_world.cpp with svn-rm" hello_world.cpp
now, it is up to you to suppress the directory Hello/Darwin...
$> svn rm <????>
During the following steps, we’ll experiment with 2 usages of the versions’ history which is stored in the repository: visualizing the differences between versions and rolling back to an older version. To use the history, one usually begins with dumping the list of revisions available for inspection together with their (hopefully descriptive and informative) commit message.
display the modifications (default mode):
$> svn log
dump the modifications (detailed/verbose output):
$> svn log -v
display the modifications for a particular file:
$> svn log hello.cpp
compare the differences.
We’ll investigate 2 use-cases for displaying differences:
dump the differences between the local workarea and the last revision in the repository:
$> svn diff hello.cpp
display the differences between the local workarea and an arbitrary revision in the repository. Compare with the previous result:
# select a revision 'n' in the history...
$> svn diff -r n hello.cpp
display the differences between 2 revisions m and n in the repository (the last revision is always named HEAD). The file hello.cpp should exist in both revisions (check the effect if this wasn’t the case):
$> svn diff -r m:n hello.cpp
A rather interesting usage for keeping an history of revisions is the ability to roll back to an earlier version of a file or a set of files.
revert the modifications previously applied to your workarea and roll back to the last revision in the repository:
$> svn status
# ... check that hello.cpp has indeed been modified
$> svn revert hello.cpp
roll back to a particular revision n in the repository in order to start again from a ‘right version’ - you first revert the modifications applied to your workarea - HEAD means the latest revision in the repository:
$> svn revert hello.cpp
$> svn merge -r HEAD:n hello.cpp
$> svn status
roll back to revision n of the repository, keeping the local modifications:
# ... edit and modify
$> svn merge -r HEAD:n hello.cpp
$> svn status
# check for conflicts and, if any, resolve them
$> svn commit -m "revert to revision n for hello.cpp" hello.cpp
Some times one want to get back a deleted file the way the file is added back to the repository together with it’s history. Hence future ‘svn log‘ on this file will traverse back through the file’s resurrection and through all the prior history.
add a file, edit it and check in several times
$> echo "Test 1" > foo.txt
$> svn add foo.txt
$> svn commit -m "Added foo.txt" foo.txt
$> echo "Test 2" >> foo.txt
$> svn commit -m "First modification of foo.txt" foo.txt
$> echo "Test 3" >> foo.txt
$> svn commit -m "Another modification of foo.txt" foo.txt
$> svn update
$> svn log
then delete it
$> svn delete foo.txt
$> svn commit -m "Deleted foo.txt" foo.txt
edit hello.cpp and check in several times too
$> echo "// Test 4" >> hello.cpp
$> svn commit -m "Added some comments" hello.cpp
$> echo "// Test 5" >> hello.cpp
$> svn commit -m "Added some comments" hello.cpp
now look for the revision N in which was deleted the file to be resurrected
$> svn update
$> svn log --verbose
add the file to the repository
$> export REPO=https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>
$> svn copy $REPO/Hello/trunk/src/foo.txt@<N-1> ./foo.txt
$> svn status
$> svn commit -m "Resurrected foo.txt from revision N-1" foo.txt
Note that the same technique works just as well for resurrecting deleted directories.
A branch is a “cheap copy” of a subtree (ie, the trunk or another branch) of a SVN repository. It works a little bit like symbolic links on UNIX systems, except that once you make modifications to files within a SVN branch, these files evolve independently from the original files which were “copied”. When a branch is completed and considered stable, it must be merged back to its original copy.
Now you will create an experimental branch in order to test a new implementation without betting your entire project. Experimental branches may be abandonned when the experiment fails. But if they succeed you can easily merge that branch with the trunk.
In our case our refactoring will be simple: we want to test the instruction 'using namespace std;' in order to get rid of all std:: ...
define a environment variable to ease the repository calls and verify:
$> export REPO=https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>
$> svn ls $REPO
be careful to start from a well synchronized state:
$> cd ~/Project/Hello
$> svn st
# if needed check in or revert
create your branch:
$> svn copy $REPO/Hello/trunk \
$REPO/Hello/branches/TRY-namespace-std \
-m "Branch from trunk to test namespace std"
transforms your current working copy to reflect your experimental branch:
$> svn switch $REPO/Hello/branches/TRY-namespace-std
$> svn info
edit and check in as often as needed:
$> svn ci -m "Use of 'using namespace std;'" .
$> svn info
switch back to the trunk:
$> svn switch $REPO/Hello/trunk
$> svn info
finally merge your experimental branch to the trunk:
$> svn merge $REPO/Hello/trunk \
$REPO/Hello/branches/TRY-namespace-std
$> svn ci -m "Merge TRY-namespace-std branch with trunk" .
you may delete your experimental branch, you don’t need it anymore. Of course, your branch isn’t really gone, it’s simply missing from the HEAD revision. If you use svn checkout, svn switch or svn list with earlier revision number, you will still see your branch.
$> svn delete $REPO/Hello/branches/TRY-namespace-std \
-m "Removed branch TRY-namespace-std"
# Get the log with additional information from merge history and spot the branch revisions
$> svn up && svn log --use-merge-history .
$> svn ls $REPO/Hello/branches/ -r<nn>
A tag is just a ‘snapshot‘ of a project in time, named in a human-friendly way.
if not done define a environment variable to ease the repository calls and verify:
$> export REPO=https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>
$> svn ls $REPO
be careful to start from a well synchronized state:
$> cd ~/Project/Hello
$> svn st
# if needed check in or revert
create your tag:
$> svn copy $REPO/Hello/trunk \
$REPO/Hello/tags/SVN-exercise
-m "Tagging the end of the SVN exercise."
verify:
$> svn ls -R $REPO/Hello
Normally and by convention one never works in a tag branch.
Do not forget to check, at the last session, that all your work is indeed correctly committed and saved in your svn repository.
i.e.: