git remote add upstream_Git使用多个远端仓库协作开发
我是常年自己开发项目,一个项目对应一个git仓库,而且经常就一个master分支,这种情况一用就是好几年。
最近遇到一个比较特别的需求,需要用一个大型开源项目作为项目起点,和之后自己开发的部分提交到另一个私有库,同时需要和开源项目保持更新同步。
作为一个常年处于git新手的我光是想起来就觉得复杂,想想以后的代码冲突就陷入绝望,但我肯定不是第一个遇到这样问题的人。
查了一大堆资料,大部分都是说的把项目备份到多个远端库,而我需要从一个开源库拉取代码,合并,开发,提交到私有库,并且不断重复这个过程推进私有库项目,为了厘清思路,特地画了个流程图。
如图所示的逻辑已被我运用到实际开发中,为了简明扼要的说明问题,私有库只有一个master分支,本地开发库有两个分支master和up-master,分别绑定远端的私有库和开源库的master分支。
开源库的分支有很多,我选定master分支来使用,以获得及时更新的代码,这个根据实际情况来定,也可以选择product之类的分支来追求更稳定的代码。
上面是理论模型,下面我们从零开始一步步实现,现在我们什么也没有,就只知道开源库的地址。
1:创建私有库备用
登录https://github.com/new新建一个私有项目,这里就不做更多描述了。
2: 初始化本地项目
cd workdirmkdir my_project_namecd my_project_namegit init
这样我们就在my_project_name目录下新建了一个空的git项目。
3: 添加远程仓库到本地
我们现在有两个远程仓库,一个是刚刚创建的私有仓库,另一个是开源仓库。
# 添加私有仓库,别名为 origin(master) git remote add origin https://github.com/easelify/my_project_name.git# 添加开源仓库,别名为 upstream(master) git remote add upstream https://开源库地址
4: 创建本地分支并和远端分支绑定
# 拉取开源库(upstream)的master分支到本地(master) git fetch upstream master# 此时本地工作目录是空的, 检出到 upstream/master(master) git checkout master# 在本地创建up-master分支并将工作目录切换到此分支(master) git checkout -b up-master# 将本地的up-master分支和开源库(upstream)的master分支绑定(up-master) git branch -u upstream/master# 将本地工作目录切换回master分支(up-master) git checkout master# 将本地master分支推送到私有库(origin)# 即实现本地master分支和origin/master分支的绑定(master) git push -u origin master
通过上面的操作,我们的分支有了如下的对应关系:
master ===> origin/master
up-master ===> upstream/master
5: 定期拉取upstream/master代码合并到本地master分支
# 切换到up-master分支(master) git checkout up-master# 拉取代码, 注意一定要先切换到up-master分支(up-master) git pull upstream master# 切换到master分支(up-master) git checkout master# 将 up-master 的代码合并到 master 分支(master) git merge up-master
合并分支的时候如果出现代码冲突,有冲突的文件会被git标红, 通过 git status 可以看到未解决冲突的文件列表,手动解决完这些冲突后再执行 git add 和 commit 进行一次常规的提交即可。
本文所述的案例中,我们没有权限向开源仓库(upstream)提交代码,也没有这个需求,只需要定期更新代码并且合并到我们自己的项目即可。
如果觉得开源项目有需要改进的地方可以单独fork修改后提交pull request, 这不在本文的讨论范围了。其实也可以直接在master分支修改,只是这是私有化的代码,如果你想改进开源项目还是要提交提交pull request的。
6: 生产环境的代码部署
直接拉取私有库的master分支即可,本文为了方便叙述和理解只有一个master分支,在实际的应用中,可能会有dev, prod等分支,按需设定,按需取用即可。
至此开篇提出的需求完美解决,庆幸的是开源库更新非常快,使我有机会测试合并代码。
7: 其他同事加入开发
本文是以全新的空仓库开始的,如果有新同事加入项目,操作流程会稍有改变。不需要第2步 git init 初始化空项目了,直接 git clone 私有库地址即可,第3步也只需要添加远端的开源库了,后面的流程一样。
8: 直接编辑git的配置文件
上面我们都是通过一系列终端命令行来操作git项目配置的,如果你熟悉git的配置可以进入项目根目录下的 .git 目录,直接编辑config文件,本文项目的完整配置文件如下:
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true[remote "origin"] url = https://github.com/easelify/my_project_name.git fetch = +refs/heads/*:refs/remotes/origin/*[remote "upstream"] url = http://开源库地址 fetch = +refs/heads/*:refs/remotes/upstream/*[branch "master"] remote = origin merge = refs/heads/master[branch "up-master"] remote = upstream merge = refs/heads/master[pull] ff = only
9: 二进制文件冲突的解决
文本冲突可以直接编辑解决,如果是二进制文件,比如图片发生冲突的时候,使用以下命令选择保留哪一个文件。
# 使用 --ours 参数保留当前分支版本的文件git checkout --ours /path/to/file# 使用 --theirs 参数保留并入分支版本的文件git checkout --theirs /path/to/file
10: git常用命令设置
# 全局配置 - 别名git config --global alias.co checkoutgit config --global alias.br branchgit config --global alias.ci commitgit config --global alias.st status
配置别名后,可以用别名替代原有命令,可以少敲几个字母,例如可以使用 git st 代表 git status了,还是方便不少的,因为这些命令用到的频率实在太高了。
# 全局配置 - 提交和日志输出的字符集编码git config --global i18n.commitencoding utf-8git config --global i18n.logoutputencoding utf-8# 设置当前终端的less命令使用utf-8编码export LESSCHARSET=utf-8
在 Linux 下通过 git log 查看提交日志的时候,中文无法正常显示,配置上述编码后可正常显示中文。