views:

641

answers:

8

While programming software stored in a Subversion repo, I often modify some files, then notice that I'd like to do some preparatory change for my main work. E.g. while implementing new functionality, I notice some refactoring which might help me.

In order not to mix two unrelated changes, in these cases I'd like to "stow away" my changes, i.e. revert to the repository version, do some other changes, commit these, then "fetch back" my changes.

git-stash allows to do just that. Is there some way to do this with Subversion, either directly or with some plugin or script. Eclipse plugins would also be fine.

+1  A: 

I have also wanted this feature. I currently use TortoiseSVN.

I have not found a hardfast solution except to export the tree, revert back to repository make my changes and commit, then compare the changes from the exported tree back into my source controlled directory using a tool like Beyond Compare.

Or, another solution might be to branch from the HEAD to another directory, make your changes and the commit. Once you're ready to merge those back to your other working copy, do an update and merge your changes.

Anthony Shaw
+1  A: 

Obvious way would be using multiple working copies, involving an additional checkout which is a bit expensive.

Alternatively, since Subversion can do branching faster than a physical copy operation, you can "checkin" your current changes to a temporary branch and switch back and forth.

If your changes do not overlap, you can put them in separate changelists to manage multiple checkins.

ssg
Subversion can do branching pretty fast compared to what? Maybe CVS, but I don't think that it is faster than any DVCSes.
Jason Baker
Of course not, what I meant was it could be faster than copying away your changes physically and doing a revert (a la stashing).
ssg
Branching in Subversion is a constant-time operation. It does not depend on the size of the repository, hence it is pretty fast.
JesperE
branching in subversion depends on the number of files because it will generate copies of the file. so it’s not really a O(1) operation
knittl
@knittl: No it doesn't. _Checking out_ a branch depends on the number of files, but _creating_ the branch doesn't. Go and read http://svnbook.red-bean.com/en/1.5/svn-book.html.
sbi
+5  A: 

The easiest way would be to use a temporary branch, like this:

$ svn copy ^/trunk ^/branches/tempbranch
$ svn switch ^/branches/tempbranch
$ svn commit -m "Stashed"
$ svn switch ^/trunk
$ ... hack away in trunk ...
$ svn commit -m "..."
$ svn merge ^/branches/tempbranch .
$ svn rm ^/branches/tempbranch
$ ... continue hacking

This could (and probably should) be put in a script if done on a more regular basis.

JesperE
Why is this voted down, while "solutions" are voted up that don't even work when you have deleted/added files or have changed any properties? Yes, this isn't the easiest thing to do when you do it for the first time, but, besides having another copy checked out to work in parallel, this is the only solution that works in all cases.
sbi
Nice use of ^ syntax for repo root (since svn 1.6). Good solution when your repo has trunk/tags/branches at top level.
bendin
The URL-abbreviation syntax in 1.6 is a great improvement for the command-line client. See http://svn.collab.net/repos/svn/trunk/notes/cli-repo-root-relative-support.txt for more info.
JesperE
I don't really like putting all these temporary branches on the server. I feel this should be done locally, instead of cluttering up the server (and generating spurios checkin emails, if you generate mails on checkin). Still, an option worth remembering.
sleske
@sleske: yes, you are committing your temporary stash to the server, but the branch itself is deleted. Anyway, I think this is the fastest and most robust way to do it.
JesperE
@sleske: SVN is not a distributed VCS, so everything has to be on the server. That's just the way it is.
sbi
+6  A: 

when I've got uncommitted changes from one task in my working copy and I need to switch to another task, I do one of two things:

Check out a new working copy for the second task.

or

Start a branch:

workingcopy$ svn copy CURRENT_URL_OF_WORKING_COPY SOME_BRANCH
workingcopy$ svn switch SOME_BRANCH
workingcopy$ svn commit -m "work in progress"
workingcoyp$ svn switch WHATEVER_I_WAS_WORKING_ON_BEFORE

I have some scripts that help to automate this.

bendin
this will result in a lot of trash on your subversion server
knittl
No, it won't result in "a lot of trash" unless you're a complete slob. The storage required for such a "stash branch" is proportional to the size of the *changes* committed. Furthermore, you can remove the branch again when it's obsolete so it doesn't clutter up the branches directory. Yes, this is a situation where a distributed system like git really wins and if the OP had phrased his question differently, I would have just answered: "use git already", but he didn't.
bendin
@knittl: No, it won't. And what's even more important: It won't result in changes lost as does your suggestion. This, and having another checked out copy of the trunk/same branch, are the only two reliable ways to do this that I know. If you feel uncomfortable with this, just check out another copy and work on it in parallel.
sbi
+1, I regularly create a second working copy of a branch simply so I can perform clean merges of trunk, without having to 'stash' my current work in progress first.
Ether
A: 

you can store your current changes with svn diff into a patch file, then revert your working copy:

svn diff > stash.patch
svn revert -r .

after you’ve implemented your preparatory feature, you can then apply your patch with the patch utility:

patch < stash.patch

as others have noted this will not work with svn:properties and tree operations (add, remove, rename files and directories).

binary files could also give problems, i don’t know how patch (or tortoisesvn in this case handles them)

knittl
This probably doesn't work too well with removed/renamed files, I think.
JesperE
it was just a suggestion. also i noted it will not work well with binary files (i guess)—the last time i seriously used subversion, before switching to git was too long ago
knittl
I think this is the least time consuming solution, however there is no patch tool on Win32 by default if that's the platform of choice.
ssg
@ssg8: iirc tortoiseSVN provides a patch tool (create patch and apply patch in submenu)
knittl
See the box titled "Why Not Use Patches Instead?" at http://svnbook.red-bean.com/en/1.5/svn-book.html#svn.branchemerge.basicmerging.stayinsync to understand why this is a bad idea.
sbi
I looked at the document and it only discourages patch because 1) svn:props are not diff'ed 2) tree operations (directory add etc) are not diffed. Since both are rare I think this methodology is still perfectly acceptable. I'm having hard time to understand the psychology behind downvotes to this answer.
ssg
@ssg: I down-voted it because, as rare as you might think tree changes (refactoring anyone?) and property changes (`svn:ignore`) are, the chance of losing any changes isn't something I feel like risking, while two other possibilities (parallel checkout and ad-hoc branching) are lying around waiting to be used. Of course, don't know why others down-voted, but I guess that losing changes is not something seen lightly by many developers. _Not_ losing any changes is all a VCS is about, after all.
sbi
@sbi: I don't think that's a valid justification for a downvote. It's not a "bad answer". It's just not the perfect answer that's all. I don't think this person deserves punishment for his suggestion. Would you prefer him not to answer instead? If yes, then yes, you should downvote. Otherwise this is punishing good intentions.
ssg
A: 

another option is to copy your current checkout to a new directory and revert all your changes. this way you’ll save the hassle of creating a temporary branch on your server—after all stashing is a local operation, which not everybody should see and can be done quite often.

after committing your hotfix you can update your main working copy and delete your “stashing area”

knittl
+1  A: 

I don't know of an easy way to do that with just svn. Honestly, I'd advise using git-svn to make a git repo that acts as an svn working copy, and just using git stash with that. Just replace git pull with git svn rebase and git push with git svn dcommit and you can actually keep 90% of your git workflow and still be talking to an svn server.

Walter Mundt
But the link http://stackoverflow.com/questions/1554278/temporarily-put-away-uncommited-changes-in-subversion-a-la-git-stash I mention in the comments above does propose practical solution to do a stash in svn only.
VonC
Fair enough; in fact, google lead me to that solution on a blog just now. I still maintain that, for this questioner, git-svn is a natural solution.
Walter Mundt
+3  A: 

This blog post advises using diff and patch.

  • git stash approximately becomes svn diff > patch_name.patch; svn revert -R .
  • git stash apply becomes patch -p0 < patch_name.patch

Note that this doesn't stash metadata changes or (I think) directory creates/deletes. (Yes, svn tracks those separately from directory contents, unlike git.)

Walter Mundt
This is an accidental duplicate of http://stackoverflow.com/questions/1554278/temporarily-put-away-uncommited-changes-in-subversion-a-la-git-stash/1554343#1554343 -- send upvotes there.
Walter Mundt