Where did I come from?

 

One of the great questions of life and source control systems.

 

Today I needed to be able to look at the merge history of a file and figure out from where it was merged.  I found it to be more difficult then I expected - so I thought I'd blog it.

 

Consider a branch tree that looks like this:

 

main

  |

  +--team1

  |    |

  |    +--dev1a

  |    |

  |    +--dev1b

  |

  +--team2

       |

       +--dev2a

       |

       +--dev2b

  

Described in words – there exists a main branch from which there are two child branches, team1 and team2.  Team1 has two child branches, dev1a and dev1b, and Team2 has two child branches, dev2a and dev2b.

 

To make this concrete – this is the output of the branches command:

 

> tf branches $/teamproject/team1

$/teamproject/main

>>      $/teamproject/team1   Branched from version 3 <<

                $/teamproject/devteams/dev1a  Branched from version 31

                $/teamproject/devteams/dev1b  Branched from version 31

        $/teamproject/team2   Branched from version 3

                $/teamproject/devteams/dev2a  Branched from version 31

                $/teamproject/devteams/dev2b  Branched from version 31

 

So when I do something like:

 

> tf merge $/teamproject/devteams/dev1a $/teamproject/team1 /r

merge, edit: $/teamproject/devteams/dev1a/foo2.cs;C32~C33 -> $/teamproject/team1/foo2.cs;C31

 

This was then submitted as change 34.

 

Let’s pretend a few weeks have passed and we forget what we merged in change 34.  I’m just trying to remember if I merged dev1a or dev1b back to team1.

 

Let’s try and find out.

 

tf merges $/teamproject/team1/foo2.cs

Changeset Merged in Changeset Author                           Date

--------- ------------------- -------------------------------- ----------

      23*                  31 rhorvick                         2/2/2006

      26                   31 rhorvick                         2/2/2006

      32*                  31 rhorvick                         2/2/2006

      33                   34 rhorvick                         2/2/2006

 

Hmmm – not exactly what I wanted.  But I can see that changeset 34 merged changeset 33 – so let’s look in there:

 

> tf changeset /i 33

Changeset: 33

User: rhorvick

Date: Thursday, February 02, 2006 3:42:21 PM

 

Comment:

 

Items:

  edit $/teamproject/devteams/dev1a/foo2.cs

 

Ok – so it was dev1a that I merged.  Good enough.

 

But it won’t always be as clear…

 

What happens if you made changes to both dev1a and dev1b in a single changeset and then merged only one of them back (since you can’t merge both in a single changeset) …

 

Look at our command output now:

 

>tf merges $/teamproject/team1/foo2.cs

Changeset Merged in Changeset Author                           Date

--------- ------------------- -------------------------------- ----------

      23*                  31 rhorvick                         2/2/2006

      26                   31 rhorvick                         2/2/2006

      32*                  31 rhorvick                         2/2/2006

      33                   34 rhorvick                         2/2/2006

      35*                  36 rhorvick                         2/2/2006

 

>tf changeset /i 35

Changeset: 35

User: rhorvick

Date: Thursday, February 02, 2006 3:53:21 PM

 

Comment:

 

Items:

  edit $/teamproject/devteams/dev1a/foo2.cs

  edit $/teamproject/devteams/dev1b/foo2.cs

 

Not as clear this time.  There are two possible merge contributors here – either dev1a and dev1b could have merged.  So which was it?  Do you know?  No – you don’t.  You don’t have enough information yet.

 

To figure it out we need to look at the merge history for each  potential contributor.

 

Query each one to see if they participated in changeset 36…

 

>tf merges $/orcas/devteams/dev1a/foo2.cs

Changeset Merged in Changeset Author                           Date

--------- ------------------- -------------------------------- ----------

      31*                  32 rhorvick                         2/2/2006

      34                   33 rhorvick                         2/2/2006

      36                   35 rhorvick                         2/2/2006

 

>tf merges $/orcas/devteams/dev1b/foo2.cs

Changeset Merged in Changeset Author                           Date

--------- ------------------- -------------------------------- ----------

      31*                  32 rhorvick                         2/2/2006

 

You can see that only one of them contributed to changeset 36 and therefore that is the one which was merged.

 

So to figure this all out you need to:

 

1)       query the branch history to see what branches could be contributing to a merge

2)       query the merge history to see what changesets could have contributed.

3)       query the merge history for each item with multiple potential contributors until you find the right one

4)       repeat for each file with multiple potential contributors

 

I don’t like how many steps this took.  And since the client doesn’t make it much easier I wrote a tool to automate this.

 

In my next post we’ll start looking at that.