2012-02-14 25 views
17

Điều này sau my previous question về TFS 2010 và khả năng tạo một thay đổi.TFS2010: Truy xuất tất cả các thay đổi được liên kết với chi nhánh (đệ quy đầy đủ)

Trước đây tôi đã sử dụng nhãn để xác định phiên bản của chương trình, nhưng vì nhãn không phải là điểm cố định kịp thời, giờ tôi đang sử dụng các nhánh.

Đây là cách hệ thống phân cấp chi nhánh trông giống như:

branch hierarchy

Như bạn có thể thấy, có hai ứng dụng khác nhau mà là chi nhánh của thân cây: APP_A (ứng dụng A) và APP_B (ứng dụng B). Cả hai đều gần giống nhau, nhưng có một số khác biệt chức năng.

Dưới đây là quá trình để tạo ra một phiên bản mới của ứng dụng (chẳng hạn phiên bản 1.3):

  1. Các Main trunk được sửa đổi (chức năng mới được bổ sung, sửa lỗi ...)
  2. Từ sửa đổi Main trunk, một chi nhánh mới được tạo ra: Main trunk 1.3
  3. APP_A chi nhánh có thể được sửa đổi, chức năng rất độc đáo của APP_A sẽ làm việc với sửa đổi v1.3
  4. APP_B chi nhánh có thể được sửa đổi, vì vậy chức năng độc đáo của APP_B sẽ làm việc với sửa đổi v1.3
  5. Main trunk 1.3 được sáp nhập vào APP_AAPP_B, vì vậy cả hai APP_AAPP_B ứng dụng nhận những sửa đổi của Main trunk
  6. Từ sửa đổi APP_A chi nhánh , một chi nhánh mới được tạo ra: APP_A_1.3
  7. Từ sửa đổi APP_B chi nhánh, một chi nhánh mới được tạo ra: APP_B_1.3

Mục tiêu của tôi là có thể tạo ra một thay đổi giữa APP_A_1.3APP_A_1.2.

Bằng danh sách thay đổi, tôi có nghĩa là danh sách các WorkItems. Mỗi changeset được đăng ký được liên kết với một hoặc nhiều WorkItem (ví dụ như một mục Bug). Tôi muốn có thể nhận danh sách tất cả các workitems được liên kết với một changeset đã ảnh hưởng đến APP_A_1.3: những thay đổi đó có thể đến từ Main trunk (bước 1 ở trên), APP_A branch (bước 3 ở trên) hoặc thậm chí APP_A_1.3 chi nhánh chính nó (nếu hotfix được đăng ký sau khi chi nhánh đã được tạo).

Để có được danh sách này của workitems, tôi đã cố gắng để có được danh sách của tất cả các changesets được "liên kết" để APP_A_1.2 ("liên kết" = mã đã được kiểm tra-in trong changeset tại là trên cành APP_A_1.2) và danh sách tất cả các thay đổi được "liên kết" thành APP_A_1.3.

Sau đó, tôi sẽ có thể biết những thay đổi nào được "liên kết" thành APP_A_1.3 và không được "liên kết" với APP_A_1.2.Từ tập hợp con của changesets, tôi sẽ nhận được tất cả WorkItems liên quan và do đó thay đổi của tôi.

Đây là vấn đề của tôi: làm thế nào tôi có thể nhận được danh sách ALL changesets được "liên kết" với một chi nhánh được chỉ định? Tôi đang sử dụng API TFS 2010 cho mã C#.

Các đầu vào của chương trình của tôi (mà có thể lấy tất cả các changesets cho một chi nhánh nào đó) sẽ là tên của chi nhánh (nói APP_A_1.2), và đầu ra sẽ là danh sách các changesets sau:

  • changesets áp dụng trên APP_A_1.2 chi nhánh tự
  • changesets áp dụng trên APP_A chi nhánh trước khi APP_A_1.2 đã được tạo ra
  • changesets áp dụng trên Main trunk 1.2 chi nhánh trước khi nó đã được sáp nhập vào APP_A
  • changesets áp dụng trên Main trunk chi nhánh trước khi Main trunk 1.2 đã được tạo ra

Tôi đã viết những mẩu mã sau đây để có được tất cả những changesets:

// Gets the list of all changesets ID from APP_A_1.2 branch 
var branch1ChangeSets = myVersionControlServer.QueryHistory(
    "$/PATH/APP_A_1.2/", 
    VersionSpec.Latest, 
    0, 
    RecursionType.Full, 
    null, 
    null, 
    null, 
    int.MaxValue, 
    false, 
    false).OfType<Changeset>().Select(z => z.ChangesetId).ToList(); 

Thậm chí nếu RecursionType.Full được quy định, các mã trên chỉ trả về các thay đổi đã được đăng ký trên chính chi nhánh APP_A_1.2. Điều này giống với lệnh "History" trên khung nhìn Source Code Explorer trong Visual Studio.

Sau đó, tôi đã thử các đoạn mã sau:

// Gets the list of all changesets ID from APP_A_1.2 branch 
var branch1MergedChangeSets = myVersionControlServer.QueryMerges(
    null, 
    null, 
    "$/PATH/APP_A_1.2/", 
    VersionSpec.Latest, 
    null, 
    null, 
    RecursionType.Full).Select(z => z.SourceVersion).ToList(); 

này trả changesets đó đã được kiểm tra-in trên APP_A_1.2 chi nhánh + những người được cheked-in trên APP_A chi nhánh trước khi APP_A_1.2 đã được tạo ra. Tốt hơn nhiều, nhưng không đủ. Tôi không thể tìm cách làm cho phép đệ quy hoạt động với các nhánh "ở trên" APP_A (Main trunk trong trường hợp của tôi) ...

Có ai có ý tưởng không?

Ngoài ra, bất kỳ ý tưởng tốt hơn để có được những changelog giữa hai chi nhánh đều được chào đón ... Thx.

+1

Câu hỏi hay! ATM bạn đang mắc kẹt với cách truy xuất chính xác các Thay đổi. Một khi bạn sẽ nhận được chúng, hãy xem xét bài viết tuyệt vời này bởi B.Hodges, điều đó sẽ giúp bạn tương quan một danh sách các Thay đổi với một danh sách các mục công việc: http://blogs.msdn.com/b/buckh/archive/2012 /02/01/listing-the-work-items-associated-with-changesets-for-a-path.aspx – pantelif

Trả lời

2

Cuối cùng tôi đã đưa ra một giải pháp đơn giản. Tôi không hoàn toàn hài lòng với nó vì nó thực sự trông giống như một thuật toán brute-force, nhưng ít nhất nó hoạt động.

Những gì tôi làm là:

1) Lấy danh sách các mỗi changeset được áp dụng trên rất rễ của chi nhánh TFS tôi (tức là "con đường cha mẹ" của Main Trunk):

var allChangesets = vcs.QueryHistory(
    "MySourcePath", 
    VersionSpec.Latest, 
    0, 
    RecursionType.Full, 
    null, 
    firstPossibleChangeset, 
    VersionSpec.Latest, 
    int.MaxValue, 
    true, 
    false).OfType<Changeset>().ToList(); 

2) Đối với mỗi lần thay đổi được truy xuất, tôi gọi số TrackMerges để xem liệu tác nhân thay đổi có ảnh hưởng đến một số nhánh của tôi hay không. TrackMerges có thể cho tôi biết nếu một changeset được chỉ định được áp dụng trên các nhánh mà tôi chỉ định làm tham số của hàm (nó sẽ trả về ID thay đổi đích trên các nhánh này). Nếu một changeset được áp dụng trên nhánh đích (trong trường hợp của tôi là APP_A_1.3) và không nằm trong nhánh nguồn (APP_A_1.2), thì điều đó có nghĩa là nó là một cái gì đó mới trên chi nhánh APP_A_1.3 của tôi.

List<int> newChangesets = new List<int>(); 
foreach (var z in allChangesets.Where(y => y.ChangesetId > firstPossibleChangesetId)) 
{ 
    var zz = vcs.TrackMerges(
     new int[] { z.ChangesetId }, 
     new ItemIdentifier("THE TRUNK PATH"), // The root of all branches 
     new ItemIdentifier[] { new ItemIdentifier(fromBranchPath), new ItemIdentifier(toBranchPath) }, 
     null); 

    var targetInFromBranch = zz.Where(t => t.TargetItem.Item == fromBranchPath).FirstOrDefault(); 
    var targetInToBranch = zz.Where(t => t.TargetItem.Item == toBranchPath).FirstOrDefault(); 

    if (targetInToBranch != null && targetInFromBranch == null) 
    { 
     // Then the changeset is only applied on the ToBranch 
     newChangesets.Add(z.ChangesetId); 
    } 
} 

3) Bây giờ nó rất đơn giản để có được changelog của tôi (danh sách các workitems) từ danh sách các "changesets mới":

// Now, gets associated work items! 
Dictionary<int, WorkItem> dico = new Dictionary<int, WorkItem>(); 
foreach (int changesetId in newChangesets) 
{ 
    foreach (WorkItem zz in vcs.GetChangeset(changesetId).WorkItems) 
    { 
     this.AddWorkItemToDicRecursive(wis, dico, zz); 
    } 
} 

private void AddWorkItemToDicRecursive(WorkItemStore wis, Dictionary<int, WorkItem> dico, WorkItem workItem) 
{ 
    if (!dico.ContainsKey(workItem.Id)) 
    { 
     dico.Add(workItem.Id, workItem); 

     foreach (WorkItemLink associatedItem in workItem.WorkItemLinks) 
     { 
      this.AddWorkItemToDicRecursive(wis, dico, wis.GetWorkItem(associatedItem.TargetId)); 
     } 
    } 
} 

Tôi không nghĩ rằng đó là cách tiếp cận tốt nhất có thể, nhưng nó hoạt động tốt và vẫn đơn giản. Ngoài ra, tôi đã không phải hardcode bất cứ điều gì (tên chi nhánh/hệ thống phân cấp) vì vậy nó không phải là quá xấu IMO. Hy vọng nó sẽ giúp ai đó.

3

đầu tiên cho tôi đầu tiên hỏi một câu hỏi. Ở đầu bài đăng bạn viết: "Mục tiêu của tôi là có thể tạo ra thay đổi giữa APP_A_1.3 và APP_A_1.2."

nhưng sau đó khi bạn viết những gì thay đổi đặc biệt bạn đang tìm kiếm bạn liệt kê: changesets áp dụng trên nhánh APP_A_1.2 tự changesets áp dụng trên nhánh APP_A trước APP_A_1.2 đã được tạo ra changesets áp dụng trên thân cây chính 1.2 chi nhánh trước khi nó đã được hợp nhất vào APP_A các thay đổi được áp dụng trên nhánh chính trước khi Chính trunk 1.2 được tạo ra

Đây không phải là danh sách hợp lệ vì nó sẽ cung cấp cho bạn tất cả các thay đổi đã đóng góp cho APP_A_1.3, APP_A_1.2, 1.1 v.v. đến đầu kho.

Tôi không thể kiểm tra phương pháp tiếp cận của mình ngay bây giờ, nhưng đây là những gì tôi sẽ làm: - QueryHistory để nhận tất cả các thay đổi được kiểm tra trực tiếp vào chi nhánh 1.3 - sử dụng QueryMergesExtended để thực hiện theo các lần hợp nhất vào nhánh này. QueryMergesExtended (http://msdn.microsoft.com/en-us/library/ff736485.aspx) đã được thêm vào trong TFS 2010 đặc biệt để có hiệu quả hơn nhiều và mạnh mẽ hơn QueryMerges và QueryMergesWithDetails, để hỗ trợ các công cụ trực quan hóa chi nhánh - afaik bạn không cần phải chỉ định tùy chọn FollowRenames trong QueryMergesExtended vì bạn truy vấn kết hợp trên thư mục gốc của chi nhánh - khi bạn nhận danh sách các thay đổi nguồn (từ APP_A), bạn cần phải kiểm tra từng changeset để xem nó có chứa thay đổi hợp nhất hay không. Nếu vậy, bạn cần truy vấn các kết hợp trên app_a cho các changesets đó. Làm như vậy đệ quy cho đến khi bạn đi bộ toàn bộ hệ thống phân cấp chi nhánh. Trên các chủ đề phụ, bạn có thể xem sau tại QueryMergeRelationships (http://msdn.microsoft.com/en-us/library/microsoft.teamfoundation.versioncontrol.client.versioncontrolserver.querymergerelationships.aspx) cung cấp cho bạn danh sách đối tượng nhánh được giới thiệu trong tfs 2010 (đây là những gì xảy ra khi trong Source Control Explorer bạn chọn thư mục và nhấp Convert to branch). Tuy nhiên, nếu bạn có thể khám phá chi nhánh của bạn theo cách khác (mã hóa chúng) hơn là không cần thiết.

Hy vọng điều này sẽ hữu ích!

+0

Xin chào, tôi không hiểu tại sao danh sách tôi đề cập sẽ cho tôi những thay đổi được áp dụng trên 'APP_A_1.3 '. Tôi đồng ý với 'APP_A_1.2' và' APP_A_1.1' (đây là những gì tôi mong đợi), nhưng tôi không thấy làm thế nào một changeset chỉ áp dụng trên 'APP_A_1.3' sẽ xuất hiện trong một trong các danh sách. Ngoài ra, tôi đã thử nghiệm 'QueryMergesExtended' nhưng nó không trả về đệ quy tất cả các thay đổi (ví dụ, được áp dụng trên' APP_A_1.3', nó trả về các thay đổi từ 'APP_A' nhưng không phải từ' Main Trunk'). – ken2k

+0

Tôi thực sự có thể sử dụng 'QueryMergeRelationships' để khám phá các nhánh của tôi sau đó gọi nhiều lần' QueryMergesExtended', điều này sẽ hoạt động. Tôi cũng đã tìm thấy một cách với 'TrackMerges', tôi sẽ đăng nó như một câu trả lời sớm. Tôi upvote câu trả lời của bạn gây ra nó hữu ích, cảm ơn. – ken2k

1

Vâng, cũng làm việc về vấn đề này. Tôi đã tìm thấy một dự án codeplex giải quyết nó, khi bạn đang tìm các nhãn khác nhau.

Xem nếu điều này giúp: http://tfslabeldiff.codeplex.com/SourceControl/changeset/view/7075#158224

Tôi khá ngạc nhiên khó khăn thế nào điều này là để tìm kiếm, nhưng tài liệu cho TFS thiếu lúc tốt nhất. Có vẻ như nó phải rõ ràng!

+0

Hi Sharon, tôi nghĩ rằng những gì bạn đang đề xuất không phải là đi qua lịch sử chi nhánh, nói cách khác nó sẽ không truy xuất đệ quy các changesets giữa các nhánh khác nhau. – pantelif

Các vấn đề liên quan