1

我们目前在我们的组织中使用 TFS,但正在研究 TFS 2013 的内置 Git 支持。我想从 TFS 中提取一个现有分支及其所有历史记录到 Git 中一个不同命名的子文件夹中(是的,我意识到为每个分支创建一个单独的 Git 存储库会更好,但是“出于某种原因”我不能做那件事)。

所以我使用 git-tfs 将 TFS 历史克隆到一个新的 repo 中。任何 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

接下来,我首先尝试使用子树合并将提交从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中创建了两个分支importsquash我在import中执行了子树合并,然后重新设置为squash

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

然而,这样做的结果是import现在在其根目录(不是 /MyProject/MyDir)中包含所有原始 TFS 提交,并且squash似乎不受影响。

接下来,我尝试使用来自 contrib 的新“git subtree”脚本(在远程 TFS 的新克隆中)

git subtree add -P MyProject/MyDir

同样,在本地看起来很棒,但推回 TFS 服务器显示所有内容都压缩到一个子树提交中(但同样有多个父级)。

最后,我尝试了将 git subtree 变基为具有共同祖先的第二个分支。和以前一样的问题:我导入的提交不再在子目录中。

那么我对rebase的理解是不正确的,还是只是子树合并和子树脚本不兼容?

我的下一个方法是在导入或变基之前尝试filter-branch重写oldtfs (同样, oldtfs在达到导入目的后将永远不会被共享/上传)。这是这里最好的选择吗?

(我想“做对”的原因是我想发布一个可重复的配方或脚本供部门中的其他人以类似的方式使用)。

4

1 回答 1

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
于 2013-08-05T13:59:43.033 回答