TFS消融 - 如何恢复搁置的变化(TFS Meltdown - How can I recover

2019-08-03 07:05发布

我有我的工作文件夹设置为RAM驱动器。 在夜间出现了长时间停电时,UPS跑了出去,我的机器去了。 值得庆幸的是我搁置了我的变化之前,我就回家了,并且搁置在团队资源管理器是可见的。 该变更包括项目文件,尚未被添加到源代码控制一些新的文件。

我试图恢复受影响的文件,但我得到的错误:

试图查看搁置的文件给TF10187 (或一般的,未编号), The system cannot find the file specified ,即使我可以看到他们在Pending Changes列表。

试图取消搁置在全部集合给出了与错误, incompatible changes ,我解决不了。

TFS缓存搁置本地这已经重新初始化本身,并因此失去了缓存RAM光盘上,但我希望我是错的。

任何人都可以帮助?

Answer 1:

我曾有人来找我,问同样的问题昨天,幸运的是他们有TFS项目数据库(tfs_)的备份,所以我们恢复是到另一个数据库和我戳周围,想通了(所以,如果你有一个备份,然后是的,你可以恢复所有文件)。

首先在数据库表中的所有提供一些信息。

搁置可以通过查询tbl_Workspace表,并与类型= 1(搁置),你当然也可以通过名称与工作区名列过滤器来查找所有记录来确定。

感兴趣的其他表如下:

tbl_PendingChanges(其中WorkspaceId从tbl_Workspace参考) - 哪些文件是搁置的部分

父路径和文件名的文件 - tbl_VersionedItem(通过项目Id列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类的内容和保存文件从磁盘。

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

这与2010 TFS完成。

希望这可以帮助!



Answer 2:

这里是TFS2015,它有其他模式的变化更新的响应。 下面是为txt文件写入到桌面一个C#控制台应用程序。 请务必填写CONNSTRING和shelvesetName变量。

using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.IO.Compression;

namespace RestoreTFSShelve
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            string shelvesetName = "";
            string connString = "";

            SqlConnection cn = new SqlConnection(connString);
            SqlCommand cmd = new SqlCommand(@"
SELECT c.[CreationDate], c.[Content], v.FullPath
FROM [dbo].[tbl_Content] c
INNER JOIN [dbo].tbl_FileMetadata f ON f.ResourceId = c.ResourceId
INNER JOIN [dbo].tbl_FileReference b ON f.ResourceId = b.ResourceId
INNER JOIN [dbo].[tbl_PendingChange] pc ON pc.FileId = b.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", shelvesetName);

            DataTable dt = new DataTable();
            new SqlDataAdapter(cmd).Fill(dt);

            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(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), fileName), unzippedContent);
            }
        }

        private 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();
                }
            }
        }
    }
}


Answer 3:

我有类似的事情发生在我身上了TFS 2012实例。 我的SQL查询有点不同,因为该架构改变TFS 2012年希望这可以帮助别人。

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();
    }
}
}


文章来源: TFS Meltdown - How can I recover shelved changes