0%

20 分钟教你搭建 Gitlab

logo

在部署 Gitlab 前,先了解一下 Git 的原理和使用方法,如已熟悉直接跳过第一章

一、Git 使用入门

GIT 的由来
Linux 内核代码需要版本管理工具维护代码,2002 年开始,使用的是 BitMoverBitKeeper 公司的这个商用软件。但是 Linux 社区崇尚的是自由软件相悖。2005 年,Andrew TridgellBitKeeper 对协议进行逆向工程,BitKeeper 作者决定收回无偿使用授权。磋商无果,Linus 又找不到合适的版本管理工具,决定自行开发分布式版本管理工具,一个月后,Linux 内核代码被 Git 接管。2008 年,基于 WEB 使用 Git 进行版本控制的软件托管服务的网站 GitHub 上线。

2016 年 5 月 9 日,11 年后,BitKeeper 开源,发布在了 GitHub 上

1. Git 的概念和目录结构

概念(Dev)

work2

  • Repository 仓库、版本库:
    • git 初始化后,会在当前目录生成一个 git 目录,这就是版本库。
  • Workspace 工作空间、工作区:
    • git 所在的目录就是工作区,一般是项目的根目录。
  • index 索引:
    • 介于工作区和版本库之间,暂存修改的。
  • remote 远程版本库
    • 网络上的另一个版本库,可以和本地库交互。

目录结构(Ops)

把仓库克隆到本地后,会在仓库目录下创建一个隐藏目录 .git,整个仓库的内容都在 .git 这个目录中。

用户在编辑文件时,是不会对 .git 中的内容直接修改的。在克隆完成后,会把 .git 中的内容复制出一份,放在与 .git 同级的目录中,用户是直接修改这些文件的。如果认为修改完成了一个阶段,可以提交到仓库中。

其中:

  • 仓库目录被称为 工作目录
  • .git 同级的目录被称为 工作区,文件的修改都是在此进行;
  • .git 目录本身被称为 版本库

work

2. Git 的工作逻辑

首先了解,Git 是个对象存储系统,在版本库中有两个核心组件:

  • 索引:也叫暂存区,保存文件对象的对应关系;
  • 对象库:文件真正的存放位置;

假设在一个新仓库中,新建 2 个文件,这两个文件是保存在工作目录中的。
1

等到完成一个阶段的修改后,希望数据保存一下时,可以使用 git add 命令把数据保存到对象库中一份,变成版本库中可追踪的文件。这时文件存在 2 份,一份在工作目录中,一份在对象库中。

所不同的是工作目录中的文件名是你自己定义的,而对象库中是把文件的 hash 码作为文件名,叫文件对象。索引当中存放的是这两个文件对象所对应的文件名,以及对应关系等,相当于为每一个文件对象建立一个元数据信息。
2

但如果文件不需要修改了,可以作为一个版本发布了,就可以使用 git commit 执行提交操作。提交操作时会把索引本身做成快照,保存到对象库中。此时对象库中会有 3 类对象,文件对象、索引对象和提交对象。提交对象是用来描述快照本身的信息的,记录了提交快照的时间、快照名、索引名等等一些信息。

任何对象都是以 hash 码为名字保存在对象库中,在对象库中目录也被保存为一个对象,且没有层级关系。

对象库中的文件为了快速检索,按 hash 值分级存放,而目录本身的层级关系则在索引中保存。
3

如下图,假设对左边的文件做了修改,而右边的保持原样。再提交时,改动后的文件会作为一个新文件保存,不会覆盖修改前的文件,因为文件是以 hash 码命名保存的,当文件发生变化时,hash 也一定不一样,只要 hash 码不同,文件就不会被覆盖。而 git 内部通过一个压缩结构,使不同文件中相同的部分可以指向同一个磁盘块,但是用户看到的却是不同的文件。
4

此时再次通过 git add 追加刚刚修改后的文件时,会生成一个新的索引(蓝色),指向修改后的文件,而不是老版本文件。而旧的索引快照(黄色)依然指向老版本,此时如果想恢复旧的版本,只要把旧的索引快照(黄色)恢复到索引区中替代掉目前的索引(蓝色)即可。

如果使用 git commit 提交,会再次把新的索引(蓝色),保存为一个对象存到对象库中。
5

Git 的工作逻辑:索引其实是暂存区,是通过 git add 生成的。暂存后可以不断的修改,需要提交时使用 git commit 才会把数据真真正正的永久留存在版本库中。如果索引中的内容不要了,需要还原成工作目录,使用 git rm --cached 来还原。

6

Git 的对象类型存放在 .git/objects 中,分为:

  • 块(blob)对象:文件的每个版本表现为一个块(blob);
  • 树(tree)对象:一个目录代表一层目录信息;
  • 提交(commit)对象:用于保存版本库一次变化的元数据,包括作者、邮箱、提交日期、日志;每个提交对象都指定一个目录树对象;
  • 标签(tag)对象:用于给一个特定对象一个易读的名称;

3. Git 基本概念的补充

Git 的配置文件,对应了不同的生效范围

  • 仓库持有:REPO/.git/config
  • 用户全局:~/.gitconfig
  • 系统全局:/etc/git/gitconfig

Git 仓库

  • 索引:也就是暂存区;
  • 对象库:也就是版本库;

Git 中的文件分类有 3 类

  • 已追踪的(tracked):已经在版本库中,或者已经使用 git add 命令添加至索引中的文件;
  • 被忽略的(Igored):在版本库中通过“忽略文件列表”明确声明为被忽略的文件;
  • 未追踪的(untracked):上述两类之外的其它文件;

4. Git 的命令

发现了一个不错的 Git 教程网站:猴子都能懂的 GIT 入门

基础命令

  • git glone URL:克隆仓库;
  • git init:在目录内将指定的仓库进行初始化;
  • git status:查看状态。
  • git add FILE:单个文件添加到索引(暂存区)中,空目录不会被添加;添加后在 REPO/.git/objects/$HASH/$HASH 中;
  • git add .:批量添加,点号 . 代表当前目录,这条命令将递归添加当前目录及其子目录所有文件。只要是目录,就会递归添加该目录下的文件和子目录;
  • git rm:删除工作目录中的文件,及索引中的文件的映射关系,真删除;但是,Git 无法删除对象库中的文件;
    • git rm --cached file:只删除索引中的映射,不删除工作目录中的文件;将文件从暂存转成未暂存,即文件恢复成不追踪的状态;
  • git mv:改变工作目录中的文件名,及索引中的相关映射;
  • git config -l:查看当前仓库的配置;
  • git config [--global ] --add key value:添加一个参数,默认添加到仓库配置中;
    • 例:git config --add user.name monster:添加一个用户参数;
    • 例:git config --add user.email 'admin@monster.com':添加一个用户的邮件参数;
  • git ls-files [ -c -d -m -s --directory ]:查看不同状态的文件的相关信息,权限、hash 等;
    • -c:列出已经缓存的文件(default);
    • -o:列出没有被追踪的文件;
    • -d:列出已经删除的文件;
    • -m:列出已经修改的文件;
    • -s:列出暂存区(stage area)中的文件信息:权限、对象名、暂存号及原始文件名;;
    • --directory:显示目录中的文件;
  • git cat-file -p OBJECT_HASH*4:显示仓库中指定对象的文件内容;OBJECT_HASH 最少可以只写 4 位;
    • -p:美观排版显示文件内容;
  • git hash-object --stdin FILE:计算文件的 hash 码;
    • --stdin:输出到标准输出;

git 提交相关

git 的提交分为两个步骤:

  1. 暂存变更:add 作用是把新文件或者文件新的改动添加到一个暂存区 stage,也就是加入到 index 中;
  2. 提交变更:commit 提交的是暂存区中的改动,而不是物理文件目前的改动,提交到当前分支,默认是 master 分支;

也可以使用下面命令,将两步合成一步

1
git commit index.html

如果改动一批文件,一个个写名字很麻烦,使用下面的命令

1
git commit -a -m "message"
  • git commit -a -m "release_name":提交;
    • -a-all:会把所有跟踪的文件的改动自动暂存;
    • -m "release_name":指定提交的版本信息;
  • git log:显示提交历史日志;
  • git clone SRC_DIR DST_DIR:在本地克隆仓库,指定源目录,再指定目标目录即可;

life_cycle

增补

如提交后,忘记加入一个文件,比如 about.html

使用:

  • --amend:修改,通过创建一个新的 commit,会代替当前分支的顶部。
1
2
$] git add about.html
$] git commit --amend -m "append commit"

git log 查看一下版本库里面提交的历史记录。

分支相关

每个提交都有一个唯一的标识称为 绝对提交名,但是可以使用多个别名来引用,比如:IDreferenceSHA1

名称存放目录:

  • .git/refs/heads/REF:保存本地特性分支名称;
  • .git/refs/remotes/REF:保存远程跟踪分支名称;
  • .git/refs/tags/REF:标签名;

Git 还会在 .git 中自动维护几个特定目的的特殊符号引用:

  • HEAD:可以看做是一个游标,始终指向当前分支的最近提交;或切换到其它分支时,则指向目标分支的最近提交;
    • HEAD 的值储存在 .git/HEAD 中;
    • HEAD:指最后一次 commit;
    • HEAD^:指上一次提交;
    • HEAD^^:指上上一次提交;
    • HEAD~n:指上 n 次提交;
  • ORIG_HEAD:合并操作时,指向新生成的提交的前面的一个提交;
  • FETCHED_HEAD:从远程服务器上克隆下来的分支;
  • MERGE_HEAD:合并操作时,其它分支的上一次提交;

使用 diff 比较不同

  • git diff:将当前工作目录与当前的索引相比较;
  • git diff --cached:将索引与当前分支的最新一次提交相比较;
  • git diff HEAD:将当前工作目录与当前分支的最新一次提交相比较;
  • git diff BRANCH_NAME:当前分支最新一次提交与其他分支最新一次提交;
    • --color:显示颜色;

git_diff

检出

checkout 用于切换分支,或恢复工作区文件。

注意checkout 会重写工作区,这个命令还是较为危险的。

命令 说明
git checkout 列出暂存区可以被检出的文件
git checkout file 从暂存区检出文件,覆盖工作区文件,可指定检出的文件。但是不清除 stage
git checkout commit file 检出某个 commit 的指定文件到暂存区和工作区
git checkout . 检出暂存区的所有文件到工作区
1
2
3
4
5
6
7
8
echo > about.htm # 清除工作区文件内容
git checkout about.htm # 从暂存区检出到工作区,工作区文件有了内容
git checkout HEAD about.htm # 使用当前分支的最后一次 commit 检出覆盖暂存区和工作区

# 下面 3 条命令结果一致了
git diff
git diff --cached
git diff HEAD

重置(撤销提交)

如果对 checkout 和 reset 有些混沌,不妨看看这篇:
7.7 Git 工具 - 重置揭密

  • git reflog:显示 commit 的信息,只要 HEAD 发生变化,就可以在这里看到
  • git reset:列出将被 reset 的文件;
  • git reset [ OPTION ] <COMMIT_ID>:撤消指定的提交,重置当前分支的 HEAD 为指定 commit,同时重置暂存区,但工作区不变;
    • --soft:不改变索引和工作目录;
      • 等于撤销了 git commit
    • --mixed(default):将索引内容改变为指定提交的快照,但不改变工作目录;
      • 等于追加了:撤销 git add
    • --hard:将索引内容改变为指定提交的快照,并改变工作目录中的内容为指定提交的内容;
      • 等于追加了:把指定提交版本的文件释放到工作区,工作区之前的文件则全部消失;

通过路径来重置:

  • git reset <paths>:将 暂存区 中,指定的文件或文件集合,重置为和上一次 commit 一致,工作区不影响;
    • git reset --mixed HEAD <paths> 的简写形式
    • 本质上只是将 file 从 HEAD 复制到索引中。
1
2
3
4
5
6
git add about.html     # 添加到暂存区
git reset about.html # 使用最后一次提交覆盖暂存区
cat about.html # 工作区文件有内容
git add about.html # 添加到暂存区
git reset--hard # 重置暂存区与工作区为上一次 commit
cat about.html # 工作区文件无内容

git_reset

暂存 stash

命令 说明
git stash 暂时存储最后一次提交后的变化,放入栈中
git stash pop 从栈中取出刚才保存的变化,并合并

主要在 Pycharm 中操作。

应用场景:

  • 开发中,当前手中的工作没有完成,需要中断当前工作来完成其他请求,例如修复 bug。
  • 已完成的工作内容提交不合适,可能还要需要大的调整,但是紧急请求又不能不做,就需要 stash 存储未完成的工作(上次提交后做的修改)。

分支创建、删除与合并

使用 git branch 可以列出、创建及删除分支:

  • git branch --list:列出分支;结果中的 * 表示当前分支;
  • git branch BRANCH_NAME [START_COMMIT]:创建分支;
  • git branch -d BRANCH_NAME:删除一个分支;
  • git show-branch:显示分支详细信息;
  • git checkout BRANCH_NAME:切换分支;

Git 分支合并:把其他分支合并到当前分支;

  • 合并基础:要合并的分支的最近一次的共同提交;
  • 我们的版本:当前分支的最近一次提交;
  • 他们的版本:要合并进来的分支的最近一次提交;

无冲突合并步骤:

1
2
3
4
~]# git checkout master
~]# git status
~]# git merge BRANCH_NAME
~]# git log --graph --pretty=oneline --abbrev-commit

有冲突合并步骤:

1
2
3
4
5
6
~]# git merge BRANCH_NAME
~]# git diff # 查看不同
# 1、手动解决冲突;
# 2、解决完成之后;
~]# git add
~]# git commit

Fast Forward 合并

ff

上面 dev 分支是开发中的代码,dev 测试、审查后合并 master 中 master 分支都是稳定的代码,可以发布。

在 Pycharm 中合并分支时,默认 NoFF 不勾选的,也就是默认使用 FF 的方式合并。

no-ff 的好处是,可以看清楚开发分支上的代码改动。

5. Git 远程仓库

  • 可用的网络协议:http, https, ssh, git;
  • 克隆操作:git clone
  • 原始版本库存储在:refs/heads/

Git 服务器支持协议:

  • 本地协议 (local)、HTTP/HTTPS 协议、SSH 协议、Git 协议;

本地远程库两种访问方式:

  • /path/to/repo.git
  • file:///path/to/repo.git

基本命令

  • git remote:显示远程仓库的名字;远程仓库被拉取到本地后,名字会默认被保存为 origin
  • git clone -o NEW_REPO_NAME https://XXXXXXXX:如果不想使用默认的 origin,克隆时可以使用 -o 指定保存为其他名字;
  • git remote -v:显示推送和拉去路径;
  • git remote show REPO_NAME:显示详细的信息;
  • git remote add REPO_NAME URL:添加另外的远程仓库地址;
  • git remote rm REPO_NAME:删除指定的远程仓库地址;
  • git remote rename OLD_REPO_NAME NEW_REPO_NAME:重命名指定的远程仓库地址;

分支相关命令

  • git branch -a:显示所有分支;
  • git branch -r:只显示远程分支;
  • git checkout -b <本地新分支名> REMOTE_REPO_NAME REMOTE_BRANCH_NAME:把指定远程仓库中的指定分支拉取到本地,并改变为新的分支名;
  • git fetch <远程主机名> <远程分支名>:将远程服务器中指定分支的更新取回本地,但不会自动与本地合并;不指定分支则默认取回全部分支;

拉取和推送

  • git pull <远程主机名> <远程分支名>:<本地分支名>:取回远程服务器更新,而后与本地的指定分支合并;
  • git push <远程主机名> <本地分支名>:<远程分支名>:将本地的更新推送到远程主机;

二、Gitlab 在企业中的应用

logo

1. 安装说明

以下安装过程参考官方的 Gitlab-ce 版本的安装教程:
https://about.gitlab.com/install/#centos-7?version=ce

安装依赖

先安装依赖包。

1
2
3
4
5
sudo yum install -y curl policycoreutils-python openssh-server openssh-clients

sudo yum install postfix
sudo systemctl enable postfix
sudo systemctl start postfix

安装 Gitlab 的 yum 仓库。

1
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash

安装 Gitlab 程序包

接下来,安装 GitLab 程序包。将下面的 https://gitlab.example.com 更改为您希望访问 GitLab 站点时使用的 URL。安装时将自动把 Gitlib 配置在该 URL 上并启动。

如果使用 https:// 会自动从 Let’s Encrypt 申请证书,这可能会导致安装失败,如不需要使用 SSL 连接,请使用 http://

1
sudo EXTERNAL_URL="http://gitlab.example.com" yum install -y gitlab-ce

如果下载太慢,也可以先手动下载安装包,地址 https://packages.gitlab.com/gitlab/gitlab-ce

然后上传到服务器,使用 YUM 从本地安装:

1
sudo EXTERNAL_URL="http://gitlab.example.com" yum install -y /root/gitlab-ce-12.3.5-ce.0.el7.x86_64.rpm

后续步骤

程序安装好后,从浏览器访问即可,我这里使用的 URL 为:http://node1.monster.com/

注意:

  1. 第一次登陆需要配置 root 密码;
  2. 使用 root 管理员账号登录;

2. 定义其他功能

关闭用户注册功能

为了安全,建议关闭首页上的用户注册功能,否则能访问站点的用户都可以自行注册账号了,步骤:

  1. 先使用 root 管理员登录;
  2. 点击扳手图标,然后点左下角 Settings,然后找到 Sign-up restrictions 点击 Expand
    • 注意:千万不要点错把 Sign-in restrictions 关闭了。
  3. Sign-up enabled 这个选项前面的 去掉。
  4. 点击 Sava changes 保存即可。

然后退出登录,再看首页上应该只有登录选项了。

定义中文界面

User Settings > Preferences > Localization > language 中选择 简体中文

组权限表

群组成员权限表参考:

配置 Gitlab 管理员邮箱

首先注意:配置邮箱的时候,一定要使用 ssl,然后使用 465 的邮箱端口,不然就发送不出去了。

(1). 编辑配置文件

vim /etc/gitlab/gitlab.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.163.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "your_email_address@163.com"
gitlab_rails['smtp_password'] = "your_email_password"
gitlab_rails['smtp_domain'] = "163.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true

# 配置邮箱来源, 与展示的名称
gitlab_rails['gitlab_email_enabled'] = true
gitlab_rails['gitlab_email_from'] = 'ljfchou@163.com'
gitlab_rails['gitlab_email_display_name'] = 'Gitlab_admin'
(2). 重新加载配置服务

重新加载配置文件后生效。

1
gitlab-ctl reconfigure
(3). 发送测试邮件
1
2
3
4
5
# 进入控制台
gitlab-rails console

# 然后发送邮件
Notify.test_email('your_email_address@qq.com', '邮件标题', '邮件正文').deliver_now

如果配置正常,过不了一会,应该就可以收到邮件了。

3. 使用 Gitlab 命令行工具

主配置文件在: /etc/gitlab/gitlab.rb

Gitlab 提供了一个命令行工具,可以批量控制 Gitlab 的所有服务的启动、停止、重启和查看运行状态等功能:

  • service-list:列出所有服务;正在运行的服务带有 *
  • gitlab-ctl start <start | stop | restart>:启动、停止、重启所有服务;
  • gitlab-ctl status:查看所有服务的运行信息;
  • gitlab-ctl diff-config:显示主配置文件中的差异变化;