Is it possible to checkout only those files from a SVN repository that were modified in a revision or range of revisions, without checking out any files that were not modified?
views:
947answers:
7I'm not completly sure if this is possible but you can also do something like this:
svn checkout --revision <revisionNumber>
to get a certain revision and
svn log --revision <revisionNumber>
to list all files chaned in a revision
If you use svn log with the -v (verbose option):
svn log -r <revision> -v <path>
You will get an output that includes the changed files:
r3 | ciaran | 2008-11-16 12:24:30 +0000 (Sun, 16 Nov 2008) | 1 line
Changed paths:
A /trunk/apache/apache.conf
A /trunk/application/controllers
Commit message goes here
You should be able to manipulate that with some grepping etc. to produce a sequence of svn co commands.
There is afaik now direct way to get just the changed files and not all.
My idea would be: use the verbose output of the list (which shows the last changed version), filter it through awk, and checkout the rest. E.g. to search the files which changed in version 42 I would use this
VERSION=42
svn list -v -R -r $VERSION svn://... | awk "/^[ ]*$VERSION/ {print \$7}" > files_to_checkout
And later do a svn update -r $VERSION 'cat files_to_checkout'
(or a co on the url, depending on where you will run the command).
EDIT: Additional even shorter: use the svn diff command, and replace with -x and --diff-cmd the diff command with svn co. This requires some argument shifting hacking (which I wont elaborate here), but needs just one line and no intermedate file (which you could save above too, but that would have cost readability)
My suggestion is in the same lines as flolo suggests. But, takes a range. You could the following shell function.
function checkout_files_in_revrange()
{
svn_url=$1;
start_rev=$2;
end_rev=$3;
for theCheckoutCanditate in `svn log -r $start_rev:$end_rev --verbose --incremental | grep " M " | cut -f5 -d' ' | cut -f3- -d/`
do
svn co $svn_url/$theCheckoutCandidate -q;
done
}
We do this in an MSBuild script:
Step 1: - Use the diff command to get the list of modified files, redirect output into a temporary file in the target directory Step 2: - Read the temporary file into an itemGroup
<Exec command="$(svnExecutable) diff -r $(StartRevision):$(EndRevision) $(DOUBLE_QUOTES)$(SvnRepositoryPath)/$(DOUBLE_QUOTES) --no-diff-deleted --summarize > $(TempFilePath)" WorkingDirectory="$(WorkDirectory)" />
Another take at answering your question:
Assuming you have an existing workingcopy you should just use 'svn update' on the root of the directory containing the files you are looking at as that retrieves exactly what changed between your current revision and the HEAD revision with the least data possible.
Older sourcecode management systems like CVS and VSS asked the server for every file has this file changed?, while subversion just sends the changes of a tree as a single action. When you pass a list of files to svn update you don't have this advantage.
Therefore the most efficient way to transfer what has changed is just updating. This only transfers a binary diff of the changes in HEAD compared to the base version of your working copy.
If the problem you are trying to solve is that svn update is to slow, then we are trying to solve that for Subversion 1.7.
This version will introduce a new working copy data storage format that will make simple operations that have to lock an entire working copy (like updating) much faster.
In almost the same lines as most of the folks have suggested, (however only in a system with grep and awk), you can get the list by executing
svn log -v --revision <revision_number> | grep "^ " | awk '{print $2}'
.