How To: Rename, Move, and Delete Source-Controlled Items in VS.NET

In response to my recent post, What is a Source Control Binding?, reader Keith Hill writes,

"A bit OT but do you know why VS.NET SCCI can't handle renaming projects once they are checked into a SCM system (ClearCase) is what I am using)? (...) It sure would be nice if the VS.NET SCCI could just handle this for me."

Indeed, it would be nice if SCCI supported automatic renames. And just to be clear; renames are just one of a set of similar operations, which I’ll refer to as namespace changes in this post. Namespace changes include RENAMES, MOVES, and DELETES.

So why aren't namespace changes that we make to our projects and files in Visual Studio .NET pushed to the source control database and committed automatically? 

Short answer: the source control plug-in providers (Rational, SourceGear, Microsoft, Perforce, PVCS, etc) have not taken the time to provide this functionality and/or have not demanded that this functionality be facilitated by the addition of MSSCCI functions. Of course, namespace tracking of the sort that ensures that your file renames in VS.NET are pushed to the database version of that file is completely doable, even today. However, the projected cost of doing it right--of implementing an elegant namespace change-aware source control system for integration with Visual Studio .NET and other development environments (Dreamweaver jumps to mind)--appears to have deterred even the most deep-pocketed source control vendors.  The architecture isn’t exactly mind bending. The do-it-right approach involves some or all of the following elements. Namespace changes must be:

a)     Performed in a Transactional way (SCCI commits all namespace changes at one time; on check in, for instance);

b)     Reversible (for example, on loss of network connectivity or in response to an Undo Checkout operation);

c)     Tracked by the source control system using GUIDs that link a working copy of a file to its master copy in the database or;

d)     [Optionally] broadcast or propagated to all users' working copies of that project (msg, 'Hey, UserA just renamed a file you have checked out. What do you want to do?').

A truly transactional source control solution would be ideal. The ability to reverse, or roll back a namespace change (which would be close to ideal) would require the provider to either cache a complete copy of a solution or add some code to their systems that would preserve the history of name changes to a file until the parent project/solution is checked in or an undo checkout is requested. Again, I don’t think that any of the providers do this currently. MSSCCI uses actual file names to uniquely identify all source-controlled files rather than separate GUIDs. Changings this could allow a file that is renamed in one place (on the client) to be mapped to a file with another name (the as yet un-renamed file in the scc database). Finally, none of the SCC providers provide namespace change broadcasting or notification services. Again, I reserve the right to be mistaken.

A A halfway solution?

The Visual Studio .NET source control integration development team has considered it.  However, in lieu of a well-designed namespace change-aware system, the risks associated with renaming a project or file in the database, automatically, outweigh the potential advantages.

You might ask, “what are these risks associated with renaming projects?" To answer that question, consider the following hypothetical scenario:

S Simple Rename Scenario--Single User

Risk: unable to easily undo checkout of a solution containing a renamed file.

++Assumes that client file renames are immediately committed in the SCC database++

Bob renames a project from Peck.csproj to Hubble.csproj. Two files are changed in Bob's working folder: the solution file (telescope.sln) and Peck.csproj. The SCS system detects a namespace change (the rename) and automatically commits that one change to the database; Peck.csproj gets renamed to Hubble.csproj. The database version of telescope.sln is not updated, and thus, differs from Bob’s version of the solution file. Bob works on his project for a while and then decides--for whatever reason--to undo checkout for the entire solution. The telescope.sln file that he gets back from source control references the old project name, ‘Peck’. The source control system cannot find a project named 'Peck' on local disk (because neither local source control integration nor the MSSCCI provider remembers the rename to the project file, therefore none of them can undo this change) so it assumes that another user has added a new project to the solution. Consequently, the SCC provider attempts to get the “new” project and all of its files. But there isn’t a project 'Peck' in the SCC database because it has been renamed to Hubble. The Get operation fails and Bob ends up with a solution with a missing/unloaded project.

To fix this issue, Bob must:

1.      Check out the solution exclusively.

2.      Open the database and manually rename Hubble.csproj to Peck.csproj.

3.      Manually rename Hubble.csproj.vspscc to Peck.csproj.vspscc.

4.      Get the files locally, etc and then reload the projects into the solution.

In an ideal world, the best way to solve this problem would be to add some code to scci to preserve the history of name changes to a file until the parent project/solution is checked in or until an undo checkout occurs.

Basically, if we could remember that Peck was renamed to Hubble, after we get the old solution we could rename Hubble back to Peck. Tracking this kind of change is non trivial though. The SCCI code would have to remember changes like Peck->Hubble->Orbit->Peck->(delete)Peck, or Peck->Hubble->(delete) Hubble ->(add different) Peck, etc.

C Complex Rename Scenario (Multi-user)

Risk: Teammate’s changes cannot be merged into the main code line.

++Again, assumes that client file renames are immediately committed in the SCC database++

As in the previous scenario, Bob renames one of the projects in the telescope solution. The database version of the project file is changed from Peck.csproj to Hubble.csproj. While Bob is working on the (checked-out) source files, his co-worker Mike opens the telescope solution from source control for the first time in order to make a set of targeted bug fixes. Mike gets a version of telescope.sln that contains a reference to ‘Peck.csproj’, but in the source control database there is no such project. He ends up with a missing/unloaded project and a solution that cannot be built. Mike cannot build his enlistment and might not even be able to edit the files or to fix the bug (if the bug was in the Peck project’s project files).

Concurrently, John--a third team member--who had previously opened the telescope solution from source control and has all the files locally, attempts to Get the latest version of the solution from source control in order to incorporate any outstanding team changes into his working copy before building and checking in. However, since Peck.csproj has been renamed in the database, the SCC status for John's copy of project is ‘uncontrolled’ and the file appears as a 'pending add'.

John, who has added several files and has made major build configuration changes since checking out the solution, decides to add Peck.csproj to and check in his version of the solution. Consequently, Peck.csproj is added back to the SCC database.

Now, there are 2 project files in the database, Peck.csproj and Hubble.csproj.

A few minutes later Bob checks in his changes. The solution file now references the new project Hubble.csproj rather than Peck.csproj. Effectively, John's major changes (file additions/changed build configuration) are orphaned and will have to be, when somebody realizes that they're missing, re-integrated into the main codeline, manually and painfully.

S Summary

In the absence of reliable mechanisms for 1) rolling back and synchronizing previously committed namespace changes between a source control database and a local enlistment and; 2) disseminating namespace change notifications or commits to all project enlistees automatically, it is much safer to implicitly discourage renaming, moving, or deleting source-controlled files and projects than to complete such operations automatically and thereby enable serious scheduling setbacks in mainstream collaborative development scenarios.  Whew.  That was a mouthful.

I can only assume that the source control providers (VSS, ClearCase, PVCS, Vault, et al) are as responsible for the lack of transactionality in source control integration as SCCI in Visual Studio .NET. I speculate that the SCCI team has entertained some requests from our VSIP partners in this area sometime in the past and that somebody whose salary is much bigger than mine said, "Whoa. That sounds expensive. Let's punt."  Obviously, the second roadblock (lack of ability to 'push' namespace changes down to project enlistees) would be the sole responsibility of the source control provider.

To rename, move, or delete a source-controlled file or project in Visual Studio .NET 2002 or 2003

1.      Inform all project enlistees that you plan to make a namespace change to the project.

2.      Ask all project enlistees to check in the solution to which the file or project belongs.

3.      Rename, move, or delete the item in Visual Studio .NET.

4.      Check in your changes.

5.      Ask all project enlistees to synchronize their working copies of the solution with the database version.

For more information see Q305516.

++++++++++++++++++++++++++++

Ugh, This posting is provided "AS IS" with no warranties, and confers no rights. Microsoft kann für die Richtigkeit und Vollständigkeit der Inhalte in dieser Newsgroup keine Haftung übernehmen. Este mensaje se proporciona "como está" sin garantías de ninguna clase, y no otorga ningún derecho. Ce message est fourni en l’état, sans garantie d’aucune sorte, et ne vous confère aucun droit. Vous assumez tous les risques liés à son utilisation. Il presente posting viene fornito “così come é”, senza garanzie, e non conferisce alcun diritto.

Published 19 September 03 07:52 by KorbyP

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# AsbjornM said on September 20, 2003 5:43 AM:
You forgot one item in the summary list, which is mentioned in Q305516, do the same operation in VSS before you checkin the file. I use another approach to this: 1. Check in the file to be modified (we don't trust multiple checkouts so only one has the file anyway) 2. Exclude the file from the project 3. Move/Rename/Delete the file in vss-explorer 4. Getlatest on the file in vss-explorer 5. Include the file in vs.net This way you keep the history of the file, which is the main reason for using vss anyway. When I think of it, another possible solution could be using sharing, share the file to it's new destination, get it, and include it to the project, and then remove the orginial file. It shouldn't be so hard doing this in the scc provider either.
# Korby Parnell said on September 22, 2003 12:54 PM:
Thanks a million, Asbjorn. I forgot to mention this method for renaming or moving a file. This method preserves file history, whereas the method I proposed does not. I will mention this in a separate post to ensure that it gets the exposure it deserves. There are a few gotchas that I should point out for anybody else who might read this: 1) Whereas you can rename source-controlled files in this way, it doesn't work for project renames. 2) For C++ projects--and other reference-based project types--there is no Exclude from Project command and consequently, no Include in Project command. For such projects, you can use the Remove command to remove a file from a project temporarily, rename the file in VSS, re-add it to the project in VS.NET using Add Existing Item from Source Control, and then delete the original from disk if necessary. 3) To rename or move a source-controlled file in this way, you must perform a source control operation outside the VS.NET IDE, which is not generally recommended. Note: For VB, C#, and other directory based or reference-directory hybrid project types, before you can include the renamed file in VS.NET, you must select the project in Solution Explorer and then click the Show All Files button (three little documents), which is next to the Refresh button. Asbjorn, I have a question for you: Shouldn't there be a step #6? Delete the old file from the project in VS.NET permanently. Thanks Again.
# AsbjornM said on September 22, 2003 3:30 PM:
yes ofcourse :), i forgot that, the old file should be deleted from the project *folder*, not from the project..
# Kevin Greiner said on March 19, 2004 12:48 PM:
The 2nd method mentioned by AsbjornM (sharing), works very well for moving the same file to a different place in the same (or different) projects. I've also used the MSKB article to mentioned to rename a file. I don't think it matters which is done first.

Here is the process I used with VS.NET 2003.

1. Check in the file to be moved. I'm not sure if the parent project & solution need to be checked in as well, but it can't hurt.
2. In VS.NET, select the destination folder, then File -> Source Control -> Share menus. Navigate the VSS project folders and share the file to be moved.
3. In VS.NET, delete the original file. Because this just deletes it from the local filesystem, and the project, you'll also need to delete it using VSS Explorer to keep your project folders neat & tidy.

Leave a Comment

(required) 
(optional)
(required) 

Search

Go

This Blog

Syndication

Page view tracker