Renaming branches in TFS 2010

With the switch over to slot mode in TFS 2010 renaming branch roots can lead to situations where the next merge from the renamed branch to related branches will generate more than necessary conflicts. The reason for this is that when you rename the root of a branch, the source of the rename is considered out of scope of the merge - hence we do not consider the merge history of the source name - so items where the content differs between the source and target since the last merge will be baseless merged. Below is an example which demonstrates this behavior:

REM CREATE A FOLDER WITH 2 FILES

C:\temp_dd\ws\test4>md source

C:\temp_dd\ws\test4>echo 1 > source\1.txt

C:\temp_dd\ws\test4>echo 2 > source\2.txt

C:\temp_dd\ws\test4>tf add source /r
source

source:
1.txt
2.txt

C:\temp_dd\ws\test4>tf checkin /i
Checking in add: source

source:
Checking in add: 1.txt
Checking in add: 2.txt

Changeset #14 checked in.

REM BRANCH THE FOLDER

C:\temp_dd\ws\test4>tf branch source target
target

target:
1.txt
2.txt

C:\temp_dd\ws\test4>tf checkin /i
Checking in branch: target

target:
Checking in branch: 1.txt
Checking in branch: 2.txt

Changeset #15 checked in.

C:\temp_dd\ws\test4>tf edit target\1.txt
target:
1.txt

REM EDIT A FILE IN THE TARGET BRANCH

C:\temp_dd\ws\test4>echo "line added in target" > target\1.txt

REM EDIT A FILE IN THE SOURCE BRANCH

C:\temp_dd\ws\test4>tf edit source\1.txt
source:
1.txt

C:\temp_dd\ws\test4>echo "line added in source" > source\1.txt

C:\temp_dd\ws\test4>tf checkin /i
source:
Checking in edit: 1.txt

target:
Checking in edit: 1.txt

Changeset #16 checked in.

REM MERGE THE EDIT FROM THE SOURCE BRANCH TO THE TARGET BRANCH. RESOLVE THE CONFLICT BY KEEPING BOTH LINES

C:\temp_dd\ws\test4>tf merge source target /r
Conflict (merge, edit): $/proj/test4/source/1.txt;C16~C16 -> $/proj/test4/target/1.txt;C16

C:\temp_dd\ws\test4\target\1.txt: 0 local, 0 server, 0 both, and 1 conflicting
Resolved C:\temp_dd\ws\test4\target\1.txt as AutoMerge

C:\temp_dd\ws\test4>tf checkin /i
target:
Checking in merge, edit: 1.txt

Changeset #17 checked in.

REM RENAME THE SOURCE BRANCH

C:\temp_dd\ws\test4>tf rename source source2
source2

source2:
1.txt
2.txt

C:\temp_dd\ws\test4>tf checkin /i
Checking in rename: source2

Changeset #18 checked in.

REM MERGE AGAIN FROM THE RENAMED BRANCH TO THE TARGET BRANCH

C:\temp_dd\ws\test4>tf merge source2 target /r
Conflict (merge, edit): $/proj/test4/source2/1.txt;C18~C18 -> $/proj/test4/target/1.txt;C17
merge: $/proj/test4/source2;C18~C18 -> $/proj/test4/target;C15
merge: $/proj/test4/source2/2.txt;C18~C18 -> $/proj/test4/target/2.txt;C15

As you can see source2\1.txt shows up as a merge-edit conflict, however source2\2.txt just has a merge on it (to update merge history) - since the content between the last merged versions are the same. In this case the conflict auto-merges well, but it might not in certain cases.

So my recommendations for this case:

1. Avoid renaming branches - a cleaner solution would be to, at the right point in your release merge all changes to a parent branch and then re-branch to create a new branch hierarchy.

Or for the brave of heart :) 

2. You will need to time the rename of your branch, to a point in your release where you can merge to all related branches. The steps to follow are:

a. Merge all changes from the branch you wish to rename to all related branches, check in these merges.

b. Rename the branch and checkin the rename.

c. Re-merge to all related branches

d. Look at any items which have a merge, undelete from step c). Undo the merge on them and re-merge using /discard. e.g. if $/proj/target/1.txt has a merge, undelete on it

tf undo $/proj/target/1.txt

tf merge /discard $/proj/source-rename/1.txt $/proj/target/1.txt

e. For any remaining conflicts - resolve them as KeepTarget. The reason this is safe to do, is that you have already merged all changes to the target branch in step a)

 Chandru