2

In my SVN trunk, I deleted a directory and re-added it in a single commit. Now, trying to get "svn log" I only see the history of that commit, without all the changes I did in the past. I know it makes sense because of the deletion and re-adding of the files, but I want to revert the whole thing and restore my history. How can I do that?

Additional info and details: I was working on a branch of a trunk in SVN. For updating the branch from the trunk, I manually updated files with plain diffs, not using the "svn merge" command. For new files that were added to the trunk I manually "svn add" them in my branch, same for deletion (svn rm). When I wanted to merge back the branch to the trunk, a coworker of mine suggested I "svn merge" the branch (and I solved lots of conflicts in the process), then "svn merge --reintegrate" the trunk from the branch and commmit to the trunk. Somewhere alongside all the conflicts I deleted an entire directory, committed it to the branch, re-added it to the branch and committed again. Now the "merge --reintegrate" brought the deletion-readdition of that directory, and the commit caused all the history to disappear. I really just want to revert the whole thing, so I could start clean (I already know how to make the commit correct this time, but I don't know how to revert and restore the history).

Edit: I tried to get logs of some files I know got deleted from this question. Revision 4129 was the deletion-re-adding, and 4120 was the last time I eddited one of the files. "svn log -r4129 file" just lists my latest commit without the history. "svn log -r4120 file" returns a single line of "--------". I think the main difference from that question is that I also re-added files in the same commit, instead of just deleting.

Community
  • 1
  • 1
itzhaki
  • 317
  • 2
  • 10
  • Sorry, I misunderstood you. I thought you just wanted to just view the history, but you want the repository to appear as if your delete had never happened, correct? I don't believe there's a way to do that. – Patrick Quirk Apr 06 '15 at 15:06
  • @PatrickQuirk yes that's what I want. I belive there should be away, considering if I "svn up" to the revison prior to the whole mess I can view my correct history. I'm looking for something like: "svn up -r1000 (1001 being the bad commit); svn commit -m"restored history" – itzhaki Apr 06 '15 at 15:12
  • possible duplicate of [examining history of deleted file](http://stackoverflow.com/questions/401331/examining-history-of-deleted-file) – bahrep Apr 06 '15 at 15:12
  • @bahrep the suggested svn log does not work (see my edit above) for me. I think it's because I re-added files on the same commit and not just deleted it. – itzhaki Apr 06 '15 at 15:26
  • Why don't you undo your problematic revisions with "cherry pick merge"? `svn merge -c -revNumber .` More about reverse "cherry pick" can be found here: http://svnbook.red-bean.com/en/1.6/svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.undo – Ivan Jovović Apr 06 '15 at 15:32

2 Answers2

4

In my SVN trunk, I deleted a directory and re-added it in a single commit.

Bad, programmer! No donut for you!

What you did was create a completely different directory, but one with the same name. To you, they look the same. To Subversion, the two directories have nothing to do with each other.

Why did you delete the old directory and create a new directory with the same name?

You want to revert? Find the revision where you deleted and added the directory in the svn log and try this:

$ svn merge -c -$rev

Where $rev is the revision in the log where you deleted and added back in the directory. This is how you can remove any change you've made in Subversion.

You can specify multiple -c $rev in the command. If this produces a conflict, you might have to take a slightly different tack. In that one, you'll have to use pinning to pin the directory revision as it looked in a previous release. Let's say your log shows you deleted directory foo in revision 12345, and now you need to get it back:

First, delete the current directory foo:

$ svn delete foo

Now, copy that foo back from the revision previous to the deletion when that directory still existed. Since it was deleted in revision 12345, we need to copy from revision 12344:

$ svn cp $REPO_URL/trunk/foo@12344 .

This should restore the old copy.

Additional info and details: I was working on a branch of a trunk in SVN. For updating the branch from the trunk, I manually updated files with plain diffs, not using the "svn merge" command. For new files that were added to the trunk I manually "svn add" them in my branch, same for deletion (svn rm).

I need a drink...

What you're doing is a merge, but not telling Subversion you did the merge. If you do the merge in Subversion now, you'll get a bunch of merge conflicts because Subversion will see the same area of the file being changed in both the branch and the trunk.

When you add a new file to the branch, it's a completely different file than the one in trunk. It might be the same name and in the same directory, but since you added it into the branch, you can't merge changes from the trunk on that file into that branch.

If possible, delete the file on the branch, and copy it from trunk. That way, changes in trunk can be merged to the branch.

Which gets us to something very, very important: Don't create a branch by doing an add. Always copy the branch from trunk (or wherever you're branching from). Otherwise, that branch and trunk don't share the same history. If you haven't done that initial copy, you can never ever use the Subversion merge. The branch and trunk share no common history.

There are times when it is easier to manually add a change into the branch rather than merging it from trunk. For example, the change on the branch isn't the same change on trunk. In that case, you can use the --record-only to let Subversion know you did the merge anyway:

 $ svn merge --record-only -r12345 $REPO/trunk .

The above will record that a merge of change set 12345 was done on the branch, and Subversion won't try to do the merge again.

Merging is your friend. Don't try to get around it. Subversion does a pretty good job at merging once you understand that Subversion needs a common ancestor between the branch and the branch/trunk being merged. Use svn cp to setup that relationship.

David W.
  • 105,218
  • 39
  • 216
  • 337
  • Thank you very much for the tips. Looks like I just started the whole thing a mess, definitely a lesson learned there. Lucky me, we are switching our repository to GIT in about a week, and GIT managed to ignore all the problems, and shows all the history correctly. – itzhaki Apr 07 '15 at 07:19
-1

The only way you can truly restore this with the original history showing for that directory is to recreate the repository using svnadmin dump/load commands operating on the server. Any merging or other normal svn commands you do will only result in more additional commits on top the already existing cut in the history. Maybe something like that is acceptable for you, but it's not what your question was.

So, with svnadmin, what you would do is dump the contents of the repository to a file, adding an option to only include up to the revision before the directory was deleted. Then load that dump file into a new repository. Then you have your repository as it was before the delete happened. Now, in theory you should be able to do another dump of the revisions from after the delete/readd to HEAD and load those back in to the new repository, giving you a perfect new repository without the break and included everything up to current. That may not work though depending on what other changes might be mixed into that skipped revision.

You will probably want to read up on the commands over in the svn reference, but here's what it might look like:

svnadmin dump C:\Repositories\myrepo -r4128 > myrepo.dump
svnadmin load C:\Repositories\mynewrepo < myrepo.dump

svnadmin dump C:\Repositories\myrepo -r4130:HEAD --incremental > myrepo2.dump
svnadmin load C:\Repositories\mynewrepo < myrepo2.dump

Community
  • 1
  • 1
ioscode
  • 801
  • 4
  • 12