我有一个使用单个存储库的现有项目。目录结构如下所示:
* MyProject
* client
* server
* tester
* documentation
* deployment
* graphics
我想修改它,以便client
,server
和tester
是单独的存储库; MyProject
仍然存在,其中包含其他子目录,并通过client
托管git subtree
等。
所以最终的结果是我有相同的目录结构,但我可以单独对client
等进行版本控制,而不会打扰其余的回购。
我应该用什么命令来实现这个目标?我有权登录远程repo的服务器并直接在repo上发出git
命令。
额外额外奖励:目前我已在client
的历史记录中同时获得了MyProject
的所有提交。如果可能的话,我想保留这个新的子树项目的历史。
答案 0 :(得分:0)
我刚刚阅读了一个关于子树的非常有趣的页面:http://blogs.atlassian.com/2013/05/alternatives-to-git-submodule-git-subtree/
因此,如果没有远程跟踪,您可以执行以下操作:
1)他说要先创建子树,然后提供这个片段。要保留此目录中的历史记录,您只需避免使用“--squash”,但我认为此历史记录仍保存在主仓库中。
git subtree add --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git master
2)然后只需获取远程仓库
我怀疑你会想要遵循他的指示,包括远程跟踪,这是完全不同的。
答案 1 :(得分:0)
这个答案基于this blog post,我直到今天才发现。
所需的步骤是:
client
,server
,tester
有单独的分支,则将它们展平(rebase或merge),以便单个提交具有所有使用git subtree
可以轻松完成此操作。注意:git-subtree可能require installation。
将目录复制到其自己的存储库,其中目录的名称将从新存储库中的文件路径中删除(即tester/foo/bar.c
在新存储库foo/bar.c
中变为tester
}),使用以下代码。这是tester
的代码;我一次做了多个拆分我使用了一个shell for
,当然也可以复制粘贴。
另请参阅this thread,尽管在该主题中,OP希望将tester/foo/bar.c
移至ABC/foo/bar.c
。
在git主机上,你保留了你的存储库 - 我这样做是为了有兄弟姐妹Base,客户端,服务器,测试人员,但这并不重要:
cd /path/to/base
mkdir tester.git
cd tester.git
git init --bare
在开发系统上(使用git remote -v
查看您现有的遥控器;我使用ssh:
)
git remote add sub_tester ssh://git_host/path/to/base/tester.git
git checkout master; # assume master for this demonstration
git subtree split --prefix=tester -b split_tester
git push sub_tester split_tester:master
git branch -D split_tester
subtree split
命令在同一个repo中创建一个新根,将该目录中master
个文件的所有历史提交复制到新根上的一个分支上,最后将其合并到master
。
现在你可以清除糠:
git rm -r tester
git add -A
git commit -am "Removing tester which has been split to its own repo"
新的回购在其中有历史,因此没有必要在基础回购中保留该历史记录。事实上,如果您稍后重新添加新的repos作为子树,那么您已经复制了所有历史记录。我通过以下步骤删除了历史记录:
git checkout last_commit_to_keep
git checkout --orphan history
git commit -m "Squashed old history"
git replace last_commit_to_keep history
git branch -D history
现在您可以将单独的repos添加为子树:
git subtree add --prefix-tester sub_tester master
附录(并非真正相关):这样做之后我决定对我的工作流程来说,子树不是一个好主意。最大的问题是,如果在子树中的分支上进行更改,则必须每次将该分支合并到repo的主要部分。这会很快导致在gitk
中查看时看起来像意大利面条的历史记录。
或者,如果您在master
上开发然后向后移植到子树,则没有任何检查可以阻止您与子树不同步,并且您可能必须保持合并以确保您保持在同步。
我最终如上所述分裂,但随后使用子模块,结果更适合我的工作流程。通过压缩子模块更新提交可以保持整洁。
当然,使用嵌套存储库是另一种选择,但是在不同的存储库之间根本没有相对版本控制。并且可以使用git clean
意外删除它们。可能最适合我的是那些在嵌套的repos之间维护公共标记的强大脚本之一。