【问题标题】:Overwritten changes in Git with Azure DevOps使用 Azure DevOps 覆盖 Git 中的更改
【发布时间】:2021-10-11 08:21:42
【问题描述】:

我的团队在 Azure DevOps 中遇到了 Git 问题。他们使用 SSIS 包,开发是通过 Visual Studio (VS) 完成的。他们还通过 VS 进行提交(在我这边,我使用 Git Bash)。它们实现的更改经常在分支合并期间被覆盖,这显然是一种非常危险的行为: 我对 SSIS 一点也不熟悉,我根本不理解这种行为。我是 R 和 Python 用户,据我所知,我只遇到过 Git 冲突。这种行为的原因是什么?如果我们不指定它(通过 git 分支),怎么可能创建分支?是 VS 和 SSIS 的结合,让 Git 的版本控制变得不可预测?他们是否应该使用 TFVC 而不是 Git,因为他们知道 Microsoft 不推荐它(顺便说一句,为什么?它没有给出明确的解释)

【问题讨论】:

    标签: git visual-studio visual-studio-code azure-devops ssis


    【解决方案1】:

    不是 git 专家,但我对 SSIS 有所了解。

    SSIS 包是集成服务对象的 XML 序列化。不幸的是,它还包含演示数据以支持设计体验的画布布局。

    假设以下定义了一个截断表的 SSIS 包,并且您将其签入。

    <SSIS>
        <TASKS>
            <EXECUTE_SQL_TASK COMMAND="TRUNCATE TABLE dbo.T1;"/>
        </TASKS>
        <LAYOUT>
            <EXECUTE_SQL_TASK X="100" Y="200" HEIGHT="300" WIDTH="50" />
        </LAYOUT>
    </SSIS>
    

    下一位开发人员打开包并调整任务的大小。不会发生语义变化,但包的序列化版本会发生变化。

    <SSIS>
        <TASKS>
            <EXECUTE_SQL_TASK COMMAND="TRUNCATE TABLE dbo.T1;"/>
        </TASKS>
        <LAYOUT>
            <EXECUTE_SQL_TASK X="50" Y="200" HEIGHT="300" WIDTH="150" />
        </LAYOUT>
    </SSIS>
    

    同时,开发人员 #2 对包进行结构更改,因此他们创建了原始包的这种表示

    <SSIS>
        <TASKS>
            <EXECUTE_SQL_TASK COMMAND="TRUNCATE TABLE dbo.T2;"/>
            <EXECUTE_SQL_TASK COMMAND="TRUNCATE TABLE dbo.T1;"/>
        </TASKS>
        <LAYOUT>
            <EXECUTE_SQL_TASK X="100" Y="200" HEIGHT="300" WIDTH="50" />
        </LAYOUT>
    </SSIS>
    

    最后一个签入更改的人将遇到合并冲突。没有版本控制工具可以优雅地处理 XML 合并(至少 rcs、cvs、svn、SourceSafe、TFS、git 不会)

    在精神上,是的,您可以处理合并示例 XML,但表示 SSIS 的实际 XML 非常复杂。在深入研究 SSIS 15 年多之后,我可能能够手动修改 XML 以解决合并冲突,即使那样它也将高度依赖于版本(仅限 2012+请)。

    在较小程度上,同样的问题发生在同样基于 XML 的 .NET 项目 (MyProject.csproj) 中。如果您添加了一个新类,而另一个开发人员也添加了一个新类,那么如果您同时签入您的项目,您可能会遇到合并冲突。

    我该怎么办

    以下是我鼓励的一组良好做法

    沟通

    开发人员 A 将 packageSales 添加到项目中,开发人员 B 将 packageCustomer 添加到项目中,并且都将更改提交到源代码管理,其中一个可能会“丢失”他们的包,因为 XML 合并不会发生。该包仍在文件系统中,只是Visual Studio使用的.dtproj文件合并的已知包列表

    <PACKAGES>
        <PACKAGE Name="packageSales.dtsx"/>
    </PACKAGES>
    

    当它真的应该“合并”为时

    <PACKAGES>
        <PACKAGE Name="packageSales.dtsx"/>
        <PACKAGE Name="packageCustomer.dtsx"/>
    </PACKAGES>
    

    具有多个并发 SSIS 开发人员的大型项目,指定一个人负责将包添加到项目中。让他们添加一个空白包并将更新的包和项目文件提交到版本控制,然后让其他开发人员知道从源代码控制获取最新版本。

    将 SSIS 包视为二进制对象

    将 SSIS 包视为二进制对象会更好。由于“噪音”太多,尝试生成diff 来识别版本之间的变化没有任何理由或价值。每次保存时,即使您没有对包进行任何更改,也会始终更新两个字段:VersionNumber 和 VersionGuid(名称近似)

    我什至在各种版本控制系统中将 SSIS 标记为二进制对象,因为合并包几乎可以保证是 XML 包方言的损坏表示。

    越小越好

    由于我们已经将包视为二进制对象,并且系统生成的差异文件无助于识别发生了什么变化,因此创建专注于业务流程的 SSIS 包。将运行 N 个任务的“加载数据”替换为“加载销售”、“加载客户”,也许“加载数据”仍然存在,但它只是协调销售和客户包的运行。因为我们正在制作更多包但范围更小,这允许您将工作分配给多个开发人员,但不会有包中合并冲突的风险。

    重新思考你的方法

    取决于您的开发的可重复性,虽然表示实际 SSIS 包的 XML 过于复杂,但 Biml 不是。 Biml 是一种描述表和包的领域特定语言。它的美妙之处在于它足够小,可以准确地描述您在 SSIS 中可以做的所有事情,但没有实际 XML 中的所有繁琐内容。

    这是一个用 Biml 表示的 hello world 级 SSIS 包

    <Biml xmlns="http://schemas.varigence.com/biml.xsd">
        <Packages>
            <Package Name="SimpleBimlPackage" />
        </Packages>
    </Biml>
    

    通过BimlExpress 上的免费 Visual Studio 添加运行它,它将创建一个没有任何内容的 SSIS 包。

    以下是 Biml 的重要部分,它描述了具有两个 OLEDB 连接管理器的 SSIS 包。它有一个名为RowCountNew 的变量。它有一个数据流,从 Adventureworks Sales.Currency 表中获取数据,计算管道中的行数,然后将其放入名为 RAW.SalesCurrency 的表中,并将 Name 的原始列映射到 CurrencyName 的目标

    <Biml xmlns="http://schemas.varigence.com/biml.xsd">
        <Connections>
        <OleDbConnection 
            ConnectionString="Data Source=localhost\dev2012;Initial Catalog=AdventureWorks2012;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;" Name="AdventureWorks"/>
        <OleDbConnection 
            ConnectionString="Data Source=localhost\dev2012;Initial Catalog=TypeMoreClickLess;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;" Name="TypeMoreClickLessLocal"/>
        </Connections>
        <Packages>
            <PackageName="HelloDataFlow"
                <Variables>
                    <Variable Name="RowCountNew" DataType="Int32" Namespace="User">0</Variable>
                </Variables>
                <Tasks>
                <Dataflow Name="DFT Basic Dataflow">
                    <Transformations>
                        <OleDbSource Name="OLE_SRC Demo"
                            ConnectionName="AdventureWorks" >
                            <DirectInput>
                            SELECT SC.CurrencyCode, SC.Name
                            FROM Sales.Currency AS SC;
                            </DirectInput>
                        </OleDbSource>
                        <RowCount Name="CNT New"
                            VariableName="User.RowCountNew"/>
                        <OleDbDestination
                            Name="OLE_DST RAW_SalesCurrency"
                            ConnectionName="TypeMoreClickLessLocal"
                            KeepIdentity="false"
                            TableLock="true"
                            UseFastLoadIfAvailable="true"
                            KeepNulls="true"
                        >
                            <ExternalTableOutput Table="[RAW].[SalesCurrency]"/>
                            <Columns>
                                <Column SourceColumn="Name" TargetColumn="CurrencyName" />
                            </Columns>
                        </OleDbDestination>
                    </Transformations>
                </Dataflow>
                </Tasks>
            </Package>
        </Packages>
    </Biml>    
    

    这对开发人员来说更容易理解。并且比 SSIS 所涉及的所有鼠标点击更容易实现自动化。

    另外,您可以将现有的 SSIS 包逆向工程为 Biml。然后,这可以使手动识别两组 SSIS 程序包之间发生的变化的前景变得不那么艰巨,而只是凡人可以处理的事情。

    【讨论】:

      猜你喜欢
      • 2013-03-24
      • 2012-02-11
      • 2023-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-27
      • 2012-12-25
      • 2016-12-11
      相关资源
      最近更新 更多