This project is read-only.

Pushing git-tf changes into a remote repository creates duplicate commits

Feb 18, 2014 at 7:45 AM
TFS is the main VCS at my company. We are a team of 3 and prefer using git for local development and we push changes to a remote repository on the network that acts as a VCS for our team build server, which will trigger a new build every time someone pushes any changes on the remote master branch.
The problem we encounter is that every time developer 1 pushes his local git changes to the remote location, all the other developers will begin seeing duplicate commits, like in the picture bellow.
The changes that developer 2 sees are as follows:
-the remotes/origin_tfs/tfs branch (same as local master branch) will show all changesets pulled from TFS using git tf pull command and the user associated with each commit is the TFS user (DOMAIN\user)
-the remotes/team/master branch are the changes that developer 1 pushed, but even though the content of the commits on the remote branch is exactly the same as the ones on the local branch, the user shown here is the one configured in git (showing the git user email address), therefore they have different hash codes.

In the example offered here on CodePlex (Working with teams) only Alice performs operations in TFS.

What happens when all developers have access to TFS? How can I 'trick' GIT in not creating duplicates, since if I'll try and pull changes from the remote master branch, I will get a nasty merge commit, which is something I don't want. It's also not possible to change the git email address to the TFS user name, since I will get an error when GIT will load its config file.

Any suggestions?

Mar 13, 2014 at 4:10 PM
Edited Mar 13, 2014 at 4:20 PM
I've triggered the same issue and found out the workaround.

Gittf doesn't share the mapping (git commit <=> TFS commit) between developers, so each developer gets a TFS commit as a separate git one.

Gittf stores the mapping between commits in the .git/git-tf file:
[git-tf "commits"]
    changeset-756390 = d200a8776b70ff7cde1b182936f1bec6822b7f9a
    changeset-756391 = 18c7cb3344ad08aaa3e1180d2a8cd1c419d88aa5
[git-tf "changesets"]
    commit-d200a8776b70ff7cde1b182936f1bec6822b7f9a = 756390
    commit-18c7cb3344ad08aaa3e1180d2a8cd1c419d88aa5 = 756391
    hwm = 756391
You can avoid duplicates if you share or recreate the .git/git-tf file.
I haven't succeed in forcing the gittf to restore the mapping from the git tags. This would be a useful feature.

My solution is to restore the file from git tags using script:
  • gittf creates git tags for each TFS commit,
  • a commiter pushes tags to the git remote,
  • each developer gets tags from the remote,
  • a script recreates the mapping from the tags,
  • now it's safe to get new TFS commits.
I use the following .git/config:
    tag = true
[remote "origin"]
    tagopt = --tags
The script .git/create_tf_index recreates the mapping from the tags:

INDEX=`git rev-parse --show-toplevel`/.git/git-tf

TAGS=`git show-ref -d --tags | sed "s/refs\/tags\///g" | sed -n "s/\(.*\) TFS_C\(.*\)^{}/\1 \2/gp"`

echo '[git-tf "commits"]' > $INDEX
( awk '{ print "\tchangeset-"$2 " = " $1 }' >> $INDEX <<EOF

echo '[git-tf "changesets"]' >> $INDEX
( awk '{ print "\tcommit-"$1 " = " $2 }' >> $INDEX <<EOF

echo -E $TAGS | awk '{ print "\thwm = " $NF }' >> $INDEX 
(The script is ugly, but this draft solution satisfies my needs. I think that it's possible to partially create the mapping using tags which are newer then refs/remotes/origin_tfs/tfs)

Maybe, the script can be attached to the appropriate git hook, but I use the aliases for the commands:
!git pull --rebase origin master && `git rev-parse --show-toplevel`/.git/create_tf_index && git tf pull --rebase --deep
!git tf checkin --deep && git push --follow-tags origin master