Subversion

Subversion is an open source version control system

https://subversion.apache.org/

Update

svn update

Commit

svn commit -m 'message'
svn protected/* themes/* commit -m 'message'

Add unversioned files

/usr/bin/svnaddunversioned.sh:

   1 #!/bin/sh
   2 svn status | grep ? | awk '//{print $2}' | xargs -i svn add {}
   3 
   4 # revert add 
   5 svn revert addedFile

Branches

http://svnbook.red-bean.com/en/1.7/svn.branchmerge.using.html

svn copy http://svn.example.com/repos/calc/trunk http://svn.example.com/repos/calc/branches/my-calc-branch -m "Creating a private branch of /calc/trunk."
svn checkout http://svn.example.com/repos/calc/branches/my-calc-branch my-calc-branch 

Ignore one folder

http://stackoverflow.com/questions/11293539/equivalent-of-gitignore-file-with-subversion

C# example:

Ignore several files folders

http://sdesmedt.wordpress.com/2006/12/10/how-to-make-subversion-ignore-files-and-folders/

svnignore.txt

obj
bin

Issue the command to ignore the folders listed inside the file

Add to ~/.bashrc

# export SVN_EDITOR=vi
export SVN_EDITOR=nano

Merge

Diff between branches

Commit with message(s) in file

Files added or modified

Cherrypicking

Solve conflict

Revert working copy

Mark script as executable

Search logs by username

Get folder without content

svnserve

The svnserve program is a lightweight server, capable of speaking to clients over TCP/IP using a custom, stateful protocol. Listens port 3690 http://svnbook.red-bean.com/en/1.7/svn.serverconfig.svnserve.html

/tmp/svnserver/test/conf/passwd

[users]
harry = 1234
sally = 1234

/tmp/svnserver/test/conf/svnserve.conf

[general]
password-db = passwd
[sasl]
use-sasl = false

   1 touch a
   2 svn add a
   3 svn commit a --username harry --password 1234
   4 svn log
   5 svn up .
   6 svn log
   7 svn ls
   8 mkdir branch tag trunk
   9 svn rm a
  10 svn status
  11 svn add branch/ tag/ trunk/
  12 svn status
  13 svn commit -m "Created branch tag trunk" --username harry --password 1234

   1 #!/bin/sh
   2 mkdir -p /tmp/svnserver/testrepo
   3 svnserve -d -r /tmp/svnserver
   4 svnadmin create --fs-type fsfs /tmp/svnserver/testrepo
   5 cd /tmp/svnserver/testrepo
   6 echo -e "[users]\nharry = 1234\nsally = 1234\n" > conf/passwd
   7 echo -e "[general]\npassword-db = passwd\n[sasl]\nuse-sasl = false\n" > conf/svnserve.conf
   8 BASE_SVN_REPO=svn://localhost/testrepo
   9 CREDENTIALS="--username harry --password 1234"
  10 cd /tmp
  11 svn checkout $BASE_SVN_REPO
  12 cd testrepo 
  13 mkdir branches tag trunk
  14 svn add branches/ tag/ trunk/
  15 svn status
  16 svn commit -m "Created branches tag trunk" $CREDENTIALS
  17 # Committed revision 1.
  18 svn up .
  19 BASE=/tmp/testrepo
  20 cd $BASE/trunk
  21 echo -e "trunk 1" > dummy.txt
  22 svn add dummy.txt
  23 svn commit -m "Created dummy1.txt in trunk" $CREDENTIALS
  24 #Committed revision 2
  25 svn up .
  26 svn copy $BASE_SVN_REPO/trunk $BASE_SVN_REPO/branches/feature_branch1 $CREDENTIALS  -m "created feature branch1"
  27 # Committed revision 3.
  28 cd $BASE
  29 svn up .
  30 cd $BASE/branches/feature_branch1
  31 echo -e "fb1 1" >> dummy.txt
  32 svn commit -m "Changed dummy1.txt in feature_branch1" $CREDENTIALS
  33 #Committed revision 4
  34 svn up .
  35 cd $BASE/trunk
  36 echo -e "\ntrunk 2\n" >> dummy.txt 
  37 svn commit -m "Changed trunk" $CREDENTIALS
  38 svn up .
  39 # Committed revision 5
  40 # Synch from trunk to feature_branch1
  41 cd $BASE/branches/feature_branch1/
  42 svn up .
  43 svn merge $BASE_SVN_REPO/trunk $CREDENTIALS --accept postpone 
  44 # Conflict discovered in file 'dummy.txt'. postpone
  45 vi dummy.txt
  46 svn resolve --accept working dummy.txt
  47 svn status
  48 svn commit -m "synch merge from trunk to feature_branch1" $CREDENTIALS
  49 svn up .
  50 # Committed revision 6.
  51 # create feature branch2 from feature branch1
  52 svn copy $BASE_SVN_REPO/branches/feature_branch1 $BASE_SVN_REPO/branches/feature_branch2 $CREDENTIALS -m "created feature branch2 from feature branch1"
  53 # Committed revision 7.
  54 svn up .
  55 cd $BASE
  56 svn up .
  57 cd $BASE/branches/feature_branch2/
  58 echo -e "\nfb2 1\n" >> dummy.txt
  59 svn commit -m "changed feature branch2" $CREDENTIALS
  60 svn up . 
  61 # Committed revision 8.
  62 cd $BASE/branches/feature_branch1
  63 echo -e "\nfb1 2\n" >> dummy.txt 
  64 svn commit -m "changed feature branch1" $CREDENTIALS
  65 svn up .
  66 # Committed revision 9
  67 # synch feat_branch2 from feat_branch1
  68 cd $BASE/branches/feature_branch2/
  69 svn up .
  70 svn merge $BASE_SVN_REPO/branches/feature_branch1 $CREDENTIALS --accept postpone 
  71 # Conflict discovered in file 'dummy.txt'. postpone
  72 vi dummy.txt
  73 svn resolve --accept working dummy.txt
  74 svn status
  75 svn commit -m "synch merge from feature_branch1 to feature_branch2" $CREDENTIALS
  76 svn up .
  77 # Committed revision 10.
  78 cd $BASE/trunk
  79 echo -e "\ntrunk 3\n" >> dummy.txt 
  80 svn commit -m "Changed trunk" $CREDENTIALS
  81 svn up .
  82 # Committed revision 11.
  83 # synch fb1 with trunk
  84 cd $BASE/branches/feature_branch1
  85 svn merge $BASE_SVN_REPO/trunk $CREDENTIALS --accept postpone 
  86 vi dummy.txt # solve conflicts
  87 svn resolve --accept working dummy.txt
  88 svn commit -m "synch merge from parent trunk to feature branch1" $CREDENTIALS
  89 # Committed revision 12.
  90 svn up .
  91 cd $BASE/trunk/
  92 svn up .
  93 svn merge $BASE_SVN_REPO/branches/feature_branch1 $CREDENTIALS --accept postpone 
  94 svn status
  95 svn commit -m "got changes into trunk from feature branch1 (reintegrate)" $CREDENTIALS
  96 # Committed revision 13.
  97 # terminate feature branch 1
  98 svn rm $BASE_SVN_REPO/branches/feature_branch1 $CREDENTIALS -m "removed feature branch1"
  99 # Committed revision 14.
 100 cd $BASE
 101 svn up .
 102 # add new entry to trunk
 103 cd $BASE/trunk
 104 echo -e "\ntrunk 4\n" >> dummy.txt 
 105 svn commit -m "changed trunk" $CREDENTIALS
 106 #Committed revision 15
 107 svn up . 
 108 
 109 svn diff $BASE_SVN_REPO/trunk@13 $BASE_SVN_REPO/trunk@15  $CREDENTIALS 
 110 # added trunk 4
 111 svn diff $BASE_SVN_REPO/trunk@3 $BASE_SVN_REPO/trunk@13  $CREDENTIALS 
 112 # added fb1 1 , trunk 2 , fb1 2 , trunk 3
 113 # the synch from trunk to feature branch 2 should have ....
 114 # trunk1, trunk2, trunk3, trunk4, fb2 1, fb1 1, fb1 2, 7 elements
 115 # merge from integrate revision to head of trunk
 116 cd $BASE/branches/feat_branch2
 117 svn merge $BASE_SVN_REPO/trunk@13 $BASE_SVN_REPO/trunk@HEAD $CREDENTIALS --accept postpone 
 118 # has all the elements
 119 
 120 svn merge $BASE_SVN_REPO/trunk@15 $BASE_SVN_REPO/trunk@15 $CREDENTIALS --accept postpone
 121 # only has 5 elements
 122 
 123 # from fb1 creation to reintegration 13
 124 svn merge $BASE_SVN_REPO/trunk@3 $BASE_SVN_REPO/trunk@13 $CREDENTIALS --accept postpone 
 125 # has six elements, trunk 4 was added in r15
 126 

Show svn diff side by side

   1 svn --diff-cmd "diff" --extensions "-y" diff
   2 svn --diff-cmd "diff" --extensions "-y -W250" diff | colordiff | less -rS
   3 svn --diff-cmd "diff" --extensions "-y -W250 --suppress-common-lines" diff | colordiff | less -rS

Revert commited file to previous revision

#1234 previous revision
svn merge -c -1234 test.py
svn commit
svn up .

http://svnbook.red-bean.com/en/1.8/svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.undo

   1 #  All you need to do is to specify a reverse difference. (You can do this by specifying --revision 392:391, or by an equivalent --change -392.)
   2 #svn merge ^/calc/trunk . -c-392
   3 svn merge ^/calc/trunk . --revision 392:391
   4 svn st
   5 svn diff
   6 svn commit -m "Undoing erroneous change committed in r392."
   7 ####
   8 cd branch
   9 svn revert . -R # undo local changes
  10 svn up . 
  11 svn log | less # see version
  12 svn merge . --revision HEAD:<prev_revision>
  13 svn commit -m "Reverted to revision xyz"

Merge with revision range

   1 cd ~/tmp
   2 svn co https://feature_branch
   3 cd feature_branch
   4 svn merge https://parent_branch -r start:end . --accept=postpone
   5 # the range of revisions is ]start,end] so only start+1 is applied until end.
   6 # sync merge
   7 

svn help merge | less

Merge types:

The 'Feature Branch' Merging Pattern

A developer creates a branch and commits a series of changes that implement a new feature. The developer periodically merges all the latest changes from the parent branch so as to keep the development branch up to date with those changes. When the feature is complete, the developer performs a merge from the feature branch to the parent branch to re-integrate the changes.

         parent --+----------o------o-o-------------o--
                   \            \           \      /
                    \          merge      merge  merge
                     \            \           \  /
         feature      +--o-o-------o----o-o----o-------

A merge from the parent branch to the feature branch is called a 'sync' or 'catch-up' merge, and a merge from the feature branch to the parent branch is called a 'reintegrate' merge.

Sync Merge Example

                                 ............
                                .            .
         trunk  --+------------L--------------R------
                   \                           \
                    \                          |
                     \                         v
         feature      +------------------------o-----
                             r100            r200

Reintegrate Merge Example

                    rW                   rX
         trunk ------+--------------------L------------------o
                      \                    .                 ^
                       \                    .............   /
                        \                                . /
         feature         +--------------------------------R

Cherry-pick Merge Example

            1.x-release  +-----------------------o-----
                        /                        ^
                       /                         |
                      /                          |
         trunk ------+--------------------------LR-----
                                                r50

2-URL merge example

Two source URLs are specified, identifying two trees on the same branch or on different branches. The trees are compared and the difference from SOURCE1@REV1 to SOURCE2@REV2 is applied to the working copy of the target branch at TARGET_WCPATH.

Two features have been developed on separate branches called 'foo' and 'bar'. It has since become clear that 'bar' should be combined with the 'foo' branch for further development before reintegration. Although both feature branches originate from trunk, they are not directly related -- one is not a direct copy of the other. A 2-URL merge is necessary.

The 'bar' branch has been synced with trunk up to revision 500. (If this revision number is not known, it can be located using the 'svn log' and/or 'svn mergeinfo' commands.) The difference between trunk@500 and bar@HEAD contains the complete set of changes related to feature 'bar', and no other changes. These changes are applied to the 'foo' branch.

                           foo  +-----------------------------------o
                               /                                    ^
                              /                                    /
                             /              r500                  /
         trunk ------+------+-----------------L--------->        /
                      \                        .                /
                       \                        ............   /
                        \                                   . /
                    bar  +-----------------------------------R

In the diagram above, L marks the left side (trunk@500) and R marks the right side (bar@HEAD) of the merge. The difference between the left and right side is applied to the target working copy path, in this case a working copy of the 'foo' branch.

The exact changes applied by a 2-URL merge can be previewed with svn's diff command, which is a good idea to verify if you do not have the luxury of a clean working copy to merge to.

testrepo2 , sync merge and 2 URL merge

   1 #!/bin/sh
   2 # as root
   3 rm -rf /tmp/svnserver/testrepo2
   4 mkdir -p /tmp/svnserver/testrepo2
   5 svnserve -d -r /tmp/svnserver
   6 svnadmin create --fs-type fsfs /tmp/svnserver/testrepo2 
   7 cd /tmp/svnserver/testrepo2
   8 echo -e "[users]\nharry = 1234\nsally = 1234\n" > conf/passwd
   9 echo -e "[general]\npassword-db = passwd\n[sasl]\nuse-sasl = false\n" > conf/svnserve.conf
  10 exit
  11 # as normal user 
  12 BASE_SVN_REPO=svn://localhost/testrepo2
  13 CREDENTIALS="--username harry --password 1234"
  14 cd /tmp
  15 rm -rf testrepo2 
  16 svn checkout $BASE_SVN_REPO
  17 cd testrepo2 
  18 mkdir branches tags trunk
  19 svn add branches/ tags/ trunk/
  20 svn status
  21 svn commit -m "Created branches tags trunk" $CREDENTIALS 
  22 # Committed revision 1.
  23 # if error appears with txn-current-lock': Permission denied, run the svnserve as root ...
  24 svn up .
  25 
  26 BASE=/tmp/testrepo2
  27 cd $BASE/trunk
  28 echo -e "t1" > dummy.txt
  29 svn add dummy.txt
  30 svn commit -m "Created dummy1.txt in trunk" $CREDENTIALS
  31 #Committed revision 2
  32 svn up .
  33 
  34 echo -e "t2\n" >> dummy.txt
  35 svn commit -m "Added t2 to dummy1.txt in trunk" $CREDENTIALS 
  36 # Committed revision 3.
  37 svn up .
  38 
  39 #create feature branch fb1
  40 svn copy $BASE_SVN_REPO/trunk $BASE_SVN_REPO/branches/fb1 $CREDENTIALS  -m "Created fb1"
  41 # Committed revision 4.
  42 
  43 cd $BASE/trunk
  44 echo -e "t3\n" >> dummy.txt
  45 svn commit -m "Added t3 to dummy1.txt in trunk" $CREDENTIALS 
  46 # Committed revision 5.
  47 svn up .
  48 
  49 cd $BASE
  50 svn up .
  51 cd $BASE/branches/fb1
  52 echo -e "fb1_1" >> dummy.txt
  53 svn commit -m "Added fb1_1 to dummy1.txt in fb1" $CREDENTIALS
  54 #Committed revision 6
  55 svn up .
  56 
  57 cd $BASE/trunk
  58 echo -e "t4\n" >> dummy.txt 
  59 svn commit -m "Added t4 to dummy.txt in trunk" $CREDENTIALS
  60 # Committed revision 7
  61 svn up .
  62 
  63 # create feature branch fb2
  64 svn copy $BASE_SVN_REPO/trunk $BASE_SVN_REPO/branches/fb2 $CREDENTIALS  -m "Created branch fb2"
  65 # Committed revision 8
  66 svn up . 
  67 
  68 cd $BASE/branches/fb1
  69 echo -e "fb1_2\n" >> dummy.txt 
  70 svn commit -m "Added fb1_2 to dummy.txt in fb1" $CREDENTIALS
  71 # Committed revision 9
  72 svn up .
  73 
  74 cd $BASE/trunk
  75 echo -e "t5\n" >> dummy.txt 
  76 svn commit -m "Added t5 to dummy.txt in trunk" $CREDENTIALS
  77 # Committed revision 10
  78 svn up .
  79 
  80 cd $BASE
  81 svn up . 
  82 
  83 cd $BASE/branches/fb2
  84 echo -e "fb2_1\n" >> dummy.txt 
  85 svn commit -m "Added fb2_1 to dummy.txt in fb2" $CREDENTIALS
  86 # Committed revision 11
  87 svn up .
  88 
  89 cd $BASE/trunk
  90 echo -e "t6\n" >> dummy.txt 
  91 svn commit -m "Added t6 to dummy.txt in trunk" $CREDENTIALS
  92 # Committed revision 12
  93 svn up .
  94 
  95 cd $BASE/branches/fb2
  96 echo -e "fb2_2\n" >> dummy.txt 
  97 svn commit -m "Added fb2_2 to dummy.txt in fb2" $CREDENTIALS
  98 # Committed revision 13
  99 svn up .
 100 
 101 cd $BASE/trunk
 102 echo -e "t7\n" >> dummy.txt 
 103 svn commit -m "Added t7 to dummy.txt in trunk" $CREDENTIALS
 104 # Committed revision 14
 105 svn up .
 106 
 107 # Sync merge from trunk to fb1
 108 cd $BASE/branches/fb1/
 109 svn up .
 110 # will get t3 to t6 revisions ]3:12] -> 5,7,10,12
 111 svn merge $BASE_SVN_REPO/trunk -r3:12 $CREDENTIALS --accept postpone 
 112 # Conflict discovered in file 'dummy.txt'. postpone
 113 vi dummy.txt
 114 svn resolve --accept working dummy.txt
 115 svn status
 116 svn commit -m "sync merge from trunk to fb1" $CREDENTIALS
 117 # Committed revision 15.
 118 svn up .
 119 
 120 # Sync merge from trunk to fb2
 121 cd $BASE/branches/fb2/
 122 svn up .
 123 # will get t5 to t7 revisions ]7:14] -> revisions 10,12,14
 124 svn merge $BASE_SVN_REPO/trunk -r7:14 $CREDENTIALS --accept postpone 
 125 # Conflict discovered in file 'dummy.txt'. postpone
 126 vi dummy.txt
 127 svn resolve --accept working dummy.txt
 128 svn status
 129 svn commit -m "sync merge from trunk to fb2" $CREDENTIALS
 130 # Committed revision 16.
 131 svn up .
 132 
 133 # test 2-URL merge, put changes made into feature branch fb1 into feature branch fb2 
 134 # the feature branches must be synchronized with the parent branch before doing this
 135 cd $BASE
 136 svn up .
 137 cd $BASE/branches/fb2/
 138 svn up . 
 139 svn diff $BASE_SVN_REPO/trunk@12 $BASE_SVN_REPO/branches/fb1@HEAD
 140 # shows added fb1_1 and fb1_2 in branch fb1 when compared to trunk in the revisin used to sync
 141 svn merge $BASE_SVN_REPO/trunk@12 $BASE_SVN_REPO/branches/fb1@HEAD  --accept postpone 
 142 svn commit -m "2-URL merge with diff between trunk and fb1 to fb2" $CREDENTIALS
 143 # Committed revision 17.
 144 svn up . 
 145 
 146 svn diff $BASE_SVN_REPO/trunk $BASE_SVN_REPO/branches/fb1@HEAD
 147 # fb1 has entries for fb1 and is missing t7
 148 svn diff $BASE_SVN_REPO/trunk $BASE_SVN_REPO/branches/fb2@HEAD
 149 # fb2 branch has added entries for fb1 and fb2 when compared to trunk
 150 
 151 # integrate feature branch fb2 in trunk 
 152 cd $BASE/trunk/
 153 svn up .
 154 svn merge $BASE_SVN_REPO/branches/fb2 $CREDENTIALS --accept postpone 
 155 cat dummy.txt
 156 svn status
 157 svn commit -m "Got changes into trunk from feature branch fb2 (reintegrate)" $CREDENTIALS
 158 # Committed revision 18.
 159 svn up . 

Before the 2-Url merge feature branches must be synchronized with their parent branch. Mergeinfo might not allow the application of revisions 10 and 12 to fb2 if done after the 2-URL merge.

testrepo2RevisionGraph.png

External item (link)

cd /home/user/container_folder
echo -e "folder https://example.org/folder\n" > ~/svn_externals.txt
svn propset svn:externals -F ~/svn_externals.txt .
svn up .
svn proplist
svn propget svn:externals

Update to revision

svn up -r <revisionId>

Go to previous revision

   1 svn merge -r HEAD:<revision> .

Subversion (last edited 2020-07-15 13:36:56 by localhost)