(→How do I create a new repository for use by my user only?: Talked more about spaces in a path) |
m (→How do I create a new repository for use by my user only?: Wrong path) |
||
| Line 224: | Line 224: | ||
Internally, however, it URL-encodes characters such as space; so space is represented as '%20'. | Internally, however, it URL-encodes characters such as space; so space is represented as '%20'. | ||
<pre> | <pre> | ||
| - | ~/Projects/Some project > svn info | + | ~/Projects/Some project/dev > svn info |
Path: . | Path: . | ||
URL: file:///home/tyler/Projects/Some%20project/svn_repository | URL: file:///home/tyler/Projects/Some%20project/svn_repository | ||
Repository Root: file:///home/tyler/Projects/Some%20project/svn_repository | Repository Root: file:///home/tyler/Projects/Some%20project/svn_repository | ||
| - | |||
</pre> | </pre> | ||
Subversion edit (Category edit)
Subpages:
svn:ignore - A newline separated list of file patterns to ignore.
> svn propedit svn:ignore . # Or, if you're sure you're not wiping out an existing svn:ignore attribute, just do > svn propset svn:ignore "tmp" . # How do you set it to ignore multiple things using a single propset command? I don't think you can. These don't work: > svn propset svn:ignore "tmp log config"` . > svn propset svn:ignore "tmp\nlog\nconfig" . > svn propset svn:ignore `echo -e "tmp\nlog\nconfig"` . # But you can do this: > echo -e "tmp\nlog\nconfig" > t; svn propset svn:ignore -F t .; rm t > echo -e "tmp\nlog\nconfig" > t; svn propset svn:ignore --file t .; rm t
From Agile Web Development with Rails (2nd ed).2.pdf:
> svn propset svn:externals "rails http://dev.rubyonrails.org/svn/rails/trunk" vendorThis tells Subversion that the directory vendor/rails actually comes from a remote repository. Type
> svn up vendorand you'll see Rails being installed into your application. From now on, every time you run
svn upyou'll update both your application's code and you'll pick up any changes to Rails.
project/vendor/plugins $ svn propset svn:externals "tyler_shared http://svn.tylerrick.com/rails_shared/" .
To clear the svn:externals property:
svn prodel svn:externals vendor
svn exportExample:
> svn export http://code.qualitysmith.com/plugins/plugin_with_test_app_template/test svn: Destination directory exists; please remove the directory or use --force to overwrite svn: 'test' already exists
You might be concerned that if you force it, it will cause you to lose all of the existing contents of your test/ directory. Never fear, you won't lose anything as long as long as you don't have any files named the same as they are in the directory you are exporting. If all the filenames are different then it will simply result in a merge of {the contents of your directory before the export} and {the contents of {the contents of the repository directory that you are exporting}.
Even if you do overwrite some files, that shouldn't be a problem if they are under version control and you don't have any local modifications that you're afraid of losing — just do an svn diff or svn status afterwards to find out what was overwritten. (If your directory is not already under version control or you do have local modifications, then you may want to be a bit more cautious...)
> ll test total 16 -rw-rw-r-- 1 tyler tyler 1016 May 14 16:03 label_test.rb -rw-rw-r-- 1 tyler tyler 461 May 4 12:17 link_test.rb -rw-rw-r-- 1 tyler tyler 492 May 4 12:17 popup_test.rb -rw-rw-r-- 1 tyler tyler 217 May 14 16:01 test_helper.rb > svn export http://code.qualitysmith.com/plugins/plugin_with_test_app_template/test --force A test A test/test_helper.rb A test/rails_root A test/rails_root/config A test/rails_root/config/database.yml A test/rails_root/vendor A test/rails_root/vendor/plugins A test/rails_root/vendor/plugins/plugin_name A test/rails_root/vendor/plugins/plugin_name/init.rb Exported revision 2945. > ll test total 20 -rw-rw-r-- 1 tyler tyler 1016 May 14 16:03 label_test.rb -rw-rw-r-- 1 tyler tyler 461 May 4 12:17 link_test.rb -rw-rw-r-- 1 tyler tyler 492 May 4 12:17 popup_test.rb drwxrwxr-x 4 tyler tyler 4096 May 14 16:09 rails_root/ # <- new -rw-rw-r-- 1 tyler tyler 314 May 4 13:01 test_helper.rb # <- changed
If you are at all concerned about overwriting files in the destination directory, then you are advised to export to a different directory and then merge the two directories manually...
> svn export http://code.qualitysmith.com/plugins/plugin_with_test_app_template/test test.exported > mv test.exported/one_file test/at_a_time
http://svn-command.rubyforge.org -- an excellent wrapper for the svn command that adds a couple new features and subcommands
http://search.cpan.org/dist/SVN-Notify/lib/SVN/Notify/HTML/ColorDiff.pm
http://home.gna.org/cvsreport/
http://opensource.perlig.de/svnmailer/doc-1.0/
http://svn.collab.net/repos/svn/tags/1.3.2/contrib/client-side/
http://svn.collab.net/repos/svn/tags/1.3.2/tools/client-side/bash_completion
http://svn.collab.net/repos/svn/tags/1.3.2/tools/client-side/
http://svn.collab.net/repos/svn/tags/1.3.2/tools/client-side/svn-graph.pl produce a GraphViz .dot graph for the branch history of a node
http://svnbook.red-bean.com/en/1.0/ch07s03.html
Sometimes it will create directories named my_external.OLD (or similar) where my_external is the name of the external.
I think this happens when I have local modifications in my external working copy and do an update after someone else has committed changes to the target of that external. Rather than trying to merge, Subversion cowardly just renames your directory to make room for a clean export of the external.
Weak!
If you have a working directory that is scheduled for addition but hasn't been added yet, and then you svn propedit svn:externals, and then you svn update, you may find that it doesn't work.
If you try it from within the directory that you addded the svn:external property to, you'll get this:
[tyler: /whatever/doc]> svn st A . [tyler: /whatever/doc]> svn up svn: REPORT request failed on '/!svn/vcc/default' svn: Two top-level reports with no target
If you go up one level, it won't give an error, but neither will it pull in those changes.
[tyler: /whatever/]> svn up doc At revision 26.
Workaround: Do an intermediate commit. Then try updating.
Apparently it's not a bug [1]:
target of an update, then I think we should print an error. It's nonsensical to try to update something that only exists in a working copy.
svn checkout http://host/path/RepositoryName
~/path/to/project > svnadmin create svn_repository
But keep in mind that the repository is stored in a separate directory from your working tree (or "checkout") of that repository. (This is different from git, where there is no central repository and everyone's working tree also contains its own copy of the repository under a subdirectory .git.) So you still need to check out the repository you just created.
I like to organize everything by project and often will have both the repository and my checkout of that repository as subdirectories within the same directory. The repository I call svn_repository and my checkout of that repository I call dev (for "development").
I don't know if there's a way to specify a relative path when you do a checkout (even though relative paths work fine with svnadmin create); this is the error I get when I try to:
~/path/to/project > svn co file://./svn_repository/ dev svn: Unable to open an ra_local session to URL svn: Local URL 'file://svn_repository' contains only a hostname, no path
So you'll have to specify an absolute path (and issue a svn switch [relocate?] that path later changes):
~/path/to/project > svn checkout "file:///home/tyler/path/to/project/svn_repository/" dev Checked out revision 0.
As you can see, you can omit the hostname if you have an absolute path that begins with a '/'.
Also, spaces are allowed but you'll need to enclose them in quotes (or equivalent method) so that your shell passes that as a single argument.
~/Projects/Some project > svn checkout "file:///home/tyler/Projects/Some project/svn_repository/" dev Checked out revision 0.
Internally, however, it URL-encodes characters such as space; so space is represented as '%20'.
~/Projects/Some project/dev > svn info Path: . URL: file:///home/tyler/Projects/Some%20project/svn_repository Repository Root: file:///home/tyler/Projects/Some%20project/svn_repository
If you received a dump file of someone else's repository, you can just as easily import it and then check it out:
~/path/to/project > svnadmin create svn_repository ~/path/to/project > svnadmin load svn_repository < my_project.svn_dump <<< Started new transaction, based on original revision 1 ... ------- Committed revision 1 >>> .. ~/path/to/project > svn checkout "file:///home/tyler/path/to/project/svn_repository/" dev A dev/include ... Checked out revision 56.
Something like this perhaps:
$ sudo svnadmin create /var/www/svn/RepositoryName $ sudo chown -R apache:apache /var/www/svn/RepositoryName
$ sudo htpasswd /etc/httpd/svnpasswd username New password: Re-type new password: Adding password for user username
where username is the name they will use to log in to connect to Subversion.
a/sub_dir up a level to take the place of its parent directory a?Why would you want to do this? Maybe sub_dir is the only subdirectory of a, and you decide it's useless to have that extra level in the hierarchy so you want to promote the subdirectory up one level.
It would be a simple matter if you just wanted to svn mv a/sub_dir ./, but you don't, because then you would have a/ and sub_dir/ as sibling directories, a/ being empty (useless) and sub_dir/ being misnamed/ambiguous (no longer having the scope information from the a/ path segment to clue you in to the scope).
In other words, is there a more concise way to do this?:
svn mv a/sub_dir a_new svn rm a svn ci -m 'Moving a/sub_dir to a/ (step 1 of 2)' a a_new svn mv a_new a svn ci -m 'Moving a/sub_dir to a/ (step 2 of 2)' a a_new
You might try doing this:
svn mv a/sub_dir a
...but then it thinks you want to move sub_dir into a/ -- and that's already where it is!
You will just get this error if you try it:
svn: Cannot move path 'a/sub_dir' into itself
So I guess we're stuck with doing a 5-step process for what should simply be a 2-stop process. Oh well. This doesn't come up all to frequently, I suppose...
You can't, using plain old Subversion. Each directory on your file system can be a working copy for one and only one repository.
However, it appears that a nifty utility called 'layered Subversion' (laysvn) will let you achieve this.
http://laysvn.alioth.debian.org/
Create two directories. One for the real svn checkouts (I called it 'storage', you can place it anywhere, and one directory for your working copy. Inside the working copy directory, create a dir named .laysvn, in there make a new file called laysvn.xml with contents following this schema:
<config title="LaySVN test"> <storage path="/path/to/where/your/storage/dir/is" /> <layer id="base" source="http://subversionserver/repository/layers/base" /> <layer id="dns" source="http://subversionserver/repository/layers/dns" /> <layer id="apache" source="http://subversionserver/repository/layers/apache" /> <layer id="hostname" source="http://subversionserver/repository/layers/hostname" /> </config>Now you can run laysvn in this directory, it will checkout your layers, and then copy the files from the layers into your working dir! To check in your changes, you have to chdir to your storage/layer directory and run 'svn ci' there. This is also where you can resolve conflicts.
svn propedit svn:ignore DirName
Then type in the file names to ignore (wildcards are allowed) and save that file. (One filename per line if you want to ignore multiple patterns.)
You will need to commit this property change if you want it to affect all users of the repository.
No, that property is not inherited by subdirectories. Yes, that is unfortunate.
~/.subversion/config
[miscellany] ### Set global-ignores to a set of whitespace-delimited globs ### which Subversion will ignore in its 'status' output. # global-ignores = *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store
Edit the file /etc/subversion/config:
[miscellany] global-ignores=*.pyc *.swp *.swo *.tmp *.*~ # etc.
Changes take place immediately.
Create a post-commit hook and put some kind of diff-mailer program in the hook script.
Example
/var/www/svn/code/hooks/post-commit
#!/bin/bash
REPOS="$1"
REV="$2"
echo "Just committed '$REPOS' revision '$REV'" >> $REPOS/hooks/post-commit.log
previous_revision=`expr $REV - 1`
skip_commit_notification=`svnlook propget $REPOS --revprop svn:skip_commit_notification_for_next_commit -r $previous_revision`
echo "svnlook propget dir --revprop svn:skip_commit_notification_for_next_commit -r $previous_revision returned '$skip_commit_notification'" >> /var/w
if [[ $skip_commit_notification == 'true' ]]; then
# Skipping
echo "Skipped notification" >> $REPOS/hooks/post-commit.log
else
svnnotify \
--repos-path $REPOS \
--revision $REV \
--subject-prefix "[your repository name]" \
--revision-url 'http://code/?rev=%s' \
--to code-commit-watchers@yourdomain.com \
--handler HTML::ColorDiff \
--subject-cx \
--with-diff \
--author-url 'mailto:%s' \
--footer "Powered by SVN-Notify <http://search.cpan.org/~dwheeler/SVN-Notify-2.62/lib/SVN/Notify.pm>" \
--max-diff-length 1000
echo "Sent notification" >> $REPOS/hooks/post-commit.log
fi
svn revert
"Won't that delete it from my working copy too?" No, it won't. You're safe.
"What about local changes I've made since doing the svn add? Will I lose those changes?" No. It's a little bit confusing since that's what would happen if it was already in the repository and you made changes to it (had an M as the status), but if it has an A, the most damage an svn revert will do is to cause it to not be scheduled for addition any longer...
No problem. svn switch.
switch (sw): Update the working copy to a different URL.
usage: 1. switch URL [PATH]
2. switch --relocate FROM TO [PATH...]
1. Update the working copy to mirror a new URL within the repository.
This behaviour is similar to 'svn update', and is the way to
move a working copy to a branch or tag within the same repository.
2. Rewrite working copy URL metadata to reflect a syntactic change only.
This is used when repository's root URL changes (such as a scheme
or hostname change) but your working copy still reflects the same
directory within the same repository.
svn switch --relocate http://www.olddomain.com/dir http://svn.newdomain.com/dir
Suppose svn info reports that the repository URL is http://svn/svn/wiki/web but it's been renamed (by another user using another working copy, let's say) to http://svn/svn/wiki/trunk . How would you update your working copy to reflect this?
This worked:
svn switch http://svn/svn/wiki/trunk
Simple!
Here's a simple example that I did on a test repository...
Creating the test repository (you can skip this step if you already have a real repository)
~/svn $ sudo svnadmin create /var/www/svn/svntest ~/svn $ svn co http://svn/svn/svntest Checked out revision 0. ~/svn $ sudo svn mkdir -m "Initial directories" http://svn/svn/svntest/trunk http://svn/svn/svntest/cows svn: MKACTIVITY of '/svn/svntest/!svn/act/f0042fb8-ea13-0410-bd81-bbd14e186309': 500 Internal Server Error (http://svn) ~/svn $ sudo svn mkdir -m "Initial directories" file:///var/www/svn/svntest/cows file:///var/www/svn/svntest/trunk Committed revision 1. ~/svn $ svn up svntest/ A svntest/trunk A svntest/cows Updated to revision 1. ~/svn $ cd svntest/
The actual rename
~/svn/svntest $ sudo mv /var/www/svn/svntest /var/www/svn/mysvntest
How to fix your working copy
~/svn/svntest $ svn up svn: PROPFIND request failed on '/svn/svntest' svn: Could not open the requested SVN filesystem ~/svn/svntest $ svn switch http://svn/svn/mysvntest svn: PROPFIND request failed on '/svn/svntest' svn: Could not open the requested SVN filesystem ~/svn/svntest $ svn switch --relocate http://svn/svn/svntest http://svn/svn/mysvntest # <---- ~/svn/svntest $ svn up At revision 1.
Obviously you can't just svn rm it because that removes it from the working copy.
When would you want to do this? Perhaps with a temp directory or config file or something that you accidentally added but now have decided doesn't belong in the repository but you still need to retain the file/directory (perhaps it contains live session data or a live configuration file).
I haven't yet found an easy/atomic way to do this.
But you can do it in a few steps:
Yes
http://svnbook.red-bean.com/en/1.0/re23.html
$ svn propset --revprop -r 25 svn:log "Journaled about trip to New York." property 'svn:log' set on repository revision '25'
Prerequisite:
You need to create a pre-revprop-change hook for the repository. I find that their template file for this works nicely:
# WARNING: unlike other hooks, this hook MUST exist for revision # properties to be changed. If the hook does not exist, Subversion # will behave as if the hook were present, but failed. The reason # for this is that revision properties are UNVERSIONED, meaning that # a successful propchange is destructive; the old value is gone # forever. We recommend the hook back up the old value somewhere. > sudo cp /var/www/svn/.../hooks/pre-revprop-change.tmpl /var/www/svn/.../hooks/pre-revprop-change > sudo chmod a+x /var/www/svn/.../hooks/pre-revprop-change
Or to add the ability to skip notification for certain commits:
REPOS="$1" REV="$2" USER="$3" PROPNAME="$4" ACTION="$5" echo "Attempt to change '$PROPNAME' for '$REPOS' revision '$REV'" >> /var/www/svn/code/hooks/pre-revprop-change.log if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi if [ "$PROPNAME" = "svn:skip_commit_notification_for_next_commit" ]; then exit 0; fi echo "Failed!" >> /var/www/svn/code/hooks/pre-revprop-change.log echo "Changing revision properties other than those listed in $0 is prohibited" >&2 exit 1
Probably
Under your user's home directory, under ~/.subversion/auth/svn.simple/.
Oh yeah, and your password is in plain-text. Don't worry, though.
The auth/ caching area is permission-protected so that only the user (owner) can read data from it, not the world at large. The operating system's own file permissions are protecting the password.
$ cat ~somebody/.subversion/auth/svn.simple/2d01559fa5e48db39f96392824b23572 cat: /home/somebody/.subversion/auth/svn.simple/2d01559fa5e48db39f96392824b23572: Permission denied
The problem is, when user A commits something, it saves A's credentials. Then when B commits something, it will say that A is the author.
You can get around this by telling Subversion to use a different username, when you start your session:
svn command --username MyName
(refer to http://svnbook.red-bean.com/nightly/en/svn.ref.html#svn.ref.svn.sw Switches)
It will prompt you for your password and then cache it... so the next person to use this account needs to remember to do that too!
Can you just disable authenticating caching altogether for that Linux account? Yes.
~/.subversion/config :
### Section for authentication and authorization customizations. [auth] ### Set store-passwords to 'no' to avoid storing passwords in the ### auth/ area of your config directory. It defaults to 'yes'. ### Note that this option only prevents saving of *new* passwords; ### it doesn't invalidate existing passwords. (To do that, remove ### the cache files by hand as described in the Subversion book.) # store-passwords = no ### Set store-auth-creds to 'no' to avoid storing any subversion ### credentials in the auth/ area of your config directory. ### It defaults to 'yes'. Note that this option only prevents ### saving of *new* credentials; it doesn't invalidate existing ### caches. (To do that, remove the cache files by hand.) store-auth-creds = no
svn st --ignore-externals
If it were your own repository, you could set up a post-commit hook and just add yourself to the commit-watchers list. But with external repositories, you usually don't have that option. Wouldn't it be great if you could get an RSS feed of the changes in someone's public repository? Well, you can!
RSSin' Your SVN (http://errtheblog.com/post/701) (2007-01-21).
How do you know when a remote repository is updated? You need to know about changes to sync (read: update). Heaven forbid we miss a killer new feature. You can follow the blogs, or check the Rubyforge, or grab the Trac feed, but sometimes none of these things are available. Sometimes all you really have is the repository.
Subversion FAQ (http://subversion.tigris.org/faq.html).
I'm trying to look at an old version of my file, but svn says something about "path not found". What's going on? A nice feature of Subversion is that the repository understands copies and renames, and preserves the historical connections. For example, if you copy /trunk to /branches/mybranch, then the repository understands that every file in the branch has a "predecessor" in the trunk. Running svn log --verbose will show you the historical copy, so you can see the rename: r7932 | joe | 2003-12-03 17:54:02 -0600 (Wed, 03 Dec 2003) | 1 line Changed paths: A /branches/mybranch (from /trunk:7931) Unfortunately, while the repository is aware of copies and renames, almost all the svn client subcommands are not aware. Commands like svn diff, svn merge, and svn cat ought to understand and follow renames, but don't yet do this. It's scheduled as post-1.0 feature, currently issue #1093. For example, if you ask svn diff to compare two earlier versions of /branches/mybranch/foo.c, the command will not automatically understand that the task actually requires comparing two versions of /trunk/foo.c, due to the rename. Instead, you'll see an error about how the branch-path doesn't exist in the earlier revisions.
It looks like issue 1093 was closed in 2004, so maybe this is no longer an issue?
Example of what is/isn't still an issue:
[tyler: ~/code/gemables]> /usr/bin/svn log -v -r 2279
------------------------------------------------------------------------
r2279 | tyler | 2007-02-08 15:42:57 -0800 (Thu, 08 Feb 2007) | 1 line
Changed paths:
A /gemables/subversion
Starting work on a Subversion gemable
------------------------------------------------------------------------
[tyler: ~/code/gemables]> /usr/bin/svn log -v -r 2345
------------------------------------------------------------------------
r2345 | tyler | 2007-03-02 12:07:48 -0800 (Fri, 02 Mar 2007) | 1 line
Changed paths:
D /gemables/subversion
A /gemables/svn-command (from /gemables/subversion:2342)
R /gemables/svn-command/README (from /gemables/subversion/README:2344)
R /gemables/svn-command/Rakefile (from /gemables/subversion/Rakefile:2344)
R /gemables/svn-command/agiledox.txt (from /gemables/subversion/agiledox.txt:2344)
R /gemables/svn-command/bin (from /gemables/subversion/bin:2344)
R /gemables/svn-command/doc_include (from /gemables/subversion/doc_include:2344)
R /gemables/svn-command/lib (from /gemables/subversion/lib:2344)
R /gemables/svn-command/pkg (from /gemables/subversion/pkg:2344)
R /gemables/svn-command/ruby_subversion.rb (from /gemables/subversion/ruby_subversion.rb:2344)
R /gemables/svn-command/tasks (from /gemables/subversion/tasks:2344)
R /gemables/svn-command/test (from /gemables/subversion/test:2344)
Renaming to svn-command
------------------------------------------------------------------------
[tyler: ~/code/gemables]> /usr/bin/svn log -v -r 2354
------------------------------------------------------------------------
r2354 | tyler | 2007-03-05 12:30:39 -0800 (Mon, 05 Mar 2007) | 1 line
Changed paths:
M /gemables/svn-command/lib/svn_command.rb
M /gemables/svn-command/test/svn_command_test.rb
each_unadded now does a preview automatically (no need to press p)
------------------------------------------------------------------------
> /usr/bin/svn diff http://code.qualitysmith.com/gemables/subversion@2279
http://code.qualitysmith.com/gemables/subversion@2354 --diff-cmd colordiff
svn: 'http://code.qualitysmith.com/gemables/subversion' was not found in the repository at revision 2354
> /usr/bin/svn diff http://code.qualitysmith.com/gemables/subversion -r 2279:2354 --diff-cmd colordiff
svn: REPORT request failed on '/!svn/bc/2354/gemables/subversion'
svn: '/!svn/bc/2354/gemables/subversion' path not found
[tyler: ~/code/gemables]> /usr/bin/svn diff subversion -r 2279:2354 --diff-cmd colordiff
svn: 'subversion' is not under version control
These work:
> /usr/bin/svn diff http://code.qualitysmith.com/gemables/subversion@2279
http://code.qualitysmith.com/gemables/svn-command@2354 --diff-cmd colordiff
> /usr/bin/svn diff http://code.qualitysmith.com/gemables/svn-command -r 2279:2354 --diff-cmd colordiff
[tyler: ~/code/gemables]> /usr/bin/svn diff svn-command -r 2279:2354 --diff-cmd colordiff
Similarly with svn log:
[tyler: ~/code/gemables]> /usr/bin/svn log -v -r 2345 ... [works] [tyler: ~/code/gemables]> /usr/bin/svn log -v -r 2345 svn-command ... [works] [tyler: ~/code/gemables]> /usr/bin/svn log -v -r 2345 subversion svn: 'subversion' is not under version control > /usr/bin/svn log -v -r 2345 http://code.qualitysmith.com/gemables/svn-command ------------------------------------------------------------------------ r2345 | tyler | 2007-03-02 12:07:48 -0800 (Fri, 02 Mar 2007) | 1 line ... [works] > /usr/bin/svn log -v -r 2345 http://code.qualitysmith.com/gemables/subversion svn: REPORT request failed on '/!svn/bc/2345/gemables/subversion' svn: '/!svn/bc/2345/gemables/subversion' path not found
See Subversion / Dump and loading
See Subversion / How do I compare the contents of two directories/branches?
Concrete example: WC ~/svn/rails_backend has svn:externals directory ~/svn/rails_backend/lib/shared which links to ~/svn/shared .
But suppose you change the API of a class in ~/svn/shared and you want to fix all references to that class in ~/svn/rails_backend before you commit ~/svn/shared. That is, you want to integrate your changes to both working copies and then commit only when you've fixed it in both places. That's a problem.
Solution: change your svn:externals directory into a plain old symlink during development??
In our example, that means rm -rf ~/svn/rails_backend/lib/shared; ln -s ~/svn/shared ~/svn/rails_backend/lib/shared
But if you commit from within A (and not within B), the commit will exclude the changes made to A/B. If you are within A/B when you commit, it will only commit your changes to A/B (obviously).
Let's the layout is this:
If you have changed A/B and A/B/shared, you can't just go up to A and commit A/B, because A/B/shared won't be commited then.
You could get it to work if you temporarily removed A/B/shared during development and symlinked it to A/shared. Then your changes would be made to A/shared yet still show up in A/B/shared. And when you committed A, A/shared would be committed too because it is not svn:external.
If you treat your working copy directory like a "normal" directory, you may notice some strange behavior.
Among them:
Doing an export of that foreign repository location also has its share of problems:
Solution: Piston
http://svn.collab.net/repos/svn/trunk/doc/user/svn-best-practices.html.
Your working copy's directories and files can be at different "working" revisions: this is a deliberate feature which allows you to mix and match older versions of things with newer ones. But there are few facts you must be aware of:
Book reference: The limitation of mixed revisions.
- After every svn commit, your working copy has mixed revisions. The things you just committed are now at the HEAD revision, and everything else is at an older revision.
- Certain commits are disallowed:
- You cannot commit the deletion of a file or directory which doesn't have a working revision of HEAD.
- You cannot commit a property change to a directory which doesn't have a working revision of HEAD.
- svn update will bring your entire working copy to one working revision, and is the typical solution to the problems mentioned in point #2.
http://svn.collab.net/repos/svn/trunk/doc/user/svn-best-practices.html.
A nice feature of Subversion is that by design, there is no limit to the size of files it can handle. Files are sent "streamily" in both directions between Subversion client and server, using a small, constant amount of memory on each side of the network. Of course, there are a number of practical issues to consider. While there's no need to worry about files in the kilobyte-sized range (e.g. typical source-code files), committing larger files can take a tremendous amount of both time and space (e.g. files that are dozens or hundreds of megabytes large.) To begin with, remember that your Subversion working copy stores pristine copies of all version-controlled files in the .svn/text-base/ area. This means that your working copy takes up at least twice as much disk space as the original dataset. Beyond that, the Subversion client follows a (currently unadjustable) algorithm for committing files:
So while there's no theoretical limit to the size of your files, you'll need to be aware that very large files may require quite a bit of patient waiting while your client chugs away. You can rest assured, however, that unlike CVS, your large files won't incapacitate the server or affect other users.
- Copies the file to .svn/tmp/ (can take a while, and temporarily uses extra disk space))
- Performs a binary diff between the tmpfile and the pristine copy, or between the tmpfile and an empty-file if newly added. (can take a very long time to compute, even though only a small amount of data might ultimately be sent over the network)
- Sends the diff to the server, then moves the tmpfile into .svn/text-base/
http://svn.collab.net/repos/svn/trunk/doc/user/svn-best-practices.html.
When a file or directory is copied or renamed, the Subversion repository tracks that history. Unfortunately in Subversion 1.0, the only client subcommand which actually takes advantage of this feature is svn log. A number of other commands (such as svn diff and svn cat) ought to be automatically following rename-history, but aren't doing so yet. In all of these cases, a basic workaround is to use 'svn log -v' to discover the proper path within the older revision. For example, suppose you copied /trunk to /branches/mybranch in revision 200, and then committed some changes to /branches/mybranch/foo.c in subsequent revisions. Now you'd like to compare revisions 80 and 250 of the file. If you have a working copy of the branch and run svn diff -r80:250 foo.c, you'll see an error about /branches/mybranch/foo.c not existing in revision 80. To remedy, you would run svn log -v on your branch or file to discover that it was named /trunk/foo.c prior to revision 200, and then compare the two URLs directly:
$ svn diff http://.../trunk/foo.c@80 \ http://.../branches/mybranch/foo.c@200
http://svn.haxx.se/dev/archive-2003-10/0791.shtml,Philip Martin,2003-10-19 14:33:50 CEST
Even if I do a fresh checkout, there seem to be repositories which don't have an uuid. Why is that?I would guess the repositories were created before the UUID code existed. A dump/load cycle will create a UUID if one does not already exist.
http://svn.haxx.se/dev/archive-2003-10/0800.shtml,Philip Martin,
Yes, that's definitely a bug. I note that ra_local and ra_dav behave differently, and that for ra_local revision 0 behaves differently from the other revisions. Care to raise an issue?
http://svn.haxx.se/dev/archive-2003-10/0801.shtml,SteveKing,
Issue filed as number 1557.
This bug seems to still exist, at least in the version of Subversion used on [Dreamhost (category)]...
Here is evidence: This is from a repository I have hosted there:
> svn info Path: . URL: http://svn.tylerrick.com/public Repository Root: http://svn.tylerrick.com/public Repository UUID: 1bae183a-7f2a-0410-9965-889560e31888 Revision: 17 Node Kind: directory Schedule: normal Last Changed Author: tyler Last Changed Rev: 17 Last Changed Date: 2007-03-21 11:34:31 -0700 (Wed, 21 Mar 2007)
PROPFIND of '...': 501 Not ImplementedExample:
> svn co http://redhillonrails.org/svn/trunk/vendor/plugins/foreign_key_migrations/ svn: PROPFIND request failed on '/svn/trunk/vendor/plugins/foreign_key_migrations' svn: PROPFIND of '/svn/trunk/vendor/plugins/foreign_key_migrations': 501 Not Implemented (http://redhillonrails.org)
I could not find any much relevant/useful information about this. (http://www.google.com/search?q=svn+501+Not+Implemented)
The most likely reason for this that I could find was that they are using an old (1.1) Subversion server, and I was accessing it with too new of a client (tried it with command-line client 1.2.3 and 1.4.4, and TortoiseSvn)... but that still doesn't make a lot of sense, because I thought the clients were backwards-compatible with older servers...
Anyway, here's what I did find out...
I was under the impression that http://redhillonrails.org/svn/trunk/vendor/plugins/foreign_key_migrations/ was a valid Subversion repository/path URL. I was able to go there in my web browser and browse the repository and browse the source, which served to further confirm my theory. (The output on that web page was "Revision 271: /svn/trunk/vendor/plugins/foreign_key_migrations/ ...", which is not something that Apache would display if it were just a normal directory listing...)
Anyway, I'm not sure how they have their web server configured or why, but it looks like you have to use one URL when accessing the repository via HTTP and a different URL when accessing from a Subversion client...
http://www.redhillonrails.org/#redhillonrails_core.
To install using SVN:ruby script/plugin install svn://rubyforge.org/var/svn/redhillonrails/trunk/vendor/plugins/redhillonrails_coreor using HTTP:
ruby script/install http://www.redhillonrails.org/svn/trunk/vendor/plugins/redhillonrails_core
So if you change the indent of every line on the file, you lose any useful diffing information; the whole file basically looks like it was replaced with entirely new content, which is not the case.
It is useless mostly because it does line based diffing. If it could identify the characterwise differences on each line, we would be in better shape.
Currently it will not give you any error/warning when you do the svn mv/cp but will throw an error when you try to commit.
Depends on the policies of the particular repository.
Usually, it's good to commit pretty frequently so that you can do frequent integration with other developers (and find out about conflicts sooner).
On the other hand, you shouldn't commit anything that's not "ready" yet. In particular, you should not commit buggy code. If you have automated tests, you should make sure these are all passing for your code before you commit.
If the affected files of each overlap... Nope. You would need two different working copies (checkouts) in order to keep them separate.
svn ci file1 overlapping_file2 -m "Change 1" # oops, you just committed part of Change 2 and said that it was for Change 1 in your log message! svn ci overlapping_file2 file3 -m "Change 2 (unrelated to 1)" # by the time you do this, overlapping_file2 will have no uncommitted changes
If they don't overlap, then yes, you can. You'd just need to list the files to commit for each of your commits:
svn ci file1 file2 -m "Change 1" svn ci file3 file4 -m "Change 2 (unrelated to 1)"
If one of my changes is really minor and hardly worth making a separate commit for (like a typo fix or removing some old debug code or minorly changing a comment, for example), then I usually don't worry about that commit being subsumed as part of a larger commit (an unrelated change). I may or may not mention the minor change in the commit log for that change set.
http://svn.collab.net/repos/svn/trunk/doc/user/svn-best-practices.html.
When you commit a change to the repository, make sure your change reflects a single purpose: the fixing of a specific bug, the addition of a new feature, or some particular task. Your commit will create a new revision number which can forever be used as a "name" for the change. You can mention this revision number in bug databases, or use it as an argument to svn merge should you want to undo the change or port it to another branch. Book reference: "Subversion and Changesets" sidebar, within chapter 4.
http://svn.collab.net/repos/svn/trunk/doc/user/svn-best-practices.html.
Try to create as many two-way links between Subversion changesets and your issue-tracking database as possible:
- If possible, refer to a specific issue ID in every commit log message.
- When appending information to an issue (to describe progress, or to close the issue) name the revision number(s) responsible for the change.
I agree!!
http://svn.collab.net/repos/svn/trunk/doc/user/svn-best-practices.html.
When committing the result of a merge, be sure to write a descriptive log message that explains what was merged, something like:
Merged revisions 3490:4120 of /branches/foobranch to /trunk.Book reference: Tracking merges manually, and Merging a whole branch to another.
(This shouldn't be necessary, because Subversion should track it for you ... but it doesn't, so it is.)
(For example, copying my_shared_code/gems/template to my_shared_code/gems/a_new_gem...)
Ah, you'd think it would be as simple as just cp -R source_dir destination_dir/
The problem with that, though, is that all the .svn files are included with it.
What's wrong with that, you ask? Well, as you start modifying, renaming, or deleting those files, it will think you are modifying a working copy.
> svn st A test/test_helper.rb ! test/some_test.rb ! + _.gemspec M + Rakefile ...
Solution 1:
If you just want to start fresh (so that you can svn add the whole directory at once as if it were a new directory), it's really easy: you just need to remove all the .svn directories inside of it.
> find -name .svn ./test/.svn ./lib/.svn ./.svn > find -name .svn | xargs rm -rf > svn st svn: '.' is not a working copy
Solution 2: Use svn export instead of cp -R !
http://svn.collab.net/repos/svn/trunk/doc/user/svn-best-practices.html.
This is a hotly debated question, and it really depends on the culture of your software project. Rather than prescribe a universal policy, we'll describe three common ones here.
The Never-Branch system
(Often used by nascent projects that don't yet have runnable code.)
- Users commit their day-to-day work on /trunk.
- Occasionally /trunk "breaks" (doesn't compile, or fails functional tests) when a user begins to commit a series of complicated changes.
Pros: Very easy policy to follow. New developers have low barrier to entry. Nobody needs to learn how to branch or merge.
Cons: Chaotic development, code could be unstable at any time.
A side note: this sort of development is a bit less risky in Subversion than in CVS. Because Subversion commits are atomic, it's not possible for a checkout or update to receive a "partial" commit while somebody else is in the process of committing.
The Always-Branch system
(Often used by projects that favor heavy management and supervision.)
- Each user creates/works on a private branch for every coding task.
- When coding is complete, someone (original coder, peer, or manager) reviews all private branch changes and merges them to /trunk.
Pros: /trunk is guaranteed to be extremely stable at all times.
Cons: Coders are artificially isolated from each other, possibly creating more merge conflicts than necessary. Requires users to do lots of extra merging.
![]()
![]()
The Branch-When-Needed system
(This is the system used by the Subversion project.)
- Users commit their day-to-day work on /trunk.
- Rule #1: /trunk must compile and pass regression tests at all times. Committers who violate this rule are publically humiliated.
- Rule #2: a single commit (changeset) must not be so large so as to discourage peer-review.
- Rule #3: if rules #1 and #2 come into conflict (i.e. it's impossible to make a series of small commits without disrupting the trunk), then the user should create a branch and commit a series of smaller changesets there. This allows peer-review without disrupting the stability of /trunk.
Pros: /trunk is guaranteed to be stable at all times. The hassle of branching/merging is somewhat rare.
Cons: Adds a bit of burden to users' daily work: they must compile and test before every commit.