views:

347

answers:

4

It is good practice to remove old code instead of just commenting it out. It is often claimed that the old code parts can always be found again in the old SVN repository revision, if needed.

But practically, it's not that easy, right? If the old code is in some unknown old SVN revision then it can be quite hard to find.

I'm exactly in that situation right now: There's a function that I don't need anymore, and I should throw it out, since it's in SVN, but I hesitate because I might need it again, and I'm afraid it's going to be hard to find in the repository.

Of course, one can always make a commit message, saying "removed function myFunction", but sometimes you can't note every little code removal in the commit message, and it can also be tedious to look through all commit messages to find something again.

An automatic tool would be better, something like

svn find "void myFunction\(" my-file.cc

which would tell me the different results from different revisions. Does something like that exist?

EDIT: Do other version control systems have it? Git maybe? (That'd be a reason to switch, I'd say.)

UPDATE: So there's no real answer except the tiny brittle shell script I found more or less by accident (see my answer below). I think, that's really a shame for SVN. Finding something in earlier revisions should be one of the central functionalities of version control. Does anyone have more info?

+2  A: 

As it turns out, Git has exactly this feature. You can use Git to clone your Subversion repository (using git svn), and then use the Git tools (in particular gitk makes this easy) to search for any text added or removed anywhere in the repository history.

To find the latest revision that still contained some specific text, you can use git bisect to efficiently search the history for the revision where some condition changed.

Greg Hewgill
Ha, I've just added that question (see EDIT). Thanks for the info!
Can you add an example of how to search for a piece of source code? It's not immediately clear to me from the linked "gitk" man page.
Wim Coenen
+6  A: 

I googled some more and found the following script (see here). I tested it briefly and it seems to be working fine:

rev_grep.sh
=====================
#!/bin/ksh

URL=$1
REGEX=$2

LAST_REV="n/a"

svn log -q $URL | perl -ne 'print "$1\n" if /^r(\d+)/' |
while read r
do
    ##svn cat -r $r $URL | grep "$REGEX" > /dev/null
    BUFFER=`svn cat -r $r $URL | grep "$REGEX"`
    RET=$?
    if [ $RET -eq 0 ]
    then
        echo "Match in revision: $r. Removed in $LAST_REV."
        echo $BUFFER

        exit 0

    elif [ $RET -ne 1 ]
    then
        ## grep hit an error
        exit 2
    fi

    LAST_REV=$r
done
exit 1

The only problem is that, if your repository requires a password, you'll have to enter it many times.

+1  A: 

I guess will get a couple of negative votes for this...

There are some things that are more easily solved on non-technical grounds. Write in the log message that you are removing the function. Searching for removals will be just parsing the svn log:

$ svn commit file.c -m "Removal of void deprecated_function()"

Now you can just search the log. Commits should always identify on a human readable short way what the changes are.

David Rodríguez - dribeas
I won't vote you down, but I think that OMG situations arise that can't be foreseen in comments...
Brent.Longborough
Sometimes you want to find specific code in an earlier revision. Just yesterday I was wondering: Wasn't this header XYZ.h included at some point? You can't log all detailed information like this in a commit message. And the search should be easy, technically. So why are you discouraging it?
Also, can you really rely on your co-workers to always exactly note everything they change in the commit log message?
+1  A: 

This is similar to the shell script from the answer by dehman but is written in python. This way you only need python to run the script and maybe more friendly to different operating systems.

import os
import re

filename = 'CustomROIMarker.cpp'
stringToFind = 'ImageMarker::outOfDataSet;'

log = os.popen('svn log ' + filename).read()
versions = re.findall('r\d+',log)
for v in versions:
    numVer =  int(v.strip('r'))
    cmdString = 'svn cat -r ' + str(numVer) + ' ' + filename
    contents = os.popen(cmdString).read()
    if re.search(stringToFind,contents) != None:
        print "Present in " + str(numVer)
    else:
        print "Not Present in " + str(numVer)

You will have to edit the filename and stringToFind variables.

Shao
Thanks for posting this. You can use sys.argv for getting command line arguments.
Jesse