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.
Comments
- Anonymous
September 19, 2003
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 project3. Move/Rename/Delete the file in vss-explorer4. Getlatest on the file in vss-explorer5. Include the file in vs.netThis 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. - Anonymous
September 22, 2003
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. - Anonymous
September 22, 2003
yes ofcourse :), i forgot that, the old file should be deleted from the project folder, not from the project.. - Anonymous
March 19, 2004
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.