Git与Gitlab协同开发

什么是git

git是一个 分布式版本控制软件,最初由林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以GPL发布。
最初目的是为更好地管理Linux内核开发而设计。应注意的是,这与GNU Interactive Tools(一个类似Norton Commander界面的文件管理器)有所不同。
git最初的开发动力来自于BitKeeper和Monotone。git最初只是作为一个可以被其他前端(比如Cogito或Stgit)包装的后端而开发的,但后来git内核已经成熟到可以独立地用作版本控制。
很多著名的软件都使用git进行版本控制,其中包括Linux内核、X.Org服务器和OLPC内核等项目的开发流程。 ——维基百科

为什么使用git

  • 传输速度快, 查看历史版本快
  • 登录认证更安全 - SSH RSA认证
  • 分支合并更方便
  • Git版本库占用空间小
  • 代码托管更安全 - 分布式托管
  • 大量文件add, submit不会奔溃
  • 更强大的功能: git bash

git安装

Ubantu/Debian

apt-get install git

Mac/Windows

官网下载相对应平台的git版本, 如果需要GUI客户端, 可在这个链接下载: GUI Clients

很多IDE, 比如VSCode WebStormd等都集成git面板, 可以代替git客户端来执行git操作

补充: Windows平台VSCode终端集成git bash

VSCode默认的终端是cmd/power shell, 我们可以在上面的链接下载安装git后, 将VSCode的终端设置为bash

  1. 安装完git后, 找到bash.exe的路径
    bash路径

  2. 打开VSCode用户设置, 修改终端使用路径

    1
    2
    3
    {
    "terminal.integrated.shell.windows": "C:\\Program Files\\Git\\bin\\bash.exe" // 你的bash.exe路径
    }
  3. ctrl + `打开VSCode控制台, 看到你的终端是bash说明设置已经成功
    VSCode-terminal

git基本操作

廖雪峰-Git教程

代码托管平台Gitlab

Gitlab是一个类似Github的基于Ruby on Rails开源版本管理系统, 实现一个自托管的Git项目仓库, 可通过Web界面访问公开或私人项目.

操作入门

  1. LDAP方式登录Gitlab

  2. 明确自己的name和email

  3. 在git bash中执行生成ssh key
    ssh-keygen -t rsa -C "your.email@example.com"

  4. Gitlab SSH Keys管理
    cat ~/.ssh/id_rsa.pub
    把公钥发布到Gitlab平台的SSH Keys上

  5. 测试ssh的rsa免密码认证是否成功
    ssh -T -vvv git@[Gitlab域名].com

  6. git全局设置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    git config --global push.default simple
    git config --global core.quotepath false
    git config --global core.autocrlf false
    git config --global core.longpaths true
    git config --global user.name "$name"
    git config --global user.email "$email"
    git config --global alias.st status
    git config --global alias.ci commit
    git config --global alias.co checkout
    git config --global alias.br branch
  7. 按不同的Gitlab域名或用户来选择证书
    vi ~/.ssh/config

    1
    2
    3
    4
    5
    6
    7
    Host gitlab1
    HostName git1.xxx.com
    IdentityFile C:/Users/myuser1/.ssh/id_rsa
    User git
    Host git2.xxx.com
    IdentityFile C:/Users/myuser2/.ssh/id_rsa
    User git
  8. 创建新的仓库(repository)
    在Gitlab创建好一个project, 接着执行

    1
    2
    3
    4
    5
    6
    git clone git@xxx.com/:author/hello-world.git
    cd hello-world
    cd touch README.md
    git add README.md
    git commit -m "Add README"
    git push -u origin master

    上面操作主要做了:

    • 从远程git仓库拷贝(clone)到本地仓库, 然后进入项目目录
    • 创建一个README markdown文件, 该文件一般是保存对项目的说明和操作流程等等需要告知使用着的信息
    • 将README.md添加(add)到索引中, 并提交(commit)
    • 最后推送(push)到远程master分支
  9. 本地项目关联到远程仓库

    1
    2
    3
    4
    5
    6
    cd existing_folder
    git init
    git remote add origin git@xxx.com/:author/hello-world.git
    git add .
    git commit -m "Add all files"
    git push -u origin master

    上面操作主要做了:

    • 进入项目目录, git初始化
    • 添加远程仓库关联
    • 接下来就是做提交推送的操作

Git与Gitlab协同开发

仓库(Repository)

源仓库(线上版本库)

在项目的开始, 项目的发起人构建一个项目的最原始的仓库, 成为origin. 用于汇总参与项目的各个开发者的代码和存放趋于稳定和可发布的代码.

源仓库应该是受保护的, 开发者不应该直接对其进行开发工作. 只有项目管理者能对其进行较高权限的操作

开发者仓库(本地仓库)

任何开发者都不会对源仓库进行直接操作, 源仓库建立后, 每个开发者需要将源仓库fork到自己日常开发的仓库. 每个开发者fork后的仓库都是完全独立, 互不干扰的. 当开发工作完成后, 开发者可以向源仓库发送pull request, 请求源仓库管理员把自己的代码合并到源仓库中, 这样就实现了分布式工作和集中式管理.

分支

master(主分支)

主分支从项目开始就一直存在, 它存放经过测试后已经稳定的代码, 在项目开发以后的任何时刻, master存放的代码应该是作为产品供用户使用的代码

master分支的代码应该保持代码整洁和稳定, 确保入库前都应该通过完全测试和code review.

master分支是所有分支中最不为活跃的分支, 大概每个月或每两个月更新一次, 每次更新的时候都应该用git打上tag来说明产品有新版本发布.

develop(开发分支)

develop分支一开始从master分支分离出来, 用于开发者存放基本稳定的代码.

每个开发者的仓库相当于源仓库的一个镜像, 每个开发者自己的仓库上也有master和develop. 开发者完成功能后, push到自己的develop分支, 测试完成后, 向源仓库发起pull request, 请求管理员将自己的develop分支merge到源仓库的develop分支中.

所有开发者开发的功能都会在源仓库的develop分支中汇总. 当develop分支的代码不断测试, 逐渐趋于稳定接近产品目标, 这时就可以将develop分支merge到master分支, 发布新版本.

注: 任何人都不应该向master分支进行无意义的push/merge操作. 正常情况下, master只接受来自develop的合并.

feature(功能分支)

feature分支用于开发项目的功能分支, 存放各个功能的代码.

开发者在本地仓库从develop分支开多一个功能分支, 在该分支下进行开发, 完成之后再merge到develop分支上, 这时候功能性分支已经完成任务, 可以将其删除.

功能分支一般将其命名为feature-, 为功能名称.

集中式工作流(适用于1-3人协同开发)

当两个开发者从中心仓库clone代码下来, 同时作了一些代码更改, 只有在第一个开发者已经成功push代码到远程仓库中, 第二个开发者在push前, 必须先下载并合并远程仓库代码, 解决冲突后才能进行push到远程仓库.

  1. 创建源仓库
    由项目发起人进行操作, 假设源仓库为mygroup/myproject, 并初始化两个分支develop和master.

  2. clone源仓库到本地
    git clone git@git.xxx.com:mygroup/myproject.git

  3. 创建功能分支进行开发
    假设现在要开发一个”资产收集”功能

    • 首先切换到develop分支
      git checkout develop
    • 分出一个功能分支
      git checkout -b feature-gather_facts
    • 假设gather-facts.js是完成功能的文件
      1
      2
      git add gather-facts.js
      git commit -m "Finished gather-facts feature"
  4. feature-gather_facts分支的功能已经完成, 切换回develop
    git checkout develop

  5. 从源仓库pull下来最新的代码, 如果有合并冲突先解决冲突

    1
    2
    3
    git pull
    // or
    git fetch && git merge
  6. 将feature-gather_facts分支merge到develop分支
    git merge --no-ff feature-gather_facts

  7. 删除feature-gather_facts
    git branch -d feature-gather_facts

  8. 将本地develop分支push到远程仓库
    git push origin develop

集成管理员工作流(适用于3人以上协同开发)

由于git允许多个远程仓库, 开发者可以建立自己的公共仓库, 往里面写数据并共享给他人, 同时又可以从别人的仓库中提取他们的更新. 这种情况下通常有个官方发布的项目仓库, 开发者们由此仓库克隆出一个自己的公共仓库, 然后将自己的提交推送上去, 请求官方仓库的维护者拉取更新合并到主项目. 维护者在自己的本地也有克隆仓库, 他可以将你的公共仓库作为远程仓库添加进来, 经过测试无误以后合并到主分支, 然后再推送到官方仓库.

  1. 创建源仓库

  2. 开发者fork源仓库
    源仓库建立后, 每个开发者都可以fork到自己的gitlab上, 作为自己开发所用的仓库. 假设我的gitlab账号是myuser, 我从源仓库mygroup/myproject fork到myuser/myproject

  3. clone源仓库到本地
    git clone git@git.xxx.com:myuser/myproject.git

  4. 开发功能, 推送到自己的远程仓库等步骤参考上一个标题

  5. 向管理员提交pull request
    经过测试之后, 在myuser/myproject中发起pull request, 请求源仓库管理员把自己的develop分支合并到源仓库的develop分支

  6. 管理员测试, 合并
    管理员需要对开发者的pull request进行code review, 然后新建测试分支, 测试开发者的代码

    • 进入管理员本地的develop分支
      git checkout develop
    • 从develop分支分出一个manager-develop的测试分支测试开发者代码
      git checkout -b manager-develop
    • 把开发者代码pull到测试分支中进行测试
      git pull git@git.xxx.com:myuser/myproject.git develop
  7. 管理员测试, 合并
    经过测试没问题, 管理员可以将开发者代码合并到源仓库的develop中

    1
    2
    3
    4
    git checkout develop
    git merge --no-ff manager-develop
    git branch -d manager-develop
    git push origin develop

Gitlab权限控制

  • 授权形式
    只能对整个project授权, 不能针对project内的目录或文件精确授权

  • 授权原则

    • 注意控制gitlab中project的权限
    • 普通开发者给予Developer角色
    • 只有Owner角色才能删除project, 不要随意授权其他人Owner权限
    • 集成管理员工作流一般需要Master角色, 集中式工作流通常无需创建Master角色
    • Developer角色无法直接将代码合并到master分支, 但可以发起pull request, 通知Master角色或Owner角色处理, 保障master分支的代码是完整的, 正确的, 及时拦截Developer角色提交存在的问题