TFS Meltdown - 如何恢复搁置的变更

时间:2012-11-28 11:01:48

标签: visual-studio-2010 tfs2010 unshelve shelveset

我将我的工作文件夹设置为RAM驱动器。在夜间有一个长时间停电,UPS用完了,我的机器坏了。值得庆幸的是,在我回家之前,我搁置了我的更改,并且在团队浏览器中可以看到搁置集。变更集包括项目文件和一些尚未添加到源代码管理中的新文件。

我正在尝试恢复受影响的文件但收到错误:

尝试查看搁​​置的文件会提供TF10187(或一般的,未编号的)The system cannot find the file specified,即使我可以在Pending Changes列表中看到它们。

尝试完全取消隐藏该集合会产生与我无法解决的incompatible changes相关的错误。

猜测 TFS在RAM光盘上本地缓存了shelveset,后来自己重新初始化并因此丢失了缓存,但我希望我错了

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:6)

我昨天有人来找我并问同样的问题,幸运的是他们有TFS项目数据库(tfs_)的备份,所以我们将其恢复到另一个数据库,然后我就把它弄清楚了(所以,如果你有的话)然后是,您可以恢复所有文件。

首先,关于数据库中表格的一些信息。

可以通过查询tbl_Workspace表并查找Type = 1(Shelveset)的所有记录来识别Shelveset,您当然也可以使用WorkspaceName列按名称进行过滤。

其他感兴趣的表格是:

tbl_PendingChanges(从tbl_Workspace引用WorkspaceId) - 哪些文件是ShelveSet的一部分

tbl_VersionedItem(通过ItemId列链接到tbl_PendingChanges) - 父路径和文件名

tbl_Content(通过FileId链接到PendingChanges) - 这是您的文件内容作为压缩(gzip)数据存储的位置

现在解决方案;以下查询可以显示您的文件:

SELECT c.[CreationDate], c.[Content], vi.[ChildItem], vi.ParentPath
FROM [dbo].[tbl_Content] c 
INNER JOIN [dbo].[tbl_PendingChange] pc ON pc.FileId = c.FileId
INNER JOIN [dbo].[tbl_Workspace] w ON w.WorkspaceId = pc.WorkspaceId
INNER JOIN [dbo].[tbl_VersionedItem] vi ON vi.ItemId = pc.ItemId
WHERE w.WorkspaceName = '<YOUR SHELVESET NAME>'

我写了一些代码来从SQL中获取数据然后使用GZipStream类解压缩内容并将文件保存到磁盘。

一个星期的工作又回来了一个小时左右。

这是通过TFS 2010完成的。

希望这有帮助!

答案 1 :(得分:3)

以下是TFS2015的更新响应,其中包含另一个架构更改。下面是一个用于将txt文件写入Desktop的C#Console应用程序。确保填写connString和shelvesetName变量。

    private void timer1_Tick(object sender, EventArgs e)
    {

       progressBar1.Increment(1);

       Dim Length As Integer = axWindowsMediaPlayer1.currentMedia.duration
       Dim Current As Integer = axWindowsMediaPlayer1.Ctlcontrols.currentPosition;

       progressBar1.Value = Current
       progressBar1.Maximum = Length

       if progressBar1.Value = 100 then
           progressBar1.Value = 0
    }

    private void progressBar1_Click(object sender, EventArgs e)
    {

    }

答案 2 :(得分:2)

我在TFS 2012实例中遇到了类似的事情。自从TFS 2012的架构发生变化以来,我的SQL查询有点不同。希望这有助于某人。

SELECT c.[CreationDate], c.[Content], v.FullPath
FROM [dbo].[tbl_Content] c 
INNER JOIN [dbo].[tbl_File] f ON f.ResourceId = c.ResourceId
INNER JOIN [dbo].[tbl_PendingChange] pc ON pc.FileId = f.FileId--c.FileId
INNER JOIN [dbo].[tbl_Workspace] w ON w.WorkspaceId = pc.WorkspaceId
INNER JOIN [dbo].[tbl_Version] v ON v.ItemId = pc.ItemId AND v.VersionTo = 2147483647
WHERE w.WorkspaceName = @ShelvesetName

2147483647似乎是2 ^ 32 - 1我认为可能代表TFS 2012中的“最新”。然后我还编写了一个C#小部件来解压缩Gzip编码的流并使用正确的文件名将其转储到磁盘。我不保留等级制度。

string cnstring = string.Format("Server={0};Database={1};Trusted_Connection=True;", txtDbInstance.Text, txtDbName.Text);
SqlConnection cn = new SqlConnection(cnstring);
SqlCommand cmd = new SqlCommand(@"
SELECT c.[CreationDate], c.[Content], v.FullPath
FROM [dbo].[tbl_Content] c 
INNER JOIN [dbo].[tbl_File] f ON f.ResourceId = c.ResourceId
INNER JOIN [dbo].[tbl_PendingChange] pc ON pc.FileId = f.FileId--c.FileId
INNER JOIN [dbo].[tbl_Workspace] w ON w.WorkspaceId = pc.WorkspaceId
INNER JOIN [dbo].[tbl_Version] v ON v.ItemId = pc.ItemId AND v.VersionTo = 2147483647
WHERE w.WorkspaceName = @ShelvesetName", cn);

cmd.Parameters.AddWithValue("@ShelvesetName", txtShelvesetName.Text);

DataTable dt = new DataTable();
new SqlDataAdapter(cmd).Fill(dt);
listBox1.DisplayMember = "FullPath";
listBox1.ValueMember = "FullPath";
listBox1.DataSource = dt;

if(!Directory.Exists(txtOutputLocation.Text)) { Directory.CreateDirectory(txtOutputLocation.Text); }
foreach (DataRow row in dt.Rows)
{
    string[] arrFilePath = row[2].ToString().Split('\\');
    string fileName = arrFilePath[arrFilePath.Length - 2];
    byte[] unzippedContent = Decompress((byte[])row[1]);
    File.WriteAllBytes(Path.Combine(txtOutputLocation.Text, fileName), unzippedContent);
}
}

    static byte[] Decompress(byte[] gzip)
    {
using(GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
    const int size = 4096;
    byte[] buffer = new byte[size];
    using(MemoryStream memory = new MemoryStream())
    {
        int count = 0;
        do
        {
    count = stream.Read(buffer, 0, size);
    if(count > 0)
    {
        memory.Write(buffer, 0, count);
    }
        }
        while(count > 0);
        return memory.ToArray();
    }
}
}