TFS branches support

601 views
Skip to first unread message

Ivan Danilov

unread,
Jul 20, 2011, 11:24:59 AM7/20/11
to git-t...@googlegroups.com
The task is to integrate TFS branches into git repository as git branches.

My initial vision of the process is to have some command like git tfs branch add BranchName $/ProjName/BranchPath resulting in next things:
  1. Determining the changeset ID that was branched to this path
  2. Creating git branch at this point with name like tfs/<id>/BranchName
  3. Setting some configuration params so that git-tfs can fetch updates from this branch in the future
  4. [optional] Fetching full history of the branch into git branch created at step 2
Also it would require modifying bootstrap command so that it will find such git branches and setup them automatically.

Steps 2-4 seems pretty clear. Anyone knows how to implement 1st one? Or maybe there are alternative ideas how to implement this?

Ivan Danilov

unread,
Jul 21, 2011, 12:01:41 AM7/21/11
to git-t...@googlegroups.com
Well, I did some test-app for analyzing branch structure in TFS and it seems to work (at least for TFS2010 that I had access to). Find sample code attached.
As a result it gives you hierarchy similar to the one you see when open properties of the folder in the TeamExplorer and select Branches tab. Except that TeamExplorer shows you only changeset number where branched item was changed last time and this code shows you also first changeset number of the new branch.

In general there's also a problem. TFS is able to branch any folder. Essentially a branch in TFS is special form of copying (at least logically). Git on the contrary is able to branch only entire repository. So I think there is some cases we won't be able to support at all. Let's explore possible cases, assuming git's master branch gets changes from $/Proj/F1/F2/:
  • Simple case. Folder $/Proj/F1/F2/ is branched to $/Proj/F1/F3/. As a result we should now have new branch tfs/<id>/branches/branchName that gets changesets from $/Proj/F1/F3/. Everything is green and cool, at least thoretically :)
  • Almost the same case. Folder $/Proj/F1/ is branched to $/Proj/F4/. As folder $/Proj/F1/F2/ included in the $/Proj/F1/ - it will be branched to $/Proj/F4/F2/ as well (at least it was so in my case - TFS just made change=branch recursively for every item in the tree. I don't know is it the only possible outcome but hope so). So we are back to first simple case except that path somewhat different.
  • Not-so-simple case. Folder $/Proj/F1/F2/F5/ is branched to $/Proj/F1/F2/F6/. As new folder will be in git's master branch - it is useless to do any branching in git. It will just recognize copying and probably that's all. No branching possible.
  • Impossible cases. Folder $/Proj/F7/ is branched to $/Proj/F1/F2/F8/. For git it is just absolutely new content. What branching?! Or consider branching $/Proj/F1/F2/F9/ to $/Proj/F10/. Well, technically we could make a branch in git and take all changes from $/Proj/F1/F2/ except for $/Proj/F1/F2/F9/ folder where content will come from $/Proj/F10/. But what will be the correspondence between TFS and git in this case? In TFS there wouldn't be a folder that has same content as $/Proj/F1/F2/ in git's branch. Nonsense.
I think that we should only support two first cases, so that we search only branches that were made from git-tfs starting point.
Program.cs

Matt Burke

unread,
Jul 22, 2011, 10:53:19 AM7/22/11
to git-t...@googlegroups.com
On Thu, Jul 21, 2011 at 12:01 AM, Ivan Danilov <van.d...@gmail.com> wrote:
> Well, I did some test-app for analyzing branch structure in TFS and it seems
> to work (at least for TFS2010 that I had access to). Find sample code
> attached.

Nice.

> In general there's also a problem. TFS is able to branch any folder.
> Essentially a branch in TFS is special form of copying (at least logically).
> Git on the contrary is able to branch only entire repository. So I think
> there is some cases we won't be able to support at all. Let's explore
> possible cases, assuming git's master branch gets changes from
> $/Proj/F1/F2/:
>
> Simple case. Folder $/Proj/F1/F2/ is branched to $/Proj/F1/F3/. As a result
> we should now have new branch tfs/<id>/branches/branchName that gets
> changesets from $/Proj/F1/F3/. Everything is green and cool, at least
> thoretically :)

This is the easy case. :)

> Almost the same case. Folder $/Proj/F1/ is branched to $/Proj/F4/. As folder
> $/Proj/F1/F2/ included in the $/Proj/F1/ - it will be branched to
> $/Proj/F4/F2/ as well (at least it was so in my case - TFS just made
> change=branch recursively for every item in the tree. I don't know is it the
> only possible outcome but hope so). So we are back to first simple case
> except that path somewhat different.

Yeah, this should look to git-tfs the same as the other easy case.
From what I've seen, the branch is always applied recursively the way
you observed.

> Not-so-simple case. Folder $/Proj/F1/F2/F5/ is branched to $/Proj/F1/F2/F6/.
> As new folder will be in git's master branch - it is useless to do any
> branching in git. It will just recognize copying and probably that's all. No
> branching possible.

I think that's right, though we may be able to do something with it
(eventually, definitely not on the first pass at supporting TFS
branches).

> Impossible cases. Folder $/Proj/F7/ is branched to $/Proj/F1/F2/F8/. For git
> it is just absolutely new content. What branching?! Or consider branching
> $/Proj/F1/F2/F9/ to $/Proj/F10/. Well, technically we could make a branch in
> git and take all changes from $/Proj/F1/F2/ except for $/Proj/F1/F2/F9/
> folder where content will come from $/Proj/F10/. But what will be the
> correspondence between TFS and git in this case? In TFS there wouldn't be a
> folder that has same content as $/Proj/F1/F2/ in git's branch. Nonsense.

I agree: nonsense. It's just new content that appears to have been
added, as far as git-tfs knows.

> I think that we should only support two first cases, so that we search only
> branches that were made from git-tfs starting point.

I agree. It would be awesome to support lots of different branching
strategies from TFS, but, it makes sense to start small.

The other side of the branching coin is merging. I really don't know
much about TFS merges, other than that, with TFS 2005, we had to
restart a branch a few times over the course of a project because the
merge history kept getting into a seemingly-unresolvable state; and
TFS 2008 and/or 2010 introduced new mechanisms for tracking and/or
doing merges.

In theory, we could track TFS merges as git merges, but there are some
merge types (like merging a single changeset) that we would want to
ignore.

--
Matt

Ivan Danilov

unread,
Jul 22, 2011, 11:29:12 AM7/22/11
to git-t...@googlegroups.com
I thought about TFS merges... I think that we could just ignore them
(at least in first version) as long as we can handle them in git-tfs
as regular checkins properly.

From my experience TFS support of merging is just in embryo to say the
least. It could handle only the basic cases with same file changed in
different branches. Any simple rename of the file or the folder makes
merging in TFS very not trivial if not to say impossible. Some time
ago I chose to throw out my changes and repeat them again manually on
top of the branch because I just hadn't found a way to do it
automatically (in fact it was one of the reasons I turned back to see
if alternative exist and found git-tfs). In our team we have several
major branches in TFS for v1.0, v2.0, v2.1 and current DEV lines of
the app. And developers almost always prefer to make same changes in
every touched branch manually. In fact they often do these changes in
single checkin (it is an interesting case for git-tfs by the way,
because we will have several git-commits for single TFS-checkin in
several branches). So for us merging support would be close to
useless.

The second reason is that in git and TFS people tend to use different
workflows. In git merge is almost always just a merge. Only possible
changes that git-user expects in merge-commit is conflict resolving.
In TFS on the contrary users often doing other changes before checkin.
Well, I wouldn't argue here is such thing is good or bad but it
exists. And thus TFS merge is often closer to git's cherry-pick than
to git's merge.

Moreover, single deeply located folder could be merged in TFS instead
of entire branch. What should we do in this case? Making in git
repository merging commit will effectively mark entire branch as
merged in the mainline while in reality just a single folder was
merged.

I tend to think that we will drop merge support in git-tfs at all
rather than in first pass only. But it's just my opinion. Maybe
someone will need it hardly who knows...

> --
> You received this message because you are subscribed to the Google Groups "git-tfs-dev" group.
> To post to this group, send email to git-t...@googlegroups.com.
> To unsubscribe from this group, send email to git-tfs-dev...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/git-tfs-dev?hl=en.
>
>

--

Yours sincerely,


Ivan Danilov
 Senior Developer
 Tel. +380937632900

Matt Burke

unread,
Jul 24, 2011, 6:54:30 AM7/24/11
to git-t...@googlegroups.com
On Fri, Jul 22, 2011 at 11:29 AM, Ivan Danilov <van.d...@gmail.com> wrote:
> I thought about TFS merges... I think that we could just ignore them
> (at least in first version) as long as we can handle them in git-tfs
> as regular checkins properly.

nod

> From my experience TFS support of merging is just in embryo to say the
> least.

nod

> I tend to think that we will drop merge support in git-tfs at all
> rather than in first pass only. But it's just my opinion. Maybe
> someone will need it hardly who knows...

This is a good way to approach software development. Just solve the
problem at hand, and figure out later if you need to solve the rest.

--
Matt

Ivan Danilov

unread,
Jul 29, 2011, 12:07:55 PM7/29/11
to git-t...@googlegroups.com
Currently I am trying to think out how to determine TFS branch where git-tfs should do checkin.

So suppose we already implemented branch support. So how would you like it to look from user's perspective?

First I'd like to have something like 'git tfs detect-branches' command that would have output like program in the first post of this thread. So I could see which branches git-tfs could detect and work with without going to Team Explorer.

Second thing is to actually configure git-tfs to fetch changes from some branch. Lets name it 'git tfs init-branch $/Proj/BranchFolder/ git-branch-name'. And suppose git-tfs repository references '$/Proj/Mainline/' As a result of this command git-tfs should:
  1. Figure out when folder '$/Proj/BranchFolder/' was branched from '$/Proj/Mainline/' (if it was branches from any other folder - error should be shown). Let's suppose first changeset that contains branch folder is 15th.
  2. Determine which changeset has latest version of $/Proj/Mainline/ before it was branched. Suppose it is 10th changeset.
  3. Figure out which commit in git history corresponds to source changeset (if it is not present in git history due to quick-clone - error should be thrown). For example here let's suppose it is changeset a12345.
  4. Execute 'git checkout -b git-branch-name a12345'
  5. Apply changes that were made in TFS changeset 15 (as TFS could have other changes with branching in single commit) and commit them (it should be committed even if there're no changes at all because we should remember changeset #15)
  6. Write some information about new branch and TFS path it corresponds to into config file.
But I'm still somewhat unsure of what git-tfs should do when user commands it to checkin something to TFS. Should user explicitly say each time to which TFS branch git-tfs should commit current state of working tree? It would be not very convenient sometimes.

If not, how git-tfs could determine this info itself? What if user is not in 'master' or 'git-branch-name' branch? What if branches were merged one into another in git-tfs before?

How do you think?

Matt Burke

unread,
Aug 1, 2011, 10:59:32 PM8/1/11
to git-t...@googlegroups.com
> First I'd like to have something like 'git tfs detect-branches' command that
> would have output like program in the first post of this thread. So I could
> see which branches git-tfs could detect and work with without going to Team
> Explorer.

While it would be nice to detect branches, I would be content with
letting the user say where the branches are, at least at first. Your
prototype shows that it wouldn't be too hard to detect them, so maybe
a "--detect-branches" on clone, or a 'detect-branches' command makes
sense.

> Second thing is to actually configure git-tfs to fetch changes from some
> branch. Lets name it 'git tfs init-branch $/Proj/BranchFolder/
> git-branch-name'. And suppose git-tfs repository references
> '$/Proj/Mainline/' As a result of this command git-tfs should:

I would look at how git-svn does it, but I would guess that it's
similar to how git tracks normal upstream/remote git branches. The way
git does it is with a combination of

branch.<name>.remote=<remotename>
branch.<name>.merge=refs/heads/<upstreambranch>

> Figure out when folder '$/Proj/BranchFolder/' was branched from
> '$/Proj/Mainline/' (if it was branches from any other folder - error should
> be shown). Let's suppose first changeset that contains branch folder is
> 15th.
> Determine which changeset has latest version of $/Proj/Mainline/ before it
> was branched. Suppose it is 10th changeset.
> Figure out which commit in git history corresponds to source changeset (if
> it is not present in git history due to quick-clone - error should be
> thrown). For example here let's suppose it is changeset a12345.
> Execute 'git checkout -b git-branch-name a12345'
> Apply changes that were made in TFS changeset 15 (as TFS could have other
> changes with branching in single commit) and commit them (it should be
> committed even if there're no changes at all because we should remember
> changeset #15)

sounds reasonable.

> Write some information about new branch and TFS path it corresponds to into
> config file.

we should be able to track this with normal git refs. e.g.
tfs/default/master (?) is currently the default, but other branches
could be tfs/default/BranchFolder. I would take the 'branch name' (ie
folder name) from TFS, unless there's a conflict, in which case we do
what we need to (add a suffix, e.g. BranchFolder1, or use the full
path, e.g. Proj_BranchFolder) to make it unique.

> But I'm still somewhat unsure of what git-tfs should do when user commands
> it to checkin something to TFS. Should user explicitly say each time to
> which TFS branch git-tfs should commit current state of working tree? It
> would be not very convenient sometimes.

we use upstream tracking info, similar to how git does it and,
presumably, how git-svn does it. If there's no upstream tracking info,
we can guess if there's an obvious ancestor, and that might be ok, or
we just error out and say "you have to tell us where to checkin". git
push has a '--set-upstream' to record the current manual mapping as
the default, and we could do something like that, too.

> If not, how git-tfs could determine this info itself? What if user is not in
> 'master' or 'git-branch-name' branch? What if branches were merged one into
> another in git-tfs before?

merging two TFS branches in git is an interesting (and probably
desirable) case to support. I could see the utility in being able to
do a difficult merge in git instead of TFS. who wouldn't want to do
that? in that case, i think we have to ask where the user wants to
send it, unless we have the upstream info, in which case we do what
they ask.

Ivan Danilov

unread,
Aug 2, 2011, 2:00:51 AM8/2/11
to git-t...@googlegroups.com
> While it would be nice to detect branches, I would be content with
> letting the user say where the branches are, at least at first. Your
> prototype shows that it wouldn't be too hard to detect them, so maybe
> a "--detect-branches" on clone, or a 'detect-branches' command makes
> sense.

The reasons I want this command are:
1) as a self-test, so git-tfs really sees the branch we want to config
and able to track it (maybe mark downstream branches with some symbol
like star). It wouldn't be able to track some branches (see starting
post) so having the command could simplify some detective work when
user will come and tell that he can't setup branches;
2) as a source of copy&paste so that less errors in typing would arise;
3) because branches could be created after repository is configured
(for example we have code stabilization phase on each sprint ending
and it is done via branch) - it is not enough to have 'clone' option.
In general I agree that it is not complex command and benefits
outweigh the complexities imo.

> merging two TFS branches in git is an interesting (and probably
> desirable) case to support. I could see the utility in being able to
> do a difficult merge in git instead of TFS. who wouldn't want to do
> that? in that case, i think we have to ask where the user wants to
> send it, unless we have the upstream info, in which case we do what
> they ask.

Merging in git and then checking in to TFS is exactly my target. At
first I think we could go with cherry-pick (i.e. without complications
of merged trees in git), but clear history in git with merging info is
really something useful so will be a must at some point (maybe not
from the start though).

Matt Burke

unread,
Aug 2, 2011, 7:16:11 AM8/2/11
to git-t...@googlegroups.com
Good stuff.

jimit...@gmail.com

unread,
Aug 2, 2011, 10:01:23 AM8/2/11
to git-t...@googlegroups.com
Maybe something similar to git-svn?

Ivan Danilov

unread,
Aug 2, 2011, 10:20:37 AM8/2/11
to git-t...@googlegroups.com
To my shame I haven't seen yet what git-svn have to propose. Could you describe their solution briefly or post some link where I could read about it?

I suppose that I will have some time to start actual developing of the feature in several days, so right now it is just a preliminary discussion about "how should it be?". So it's perfectly ok now to propose cardinally different schemes :)

Jimit

unread,
Aug 2, 2011, 12:25:11 PM8/2/11
to git-t...@googlegroups.com
The command "git svn clone <svn url>" has optional flags --trunk, --branches and --tags to designate where find them in the source tree. It also has a --stdlayout to indicate the default TTB folder layout commonly used in svn repositories where trunk is "trunk", branches are in a folder called "branches" and tags are in a folder called "tags". FYI
Git-tfs could additionally have singular forms of the above flags to allow listing the branches to be pulled: e.g. --branch "develop" "features/feature1"

Ivan Danilov

unread,
Aug 2, 2011, 12:51:36 PM8/2/11
to git-t...@googlegroups.com
tags (labels in TFS terminology) is not our concern right now.
trunk is the point where git-tfs clone was initially pointed.
As for branches... SVN community has strong standard structure of the project thus setting URL of branches folder is enough. In TFS community there're no such standard unfortunately. At least our project has many branches in different places and besides branch folder there're other items. Moreover TFS has means to automatically determine where 'trunk' folder was branched (as I described in second post above), so manual pointing to every branch is only first step.

Git-tfs could just track every branch automatically, but sometimes it is unnecessary. So we have two choices: implement some config option to ignore given branch and implement tracking all un-ignored ones or vice-verse: track only pointed.

But '--branches' seems almost useless to me in git-tfs context.

Jimit

unread,
Aug 2, 2011, 5:19:27 PM8/2/11
to git-t...@googlegroups.com
Tracking every branch automatically sounds like a reasonable default, with the option to opt-out of monitoring/pulling specific branches. Or do both :
 --include-branches (default) - detect and include all branches
--include-branch - include specific branches
--exclude-branches - disables branch detection/cloning
--exclude-branch - used in combination with --include-branches to exclude specific branches

Ivan Danilov

unread,
Aug 2, 2011, 5:20:33 PM8/2/11
to git-t...@googlegroups.com
Yep, that's something I'm aiming for, but not at first iteration.

> --
> You received this message because you are subscribed to the Google Groups
> "git-tfs-dev" group.

> To view this discussion on the web visit
> https://groups.google.com/d/msg/git-tfs-dev/-/Rx6WLCq0vBYJ.

Jimit

unread,
Sep 14, 2011, 11:12:50 AM9/14/11
to git-t...@googlegroups.com
Is it currently possible to push a specific git branch (not necessarily master) to a tfs remote?

Ivan Danilov

unread,
Sep 14, 2011, 11:49:52 AM9/14/11
to git-t...@googlegroups.com
Of course, why not? You can execute git tfs rcheckin from any branch - it looks at HEAD only. And for git tfs checkin there's last parameter where you can specify commit hash.

I don't understand why you're asking this in the topic about TFS branches though... It is possible I hadn't understand what do you need really.

mcint...@gmail.com

unread,
Feb 17, 2012, 1:04:35 PM2/17/12
to git-t...@googlegroups.com
Hi there. I was wondering what the status of this is - it sounds very promising!

Ivan Danilov

unread,
Feb 17, 2012, 1:12:14 PM2/17/12
to git-t...@googlegroups.com
Well... it hangs here until I will have it as a blocker at my main work or someone else will continue the work. There were some questions regarding contributions to branch support, but without results by far.

...or the miracle happens and I will force myself to do it at last. You know, when you can move your work forward without doing something - it's not enough motivation to start doing it :)

Sean M. Collins

unread,
Feb 17, 2012, 2:04:43 PM2/17/12
to git-t...@googlegroups.com
On Fri, Feb 17, 2012 at 10:12:14AM -0800, Ivan Danilov wrote:
> Well... it hangs here until I will have it as a blocker at my main work or
> someone else will continue the work. There were some questions regarding
> contributions to branch support, but without results by far.

$WORK does have branches in projects, so I have real data to work
against. I did gather some notes (https://gist.github.com/1473849)
about branches in TFS, and plan on doing some hacking in the near
future.

Reply all
Reply to author
Forward
0 new messages