事情是这样,有一个叫 scripts 的 git 库,里面放了一些所属不明的脚本。我希望把这些零散脚本管理起来,它们不属于任何一个项目,为每个脚本都建一个库又太小题大做,于是有了一个『脚本孤儿院』。
与此同时,另外有个项目在进行,到一定程度时,它需要引用前面脚本里的一个。我突然明白,那个脚本就是这个项目的一部分,它『找到组织』,该『认祖归宗』了!
这个背景其实不重要,就是提供一个具体的场景。不知道你有没有过在不同仓库调整文件历史的时候。
剪切,粘贴?
最简单的方法当然是,从原库 剪切 相关文件, 粘贴 到新库,然后两边分别提交变更。
确实,移交 文件所属 这件事完成了。但结果是,在新库历史里这些文件是凭空出现的,之前的提交历史都丢失了。
当然你可以在新库提交时,在 message 里提一下,这些文件原本是在哪个库,详细历史请参考该库历史。可如果有一天旧库不再维护呢?你无法保证两个库生命周期一致。
merge ?
怎么连带提交历史一起移动呢? Merge !
Merge 就是为这个目的存在的。
不过等等,merge
只能在 branch 之间进行吧,两个 repo 怎么做?
严格来说,是
commit
之间,branch
也好tag
也罢,在 git 里最后都是指向commit
的指针。
fetch & merge
当然可以,只要把要合并来源,当做远程库,获取到目标库生成一个远程分支,再合并即可。
假设要做的是 repo-from
到 repo-target
的合并,按以下操作即可:
|
|
完成之后再 git remote rm other
, 然后 git rebase
稍微调整一下提交历史就好。当然也可以 fetch
后直接选择 rebase
,把需要的 commit
挑选出来。merge
和 rebase
的用法这里不再赘述。
这样合并,会把完整历史引进来,但实际上你可能只要部分文件和相关的提交历史,所以需要挑选部分提交历史。
fast-export & fast-import
上述方法基本可以解决问题,非要挑剔的话:
- 要先 添加 远程库 再删掉
- 引入的历史可能太多
其实 git 自带了相关工具:
|
|
通过 fast-export
+ pipe + fast-import
从一个库导入到另一个库。注意的地方有几个:
- 因为两边都是本地分支,所以为了避免重名,中间可以用
sed
改名 fast-export
可以指定导入的范围,例如上面就是获取master
最后5个commit。不过注意的是,这个只是限制了commit 历史,文件还是会整个分支(也就是最新那个 commit 的所有祖先 commit)都包含进来。文件的筛选就要在merge
阶段做了。
内容就介绍到这了,留心细节并不复杂。一些具体的指令还有 commit 范围的表示,就不在本篇范围内了。
对于 Git 的使用,不该排斥甚至推荐用 TortoiseGit 和 SourceTree 这样的 GUI 工具,为常规操作节省时间。但也要了解底层的指令,可以做到更多更细致的操作。
本文为本人原创,采用知识共享 “署名-非商业性使用-相同方式共享” 4.0 (CC BY-NC-SA 4.0)”许可协议进行许可。
本作品可自由复制、传播及基于本作品进行演绎创作。如有以上需要,请留言告知,在文章开头明显位置加上署名(Jayce Chant)、原链接及许可协议信息,并明确指出修改(如有),不得用于商业用途。谢谢合作。
详情请点击查看协议具体内容。