Git 多仓库管理及代码同步

背景

在实际工作中,相信大家都有遇到过需要向两个或两个以上的远端代码仓库提交代码,或者向一个代码仓库拉取代码并同步到另一个代码仓库的情况。比如,我们就遇到过以下两种情况:

  • 基于开源项目的二开项目。为了获得开源项目的最新代码(功能),需要时不时的从开源项目的代码仓库(gitee.com、github.com等)拉取新代码,然后提交到本地二开后的代码仓库。
  • 我司最近做了一次研发环境的迁移,重新搭建一套新的研发环境,但是短时间内老的那套研发环境还会继续使用,因为进行中的研发任务还继续提交代码到老环境的代码仓库,新的研发任务则迁移到了新的代码仓库上进行开发。此时在老环境上开发的同事就需要将代码提交到老代码仓库的同时,也提交一份到新的代码仓库(当时,不要求实时同步,最终一致就可以了)。

那么我们如何通过Git的多仓库管理能力来轻松搞定同步提交代码到多个远程仓库呢?答案就是利用Git remote的多仓库管理功能来实现。具体的可以有三种方式搞定这个问题。

解决方案

下面以DRM项目为示例,跟着我来一步步体验一下这个过程吧

示例说明
代码仓库原始地址在gitee.com上
https://gitee.com/devon/drm.git
现迁移一份到我司代码仓库(我司用的是Gitea,自带有代码库迁移的功能)
http://code.example.com/devon/drm.git

目前两个代码库的代码是一样的。

方案一

配置两个独立仓库组,然后通过git push命令推送到指定仓库组仓库的方式实现代码同步。

当前仓库配置信息:

drm(master)$ git remote -v
origin  https://gitee.com/devon/drm.git (fetch)
origin  https://gitee.com/devon/drm.git (push)

添加我司代码仓库

drm(master)$ git remote add gttis http://code.example.com/devon/drm.git

指定代码仓库的别名,此处我使用 gttis 作为我司代码仓库的别名

添加完后查看仓库名称及地址

drm(master)$ git remote -v
origin  https://gitee.com/devon/drm.git (fetch)
origin  https://gitee.com/devon/drm.git (push)
gttis 	http://code.example.com/devon/drm.git (fetch)
gttis 	http://code.example.com/devon/drm.git (push)

可以看到我司的代码仓库已经成功添加了,但是此时你是没办法签出新仓库的代码分支的,因为它的仓库信息还没有被拉取下来。

所以我们需要通过fetch命令拉取新仓库的元数据信息(分支、标签等)

drm(master)$ git fetch gttis
From http://code.example.com/devon/drm
 * [new branch]      master     -> gttis/master

到这里两个远端仓库分支的信息都被拉到本地了。接下来,我们可以在一个分支上做一些代码修改,然后分别向两个仓库提交代码了。

我们修改了README.md文件

drm(master)$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git restore ..." to discard changes in working directory)
        modified:   README.md

提交代码到本地缓冲区

drm(master)$ git commit -a -m 'for testing'
[master ffd788b] for testing
 1 file changed, 1 insertion(+), 1 deletion(-)

接下来就到了验证成败关键时刻了

首先,将代码推到原代码仓库(gitee.com)

drm(master)$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 300 bytes | 100.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.0]
To https://gitee.com/devon/drm.git
   a45e294..ffd788b  master -> master

紧接着,将代码提交到我司代码仓库

drm(master)$ git push gttis
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 300 bytes | 100.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To http://code.example.com/devon/drm.git
   a45e294..ffd788b  master -> master

关键点是push的时候指定的远程仓库。

Bingo! 可以看到,同一份修改代码已经被推到了两个远端仓库。成功!

方案二

有没有可能一次提交就提交到多个代码仓库?答案是肯定的,方法就是向当前仓库组追加一个远端仓库地址。

查看当前仓库状态

drm(master)$ git remote -v
origin  https://gitee.com/devon/drm.git (fetch)
origin  https://gitee.com/devon/drm.git (push)

追加入我司代码仓库

drm(master)$ git remote set-url --add origin http://code.example.com/devon/drm.git
drm(master)$ git remote -v
origin  https://gitee.com/devon/drm.git (fetch)
origin  https://gitee.com/devon/drm.git (push)
origin  http://code.example.com/devon/drm.git (push)

这里是向默认仓库组origin追加一个新的推送(push)地址,从url后面的标识,不难看出,当执行fetch命令的时候,走的是gitee.com的地址,当推送的时候,将推给两个仓库。下面我们来验证一下

首先,还是做一些修改,并提交到本地缓冲区

drm(master)$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git restore ..." to discard changes in working directory)
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")
drm(master)$ git commit -a -m 'for testing'
[master 857bd40] for testing
 1 file changed, 1 insertion(+), 1 deletion(-)

然后,把修改推送到远程仓库

drm(master)$ git push origin
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 293 bytes | 146.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.0]
To https://gitee.com/devon/drm.git
   ffd788b..857bd40  master -> master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 293 bytes | 146.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To http://code.example.com/devon/drm.git
   ffd788b..857bd40  master -> master

从日志中可以看出它一次向两个仓库推送了代码。成功!

方案三

本方案的核心是添加多个仓库组,然后通过git merge 或者 git cherry-pick 的方式来管理代码,该方案相对自主选择性比较强些,但操作上也相对麻烦。

当前仓库名称及地址:

drm(master)$ git remote -v
origin  https://gitee.com/devon/drm.git (fetch)
origin  https://gitee.com/devon/drm.git (push)

添加我司代码仓库并查看结果:

drm(master)$ git remote add gttis http://code.example.com/devon/drm.git
drm(master)$ git remote -v
origin  https://gitee.com/devon/drm.git (fetch)
origin  https://gitee.com/devon/drm.git (push)
gttis 	http://code.example.com/devon/drm.git (fetch)
gttis 	http://code.example.com/devon/drm.git (push)

指定代码仓库的别名,此处我使用 gttis 作为我司代码仓库的别名

通过fetch命令拉取新仓库的元数据信息(分支、标签等)

drm(master)$ git fetch gttis
From http://code.example.com/devon/drm
 * [new branch]      master     -> gttis/master

到这里两个远端仓库分支的信息都被拉到本地了。接下来,我们可以在一个分支上做一些代码修改,然后通过git merge的方式将代码合并到另一个仓库分支并提交。

drm(master)$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git restore ..." to discard changes in working directory)
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")
drm(master)$ git commit -a -m 'for testing'
[master 857bd40] for testing
 1 file changed, 1 insertion(+), 1 deletion(-)
drm(master)$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 297 bytes | 99.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.0]
To https://gitee.com/devon/drm.git
   857bd40..5039fc8  master -> master

签出新仓库的Master分支代码

drm(master)$ git checkout -b gttis_master gttis/master
Switched to a new branch 'gttis_master'
Branch 'gttis_master' set up to track remote branch 'master' from 'gttis'.
drm(gttis_master)$ 

合并老分支的代码并提交

drm(gttis_master)$ git merge master
Updating 857bd40..5039fc8
Fast-forward
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drm(gttis_master)$ git push gttis HEAD:master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 297 bytes | 148.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To http://code.example.com/devon/drm.git
   857bd40..5039fc8  HEAD -> master

至此,我们搞定了向多个远端仓库提交代码的办法了。

当然,就我司而言,当环境迁移结束后,老代码仓库将被废弃,此时可以通过以下方式将老代码仓库删除,以方便后续开发。

删除老仓库

git_project(gttis_develop)$ git remote remove origin

将新仓库重名名为默认远端仓库名称

git_project(gttis_develop)$ git remote rename gttis origin

总结

本篇文章主要向大家介绍了通过Git中的多仓库管理能力来实现仓库间代码同步的方法。其核心就是通过Git remote对多个远端仓库的管理能力,至于选择那个方案,可以根据自身项目的情况自由选择。

Never too late to life is a long long journey.

你可能感兴趣的:(代码管理,git)