Importing from Git to TFS with branches structure

1,096 views
Skip to first unread message

Gian Maria Ricci

unread,
Dec 17, 2014, 3:22:07 AM12/17/14
to git-t...@googlegroups.com
Hi to everyone,

I've a git repository that was imported from subversion with Git svn. It has a main branch and some branches.

My goal is, being able to import this repository in an empty folder of TFS Source Control while keeping branches relation. I tried to setup everything but git tfs checkin gives me the error "no tfs parents found"

I've read documentation and googled around, but I was able to find only examples on how to connect to an existing TFS repository and working with branches in TFS, but nothing on: how to setup git-tfs to import everything on a TFS Blank folder.

Anyone can point me to some documentation or some suggestion?

Thanks a lot for any information.

Gian Maria.

Matt Burke

unread,
Dec 18, 2014, 11:55:12 AM12/18/14
to git-t...@googlegroups.com, Philippe Miossec
git-tfs is intended more for getting data from TFS to Git, but I think
it can be used the way you want to. There are two things you could
try, depending on whether you want to preserve history in TFS.

Note: I haven't tried either of these, so you might want to try
against a test instance of TFS to see if it works. Also, I'm assuming
that you just care about the master branch. If you care about other
branches, Philippe will be able to provide more information about how
to do that.

----------

If you don't need to preserve history:

1. Outside of any git repository or working folder, run `git tfs clone
https://server/tfs/Collection $/DestProject conversion`. This will
create a `conversion` git repository, and it should be empty and have
a commit or two that match the TFS project creating changesets.

2. `cd conversion`

3. `git remote add history <path-to-git-repo>` and `git fetch
history`. This will pull in history from the repository that you
created with git-svn.

4. Do a baseless merge (`git merge history/master`) to bring in the
current state from your git-svn's master branch. Up to this point,
everything in the "conversion" repository is local to it, and if
anything has gone wrong, you should be able to delete the conversion
repository and start over.

5. Checkin the current stuff to TFS (`git tfs checkin`). This will
create one changeset in TFS with all the content from the current git
repository.

----------

If you do need to preserve history, you'll want to check in to TFS
using a different command, and the baseless merge probably won't be
adequate.

Start with steps 1-3 from above.

4. Rebase the history onto your TFS branch by running: `git rebase
--onto master --root history/master`. This will apply all the commits
from your git-svn repository on top of the commits that were created
by `git-tfs`. This addresses the error you ran into ("no tfs parents
found"). Similar to the previous set of steps, you also have only
changed the "conversion" repository at this point, and can delete it
if something's gone wrong.

5. Use rcheckin to copy the commits to TFS (`git tfs rcheckin`). You
might want to look over the docs for rcheckin
(https://github.com/git-tfs/git-tfs/blob/master/doc/commands/rcheckin.md)
before you run it, to see if there are any options you'd like to use.

-----------

If the conversion is successful, I would archive or delete the
repository that was created by git-svn. If you try to use it and
git-tfs, you will run into problems because the commit ids don't
match. I would either make "conversion" the new common git repository;
or have your team create their own git repositories with `git tfs
clone`, and use TFS as a sync point.


--
Matt
> --
> You received this message because you are subscribed to the Google Groups
> "git-tfs-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to git-tfs-dev...@googlegroups.com.
> To post to this group, send email to git-t...@googlegroups.com.
> Visit this group at http://groups.google.com/group/git-tfs-dev.
> For more options, visit https://groups.google.com/d/optout.

Philippe Miossec

unread,
Dec 18, 2014, 5:54:03 PM12/18/14
to git-t...@googlegroups.com
My point of view......

First, be clear that git-tfs is really not intended to be used to migrate from git to tfs!
It will be a painful process to successfully push your history from git to tfs when you want to push history with branches :(
And even more if you have merges between branches!!!!!! (because you will have to do a lot of things manually).

I hope that you understand quite well how git works because in the contrary it will be quite impossible to do for you...

Lets go with the case where branches are never merged, only forked from a parent branch.

Imagine we have a git history like that:

C1--C2--C3--C4--C5<-(master)
     |
      --C6--C7--C8<-(feature1)
             |
              --C9--C10--C11<-(feature2)

Note: let say that we will use the same names for tfs folder/branch
that the git ones i.e. '$/project/master' for git branch 'master'

The first thing you have to do is clone the folder (that you MUST convert in branch to use git-tfs!) you have created '$/project/master' :

    git tfs clone http:/tfs/Collection $/project/master

Then you have to add your already existing git repository as a remote ( will be called 'old' in below) in the newly git repository create by git-tfs and fetch all the history!

The first problem that occurs is that when you have created a folder in tfs,
there is already a changeset created and then there is least one commit in your git repository.

You will have something like that:

C0<-tfs/default

C1--C2--C3--C4--C5<-(old/master)
     |
      --C6--C7--C8<-(old/feature1)
             |
              --C9--C10--C11<-(old/feature2)

Be aware that C0 contains important metadata ( for example git-tfs-id: [https://tfs.codeplex.com:443/tfs/TFS16]$/vtccds/renamed3;C33407) needed
by git-tfs! If you want to push a new commit to tfs and that there is no commit with such metadata as an ancestor, git-tfs won't work.

Then you should understand the problem, you have 2 histories with distinct roots and you can't push your history because of their is no 'git-tfs commit' with metadata
 in the history you want to push.

So, you have to rebase your history a branch at a time on the commit C0 fetched from tfs and push it to tfs!

Here you have 2 strategies (I don't know which is the best --it depends of your history-- but, the second is closer than the one that you will have to use if you've got merge commits):

(strategy 1)
1. rebase 'old/master' on C0
2. use 'git tfs rcheckin --quick' to push the commits to Tfs
3. find, looking in the log, the 'C2bis' commit in your history, which is the commit similar to 'C2' but once pushed to Tfs (with the metadata)
4. create a branch in Tfs with command 'git tfs branch $/project/feature1' (that fetch a commit that we will call 'CF1.0')
5. rebase 'old/feature1' onto the first commit 'CF1.0' using the command 'git rebase --onto CF1.0 C2 old/feature1'
6. go to step 2. and do steps 2. to 5. until you have branches to push to Tfs.

(strategy 2)
1. rebase just the part of the branch 'old/master' until you find a fork of a branch (here from C1 to C2) to C0
2. use 'git tfs rcheckin --quick' to push the commits to Tfs
3. here, you don't have to find the 'C2bis' commit in your history because that's the last commit in history
4. create a branch in Tfs with command 'git tfs branch $/project/feature1' that you will use later when you finished to push the 'master' branch.
5. go to step 1. and continue until you have pushed the 'master' branch
6. Checkout the first branch you created and apply the same strategy (from step 1. to 5.) to push the branches

Here is for the painful but simple case where you don't have merges between branches.

If you have merges between branches, if you didn't shoot you in the head before, then you will have to use the strategy 2 but stop also to each merge commit!

Then you will have to manage merge commit this way:

1. Be sure that you have pushed the 2 branches in tfs to the last commit BEFORE the merge commit
2. Recreate the merge commit with the 2 'new' branches. I am not sure what is the best/easier way to do the merge and be sure to have done the EXACTLY same merge!
Perhaps, create the merge and replace the content of the working directory
with the content of the old merge commit and amend the commit or do the merge then cherry-pick the old merge then squash the 2 commits)
3. Push only this merge commit to tfs with 'git tfs rcheckin --quick'
4. Continue (strategy 2) until next merge or fork commit...

I hope it will help...


Gian Maria Ricci

unread,
Dec 20, 2014, 5:43:43 AM12/20/14
to git-t...@googlegroups.com
@matt: I've already imported with history and without keeping branch structure, I really need to know if it is possible to import with branches.

@phillipe: really many many thanks for your detailed answer. I'm really familiar with Git and I had no problem following your workflow, you were super clear, thanks again.

It confims me that it is not possible to simple translate Git Branching to TFVC. It is something that I knew, but I have a customer that asked me to inspect every possibilities so I wrote the post to have confirmation.

Your answer confirm me officially that moving to TFVC while keeping branch relations with git-tfs is a long manual process. 

Thanks again!

Regards.
Reply all
Reply to author
Forward
0 new messages