我们目前在我们的组织中使用TFS,但正在研究TFS 2013的内置Git支持。我想将现有的分支从TFS拉到Git中的一个不同命名的子文件夹(是的,我知道为每个创建一个单独的Git repo会更好,但是“出于原因”我不能做到这一点。)
所以我使用git-tfs将TFS历史记录克隆到一个新的仓库中。没有任何Git更改会被推回到TFS,所以没有问题。
git tfs init http://ExistingTfs:8080/tfs/DefaultCollection $/Path/To/Branch oldtfs
git tfs fetch
然后我在本地克隆了新的repo,并将 oldtfs 添加为遥控器。
git clone http://NewTfs:8080/tfs/DefaultCollection/_git/NewRepo newtfs
git remote add oldtfs ../oldtfs
接下来,我首先尝试使用subtree merge将提交从 oldtfs 提取到 newtfs 并在本地提交。
git merge -s ours --no-commit oldtfs/master
git read-tree --prefix=MyProject/MyDir/ -u oldtfs/master
git commit -m 'import old TFS'
它似乎运行良好(“git log”显示所有历史记录在正确的位置)但是当我推回到TFS时,它似乎只是一个合并提交,虽然它确实有两个父母,因为我经过一番阅读,听起来就像我需要的那样。
所以我在 newtfs ,导入和壁球中创建了两个分支。我在导入中执行了子树合并,然后重新加入壁球。
git checkout import
[...subtree merge as above...]
git rebase squash
然而,结果是 import 现在在其根目录中具有所有原始TFS提交(不是/ MyProject / MyDir),并且 squash 似乎是不受影响。
接下来,我尝试使用新的"git subtree" script from contrib(来自远程TFS的新克隆)
git subtree add -P MyProject/MyDir
再一次,在本地看起来很棒,但推回到TFS服务器显示所有内容都被压缩到一个子树提交中(但同样有多个父节点)。
最后,我尝试将git子树重新引入具有共同祖先的第二个分支。和以前一样的问题:我导入的提交不再在子目录中。
因此我对rebase的理解不正确,还是只是子树合并和子树脚本与它不兼容?
我的下一个方法是在导入或重新定位之前尝试 filter-branch 重写 oldtfs (同样, oldtfs 将永远不会在它用于导入目的之后共享/上传)。这是最好的选择吗?
(我之所以要“做对了”的原因是我想为部门中的其他人发布可重复的食谱或脚本,以便以类似的方式使用。)
答案 0 :(得分:0)
所以最后我最终使用了 filter-branch 命令;因为我不会在任何地方推动“预先重写”的历史,不会对未来的合并造成任何问题。这是TFS Git视图以及其他图形历史工具(如TortoiseGit)从导入文件夹的子目录中显示我之前的整个历史记录的唯一方法。
因为我可以使用 - index-filter 子命令而不是 - tree-filter ,所以它并不像我想象的那样混乱。该手册页甚至还有一个如何操作的示例:
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