Capistrano, by default, touches every file it considers an 'asset'. As you said, this means after every deploy rails thinks every asset has changed and browsers wil download a newer version every time.
You can disable this in Capistrano with the following setting
set :normalize_asset_timestamps, false
If you are using SVN then the modified dates for your files should reflect the dates they were last modified in your repository, so that should be perfect.
If you are using Apache, you can add something like this to really making caching work for you. This helps by telling the browser to rely on the "Cache Control" directives meaning if it knows the asset is cached, it won't even bother requesting it.
#Etags should be based on the file parameters only (default includes INode)
FileETag MTime Size
#Rewrite stuff
RewriteEngine On
#This sets the environment variable (is_versioned) when the URL query string
#looks like ?874353948543 or any string of digits
RewriteCond %{QUERY_STRING} ^[0-9]+$
RewriteRule ^(.*)$ $1 [env=is_versioned:true]
<Directory /deployed-rails-app/public/ >
Options -Indexes FollowSymLinks -MultiViews
AllowOverride None
Order allow,deny
allow from all
#For files, force the browser to rely on cache-control directives and
#Rails asset timestamps by removing Etags and Last-Modified dates
#For all assets that aren't stamped by rails, cache them for ~ 3 hours
Header set "Cache-Control" "max-age=10000"
Header unset Etag
Header unset "Last-Modified"
#For all assets that ARE stamped by rails, cache them for 30 days
Header set "Cache-Control" "max-age=2592000" env=is_versioned
</Directory>
I've set my production server up this way and now return visitors only perform one request (Get /) which returns the dynamic content and all the assets (~ 40 - 50) are cached.