How do I use git-tfs and idiomatic git branching against a TFS repository?
Asked Answered
H

3

49

How Do I Use git-tfs Idiomatically?

  • The git idiom is to check out branches to the root directory of the repository. Checking out a branch will replace the contents of the directory with the contents of that branch.

  • The TFS idiom is to check out each branch in a different directory under the root directory of the repository (even the master or trunk branch). Checking out a branch will place it in a new directory next to the current one.

Using git-tfs, I can clone a TFS repository or branch into a git repository. I want to work on a TFS repository with multiple branches in a manner consistent with the git branching idiom. But I'm not sure what's technically possible or recommended :)


Clone The Whole TFS Repository

If I clone the whole repository out of TFS

> git tfs clone http://<tfsurl>:8080 $/main

That would give me a git master containing all the TFS branches as directories.

[master]> dir
  trunk
  feature-logon
  feature-search
  release-0.0.1

Add a Remote Per TFS Branch

I don't know if I can (or how to) map a git remote to each TFS branch.

> git init .
[master]> git tfs clone http://<url> $/main/trunk .

Then

[master]> git checkout -b feature-logon
[feature-logon]> git tfs clone http://<url> $/main/feature-logon .

I know this is technically incorrect, but I don't know any better without playing (my only TFS repo is very large, experimenting is taking a long time)

Halflight answered 26/2, 2011 at 21:47 Comment(1)
It looks like Ivan Danilov is tackling this issue!Halflight
F
32

It's now possible to get the TFS branches to be correct Git branches if cloning using git-tfs. This is now in the stable release! You first clone not the entire repository but the trunk :

git tfs clone http://<tfsurl>:8080 $/main/trunk

Then you run branch --init, which creates a new branch in the Git repository

git tfs branch --init $/MyProject/MyTFSBranch

in your case :

git tfs branch --init $/main/feature-logon

Or use the the --all flag on a fresh cloned repository to create ALL the branches present on the TFS server.

git tfs branch --init --all

You could also clone directly with all the branches using flag --with-branches:

git tfs clone http://<tfsurl>:8080 $/main/trunk --with-branches

The documentation for this new command is here. Feel free to provide feedback to improve it...

Freeboot answered 4/12, 2012 at 19:53 Comment(1)
Yay, this is exciting news! I guess I should've been following along closer on git-tfs-dev. I didn't realize this was even imminent.Daryn
S
3

Here's one way you can do this, and still maintain some relationships between master and the branches. You'd probably want to script it. Excuse me if I use bash statements rather than windows command line for some of my examples

First clone the whole repository out, as in your first example, with branches as directories.

This moves the trunk to the root. (hopefully there are no conflicts with your branch folders)

mv trunk/*.* .

Commit your new master

git commit -a -m "refactoring master"

creating a new branch

git checkout -b feature-login

Copy the branch files over the root files

mv feature-login/*.* .

Don't need these here any longer

rm -rf [all_branch_directories]

Commit the branch

git commit -a -m "refactoring feature-login"

back to master

git checkout master

Do it all again

git checkout -b next_branch

etc. etc..

Finally at the end

git checkout master
rm -rf [all_branch_directories]
git commit -a -m "refactoring master"

It's not perfect, but you end up with all your branches cloned off master and diffed more or less appropriately. AFAIK git should be fine if you overwrite a file with another file but the contents don't change, which allows this to all work.

One downside is that you won't clear out any files in the branches that have been deleted from the trunk. This may or may not be an issue for you...

Sambar answered 6/4, 2011 at 0:50 Comment(5)
come to think of it, you could probably just delete everything from each new branch before copying branch files downSambar
Isn't this going to break the link when you try to commit to TFS again?Longhand
oh yes. My assumption was the the OP wants to move his TFS to git permanentlySambar
would not recommend using two different source control systems at the same timeSambar
I want to continue using TFS as the "golden" repository. I want to use git on the side, or in a smaller team.Halflight
L
3

What about multiple remote tfs-repos, 1 per branch? i have the following structure:

$/Root/Main/someproject (the trunk)
$/Root/Releases/Branch1/someproject
$/Root/Releases/Branch2/someproject

what i did

git tfs quick-clone http://tfs:8080/tfs/defaultcollection $/Root/Trunk GitRepo
git tfs quick-clone http://tfs:8080/tfs/defaultcollection $/Root/Releases/Branch1 GitRepo -i 
    branch1
git tfs quick-clone http://tfs:8080/tfs/defaultcollection $/Root/Releases/Branch2 GitRepo -i branch2

then you can create a branch for each remote branch: git checkout -b localbranch1 tfs/Branch1 and commit into the tfs branch git tfs ct -i branch1

In order to be able to easily merge the two lines create a graft:

echo branch-commit-id trunk-parent-id > .git/infos/grafts

where the ids are the hash of the first branch commit (from the Releases repo) and a parent commit id (find manually)

PS: I get error: Specified git repository directory is not empty as well (don't know how it worked before), so I manually added the second url in .git/config and did git tfs fetch -i Branch1

Lurdan answered 7/9, 2011 at 12:58 Comment(3)
Don't you get "error: Specified git repository directory is not empty" when you attempt to clone into the same GitRepo multiple times?Stereoisomerism
@Stereoisomerism Haven't done extensive testing yet but the following seems to work: 1) Clone the first branch using git tfs clone. 2) Manually copy/paste/tweak the tfs-remote section in .git\config 3) run git tfs fetch -i {the-quoted-name-from-the-tfs-remote-section}Gulosity
@Gulosity I've followed your suggestion, combined with the checkout strategy in Boklucius's answer, and I seem to be able to get nicely isolated local branches to match the remote tfs branches. Also, if anyone is interested, Dr. Random/Casey also talks about a similar strategy in this blog post.Emerald

© 2022 - 2024 — McMap. All rights reserved.