I am surprised no has mentioned that this is discussed in Version Control with Subversion, which is available free online, here.
I read up on the issue awhile back and it really seems like a matter of personal choice, there is a good blog post on the subject here. EDIT: Since the blog appears to be down, (archived version here), here is some of what Mark Phippard had to say on the subject.
These are some of the advantages of the single repository approach.
- Simplified administration. One set of hooks to deploy. One repository to backup. etc.
- Branch/tag flexibility. With the code all in one repository it makes it easier to create a branch or tag involving multiple projects.
- Move code easily. Perhaps you want to take a section of code from one project and use it in another, or turn it into a library for several projects. It is easy to move the code within the same repository and retain the history of the code in the process.
Here are some of the drawbacks to the single repository approach, advantages to the multiple repository approach.
- Size. It might be easier to deal with many smaller repositories than one large one. For example, if you retire a project you can just archive the repository to media and remove it from the disk and free up the storage. Maybe you need to dump/load a repository for some reason, such as to take advantage of a new Subversion feature. This is easier to do and with less impact if it is a smaller repository. Even if you eventually want to do it to all of your repositories, it will have less impact to do them one at a time, assuming there is not a pressing need to do them all at once.
- Global revision number. Even though this should not be an issue, some people perceive it to be one and do not like to see the revision number advance on the repository and for inactive projects to have large gaps in their revision history.
- Access control. While Subversion's authz mechanism allows you to restrict access as needed to parts of the repository, it is still easier to do this at the repository level. If you have a project that only a select few individuals should access, this is easier to do with a single repository for that project.
- Administrative flexibility. If you have multiple repositories, then it is easier to implement different hook scripts based on the needs of the repository/projects. If you want uniform hook scripts, then a single repository might be better, but if each project wants its own commit email style then it is easier to have those projects in separate repositories
When you really think about, the revision numbers in a multiple project repository are going to get high, but you are not going to run out. Keep in mind that you can view a history on a sub directory and quickly see all the revision numbers that pertain to a project.
(This answer has been updated to match SVN 1.8 and 1.9's behaviour)
You have 2 questions:
Marking files as ignored:
By "ignored file" I mean the file won't appear in lists even as "unversioned": your SVN client will pretend the file doesn't exist at all in the filesystem.
Ignored files are specified by a "file pattern". The syntax and format of file patterns is explained in SVN's online documentation: http://svnbook.red-bean.com/nightly/en/svn.advanced.props.special.ignore.html "File Patterns in Subversion".
Subversion, as of version 1.8 (June 2013) and later, supports 3 different ways of specifying file patterns. Here's a summary with examples:
1 - Runtime Configuration Area - global-ignores
option:
- This is a client-side only setting, so your
global-ignores
list won't be shared by other users, and it applies to all repos you checkout onto your computer.
- This setting is defined in your Runtime Configuration Area file:
- Windows (file-based) -
C:\Users\{you}\AppData\Roaming\Subversion\config
- Windows (registry-based) -
Software\Tigris.org\Subversion\Config\Miscellany\global-ignores
in both HKLM
and HKCU
.
- Linux/Unix -
~/.subversion/config
2 - The svn:ignore
property, which is set on directories (not files):
- This is stored within the repo, so other users will have the same ignore files. Similar to how
.gitignore
works.
svn:ignore
is applied to directories and is non-recursive or inherited. Any file or immediate subdirectory of the parent directory that matches the File Pattern will be excluded.
While SVN 1.8 adds the concept of "inherited properties", the svn:ignore
property itself is ignored in non-immediate descendant directories:
cd ~/myRepoRoot # Open an existing repo.
echo "foo" > "ignoreThis.txt" # Create a file called "ignoreThis.txt".
svn status # Check to see if the file is ignored or not.
> ? ./ignoreThis.txt
> 1 unversioned file # ...it is NOT currently ignored.
svn propset svn:ignore "ignoreThis.txt" . # Apply the svn:ignore property to the "myRepoRoot" directory.
svn status
> 0 unversioned files # ...but now the file is ignored!
cd subdirectory # now open a subdirectory.
echo "foo" > "ignoreThis.txt" # create another file named "ignoreThis.txt".
svn status
> ? ./subdirectory/ignoreThis.txt # ...and is is NOT ignored!
> 1 unversioned file
(So the file ./subdirectory/ignoreThis
is not ignored, even though "ignoreThis.txt
" is applied on the .
repo root).
Therefore, to apply an ignore list recursively you must use svn propset svn:ignore <filePattern> . --recursive
.
- This will create a copy of the property on every subdirectory.
- If the
<filePattern>
value is different in a child directory then the child's value completely overrides the parents, so there is no "additive" effect.
- So if you change the
<filePattern>
on the root .
, then you must change it with --recursive
to overwrite it on the child and descendant directories.
I note that the command-line syntax is counter-intuitive.
- I started-off assuming that you would ignore a file in SVN by typing something like
svn ignore pathToFileToIgnore.txt
however this is not how SVN's ignore feature works.
3- The svn:global-ignores
property. Requires SVN 1.8 (June 2013):
- This is similar to
svn:ignore
, except it makes use of SVN 1.8's "inherited properties" feature.
- Compare to
svn:ignore
, the file pattern is automatically applied in every descendant directory (not just immediate children).
- This means that is unnecessary to set
svn:global-ignores
with the --recursive
flag, as inherited ignore file patterns are automatically applied as they're inherited.
Running the same set of commands as in the previous example, but using svn:global-ignores
instead:
cd ~/myRepoRoot # Open an existing repo
echo "foo" > "ignoreThis.txt" # Create a file called "ignoreThis.txt"
svn status # Check to see if the file is ignored or not
> ? ./ignoreThis.txt
> 1 unversioned file # ...it is NOT currently ignored
svn propset svn:global-ignores "ignoreThis.txt" .
svn status
> 0 unversioned files # ...but now the file is ignored!
cd subdirectory # now open a subdirectory
echo "foo" > "ignoreThis.txt" # create another file named "ignoreThis.txt"
svn status
> 0 unversioned files # the file is ignored here too!
For TortoiseSVN users:
This whole arrangement was confusing for me, because TortoiseSVN's terminology (as used in their Windows Explorer menu system) was initially misleading to me - I was unsure what the significance of the Ignore menu's "Add recursively", "Add *" and "Add " options. I hope this post explains how the Ignore feature ties-in to the SVN Properties feature. That said, I suggest using the command-line to set ignored files so you get a feel for how it works instead of using the GUI, and only using the GUI to manipulate properties after you're comfortable with the command-line.
Listing files that are ignored:
The command svn status
will hide ignored files (that is, files that match an RGA global-ignores
pattern, or match an immediate parent directory's svn:ignore
pattern or match any ancesor directory's svn:global-ignores
pattern.
Use the --no-ignore
option to see those files listed. Ignored files have a status of I
, then pipe the output to grep
to only show lines starting with "I".
The command is:
svn status --no-ignore | grep "^I"
For example:
svn status
> ? foo # An unversioned file
> M modifiedFile.txt # A versioned file that has been modified
svn status --no-ignore
> ? foo # An unversioned file
> I ignoreThis.txt # A file matching an svn:ignore pattern
> M modifiedFile.txt # A versioned file that has been modified
svn status --no-ignore | grep "^I"
> I ignoreThis.txt # A file matching an svn:ignore pattern
ta-da!
Best Solution
There is a program called SubWCRev.exe that comes with TortoiseSVN that will do token replacement for you. So somewhere in your source, you insert the token, and pass the input and output filenames to SubWCRev.exe, and it will replace the token with various SVN info, e.g., revision number. Note, this is a standalone program you can use with your build script, you do not need to use TortoiseSVN with it.