Вопрос

We currently use TFS in our organization but are looking into TFS 2013's built-in Git support. I'd like to pull an existing branch from TFS, with all of its history, into a differently named subfolder in Git (yes, I realize creating a separate Git repo for each would be better, but "for reasons" I can't do that just yet).

So I used git-tfs to clone the TFS history into a new repo. None of the Git changes will ever be pushed back to TFS so no problem there.

git tfs init http://ExistingTfs:8080/tfs/DefaultCollection $/Path/To/Branch oldtfs
git tfs fetch

I then cloned the new repo locally and added oldtfs as a remote.

git clone http://NewTfs:8080/tfs/DefaultCollection/_git/NewRepo newtfs
git remote add oldtfs ../oldtfs

Next I first tried using a subtree merge to pull the commits from oldtfs into newtfs and committed locally.

git merge -s ours --no-commit oldtfs/master
git read-tree --prefix=MyProject/MyDir/ -u oldtfs/master
git commit -m 'import old TFS'

It seemed to work well ("git log" showed all the history in the right place) but when I pushed back up to TFS, it appeared as only a single merge commit, although it did have two parents as I'd expect.After a bit more reading, it sounded like a rebase is what I need.

So I created two branches in newtfs, import and squash. I performed the subtree merge in import and then rebased into squash.

git checkout import
[...subtree merge as above...]
git rebase squash

The result of this, however, is that import now has all the original TFS commits in its root (not /MyProject/MyDir), and squash seems to be unaffected.

Next, I tried using the new "git subtree" script from contrib (in a fresh clone from the remote TFS)

git subtree add -P MyProject/MyDir

Again, looked great locally but pushing back up to the TFS server showed everything squashed into one subtree commit (but again with multiple parents).

Lastly, I tried git subtree with rebasing into a second branch with common ancenstor. Same problem as before: my imported commits were no longer in the subdirectory.

So is my understanding of rebase incorrect, or is it just that the subtree merge and subtree script aren't compatible with it?

My next approach was going to be attempting filter-branch to rewrite the oldtfs before importing or rebasing (again, oldtfs will never be shared/uploaded after it serves its purpose of importing). Is that the best option here?

(The reason I want to "get this right" is that I want to publish a repeatable recipe or script for others in the department to use in a similar manner).

Это было полезно?

Решение

So in the end I did just end up using the filter-branch command; since I won't be pushing the "pre-rewritten" history anywhere it won't cause any problems with future merges. It was the only way that the TFS Git view, as well as other graphical history tools (such as TortoiseGit) would show my entire previous history, from within subdirectories of the imported folder.

It wasn't as messy as I thought it would be since I could use the --index-filter subcommand instead of --tree-filter. The man page even has an example of how to do it:

git filter-branch --index-filter \
  'git ls-files -s | sed "s-\t\"*-&MyProject/MyDir/-" |
   GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
   git update-index --index-info &&
   mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top