Refspecs as a general concept are great, but there's a somewhat unfinished feeling to them.
When you first clone some existing repository, your git clone uses a built-in equivalent to git remote add to add the remote name. As the git remote documentation notes (a bit elliptically - see meaning 2a):
With -t <branch> option, instead of the default glob refspec for the remote to track all branches under the refs/remotes/<name>/ namespace, a refspec to track only <branch> is created. You can give more than one -t <branch> to track multiple branches without grabbing all branches.
What this boils down to is the fact that after git clone, the (single) default fetch refspec for the new clone is:
+refs/heads/*:refs/remotes/<name>/*
where <name> is the name from the -o option, or origin if you did not specify such an option.1
What it doesn't mention explicitly, and is not obvious, is that the remote.remote.fetch setting in a Git configuration file is cumulative.2 This means that you can open up the existing .git/config file, once git clone has created it, and edit it. You will see:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
You can change this to add another line, so that it reads:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
fetch = +refs/exp/*:refs/exp/*
Now any git fetch origin will overwrite any of your existing refs/exp/ references with those that are on origin. Fetching with prune = true or with the -p or --prune option will delete any of your existing refs/exp/* references that have no corresponding name on origin.
If you wish to replace their refs/exp/* names with your own refs/rexp/origin/* names, make the second line read:
fetch = +refs/exp/*:refs/rexp/origin/*
and now you have invented exp-tracking names.
(Given that there is no refs/tags/*:refs/tags/* refspec—with or without a leading + sign—you might wonder how tags work at all. The answer here is "somewhat magically, with internal rules that cannot be expressed through a refspec". That's part of what I mean about the somewhat unfinished feeling. It's also not obvious what to put in during a git clone, but note that git clone -c name=value lets you write configuration values at git clone time. You still need to somehow know that the remote you're cloning has refs/exp/* names, though.)
1In a forthcoming Git release, the -o option is likely to have a configurable default, so that leaving out -o won't necessarily mean use origin, but for now, that's what it always means.
2In contrast, a setting such as user.name or user.email uses only the last value. That is, if your configuration file says:
[user]
name = fred
name = flintstone
then user.name is flintstone: the earlier fred value has been discarded in favor of the later flintstone one. A cumulative setting can only obtained with git config --get-all or git config --get-regexp; it comes out as one line per value. See the git config documentation for more details.