将现有的Git仓库拉入具有完整历史记录的子树(不会挤压)

时间:2013-08-01 19:50:07

标签: git git-rebase git-subtree git-tfs

我们目前在我们的组织中使用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 将永远不会在它用于导入目的之后共享/上传)。这是最好的选择吗?

(我之所以要“做对了”的原因是我想为部门中的其他人发布可重复的食谱或脚本,以便以类似的方式使用。)

1 个答案:

答案 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