20121108

How to restore the subversion history of a file

Every now and then the history of a file in a subversion repository is lost. I’ll describe how you can restore the history.

If you do a svn copy the file history of the new location shares the history of the old location. This is way subversion supports svn move and branches. Restoring a file’s history is only a matter of copying the right file. Given the file $A_FILE to restore, the new file location $B_FILE and the last revision $A_REV of  $A_FILE (before $A_FILE was removed) the operations to restored the history of $A_FILE are:

svn delete $B_FILE
svn cp $URL/$A_FILE@$A_REV $B_FILE
svn cat $URL/$B_FILE > $B_FILE

After you restored $A_FILE’s history all changes directly to $B_FILE are lost. Only the content of the file $B_FILE survives.

Here’s a commented script demonstrates the problem and show how to fix it:
#!/bin/bash -ex

#do everything in a working directory that's removed after the script ran
mkdir -p work
WORK=$(readlink -f work)
cd "$WORK"
trap 'rm -rf "$WORK"' EXIT SIGINT SIGTERM

#setup a repository
REPOSITORY=$(readlink -f repo)
svnadmin create "$REPOSITORY"
URL=file://$REPOSITORY

#checkout the local workspace
svn co $URL workspace
cd workspace

A_FILE=a.txt
B_FILE=b.txt

#create the file to restore
echo $A_FILE content > $A_FILE
svn add $A_FILE
svn commit -m"initial version of $A_FILE"
svn update
A_REV=$(svnversion)

#history of the file is lost
svn delete $A_FILE
svn commit -m"deleted $A_FILE"

#the new file
echo $B_FILE content > $B_FILE
svn add $B_FILE
svn commit -m"initial version of $B_FILE"
svn update
B_REV=$(svnversion)

#restore the file history and keep the file content
svn delete $B_FILE
svn cp $URL/$A_FILE@$A_REV $B_FILE
svn cat $URL/$B_FILE > $B_FILE
svn status
svn commit -m"history from $A_FILE in new path $B_FILE"

#check the result
svn update && svn info
svn log --diff $URL/$B_FILE
svn cat $URL/$B_FILE
svn diff $URL/$B_FILE $URL/$B_FILE@$B_REV

No comments:

Post a Comment