第 1 章 Git 版本控制系统
1.1、Git、Github、Gitlab 的区别
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Github 是在线的基于 Git 的代码托管服务。 GitHub 是 2008 年由 Ruby on Rails 编写而成。GitHub 同时提供付费账户和免费账户。这两种账户都可以创建公开的代码仓库,只有付费账户可以创建私有的代码仓库。
Gitlab 解决了这个问题,可以在上面创建免费的私人仓库。
git:是一套软件,可以做本地私有仓库。
github:本身是一个代码托管网站,公有和私有仓库(收费),不能做本地私有仓库。
gitlab:本身也是一个代码托管的网站,功能上和 github 没有区别,公有和私有仓库(免费)可以部署本地私有仓库。
1.2、Git 与 SVN 区别
Git 不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。
如果你是一个具有使用 SVN 背景的人,你需要做一定的思想转换,来适应 Git 提供的一些概念和特征。
Git 与 SVN 区别
- Git 是分布式的,SVN 不是,这是 Git 和其它非分布式的版本控制系统,例如 SVN,CVS 等,最核心的区别。
- Git 把内容按元数据方式存储,而 SVN 是按文件存储,所有的资源控制系统都是把文件的元信息隐藏在一个类似 .svn,.cvs 等的文件夹里。
- Git 分支和 SVN 的分支不同,分支在 SVN 中一点不特别,就是版本库中的另外的一个目录。
- Git 没有一个全局的版本号,而 SVN 有,目前为止这是跟 SVN 相比 GIT 缺少的最大的一个特征。
- Git 的内容完整性要优于 SVN,Git 的内容存储使用的是 SHA-1 哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。
git:是分布式的版本控制器,没有客户端和服务器端的概念。
svn:它是 C/S 结构的版本控制器,有客户端和服务器端,服务器如果宕机而且代码没有备份的情况下,完整代码就会丢失。
1.3、部署 Git 服务
1.3.1、创建 git 仓库
git-server 上的操作:
[root@arm64v8 ~]# yum install git gitweb -y
[root@arm64v8 ~]# useradd git
[root@arm64v8 ~]# echo "Brinnatt@487X" | passwd --stdin git
[root@arm64v8 ~]# su - git
Last login: Sat Mar 5 20:06:49 CST 2022 on pts/0
[git@arm64v8 ~]$
[git@arm64v8 ~]$ mkdir git-root
[git@arm64v8 ~]$ cd git-root/
[git@arm64v8 git-root]$
[git@arm64v8 git-root]$ git init --bare shell.git
Initialized empty Git repository in /home/git/git-root/shell.git/
[git@arm64v8 git-root]$
[git@arm64v8 git-root]$ ls shell.git/
branches config description HEAD hooks info objects refs
[git@arm64v8 git-root]$
- git init 和 git init --bare 的区别:
- 使用 --bare 选项时,不再生成 .git 目录,而是只生成 .git 目录下面的版本历史记录文件,这些版本历史记录文件也不再存放在 .git 目录下面,而是直接存放在版本库的根目录下面。
- 用 "git init" 初始化的版本库用户也可以在该目录下执行所有 git 方面的操作。但远程的用户再将更新代码 push 上来的时候容易出现冲突。
- 使用 "git init --bare" 方法创建一个所谓的裸仓库,之所以叫裸仓库是因为这个仓库只保存 git 历史提交的版本信息,而不允许用户在上面进行各种 git 操作,如果你硬要操作的话,只会得到下面的错误(”This operation must be run in a work tree”)这个就是最好把远端仓库初始化成 bare 仓库的原因。
1.3.2、git 仓库测试
git-client 上的操作:
[root@armcli ~]# yum install git -y
[root@armcli ~]# ssh-keygen -t rsa
[root@armcli ~]# ssh-copy-id -i git@arm64v8
[root@armcli ~]# mkdir localgit
[root@armcli ~]# cd localgit/
[root@armcli localgit]# git config --global user.email "brinnatt@gmail.com"
[root@armcli localgit]# git config --global user.name "Brinnatt"
[root@armcli localgit]# git clone git@arm64v8:/home/git/git-root/shell.git
Cloning into 'shell'...
warning: You appear to have cloned an empty repository.
[root@armcli localgit]# ls
shell
[root@armcli localgit]#
[root@armcli localgit]# cd shell/
[root@armcli shell]# vim test.sh
#!/bin/bash
echo "hello world"
[root@armcli shell]# git add test.sh
[root@armcli shell]# git commit -m "first commit, changed test.sh"
[master (root-commit) 7b55201] first commit, changed test.sh
1 file changed, 2 insertions(+)
create mode 100644 test.sh
[root@armcli shell]#
[root@armcli shell]# git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 247 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@arm64v8:/home/git/git-root/shell.git
* [new branch] master -> master
[root@armcli shell]#
再找一台 armcli2 的服务器:
[root@armcli2 ~]# yum install git -y
[root@armcli2 ~]# git clone git@arm64v8:/home/git/git-root/shell.git
[root@armcli2 ~]# cd shell/
[root@armcli2 shell]# ls
test.sh
[root@armcli2 shell]# cat test.sh
#!/bin/bash
echo "hello world"
[root@armcli2 shell]#
- 经验证,Git 服务部署成功。
1.4、Git 工作流程
一般工作流程如下:
- 克隆 Git 资源作为工作目录。
- 在克隆的资源上添加或修改文件。
- 如果其他人修改了,你可以更新资源。
- 在提交前查看修改。
- 提交修改。
-
在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。
Git 的工作流程示意图:
1.5、Git 基本概念
- 工作区:.git 所在的目录就是工作区,一般是项目的根目录。
- 暂存区:英文叫 stage,或 index。一般存放在 "git 目录" 下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
- 版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。
工作区、版本库中的暂存区和版本库之间的关系的示意图:
-
图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage,index),标记为 "master" 的是 master 分支所代表的目录树。
-
图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。
-
图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。
-
当对工作区修改(或新增)的文件执行 "git add" 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的 ID 被记录在暂存区的文件索引中。
-
当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
-
当执行 "git reset HEAD" 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
-
当执行 "git rm --cached (file)" 命令时,会直接从暂存区删除文件,工作区则不做出改变。
-
当执行 "git checkout ." 或者 "git checkout -- (file)" 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。
-
当执行 "git checkout HEAD ." 或者 "git checkout HEAD (file)" 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
1.6、Git 客户端安装使用
1.6.1、Git 安装
[root@arm64v8 ~]# yum install git -y
[root@arm64v8 ~]# git version
git version 1.8.3.1
1.6.2、Git 配置
Git 提供了一个叫做 git config 的工具,专门用来配置或读取相应的工作环境变量。
这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方:
/etc/gitconfig
文件:系统中对所有用户都普遍适用的配置。若使用git config
时用--system
选项,读写的就是这个文件。~/.gitconfig
文件:用户目录下的配置文件只适用于该用户。若使用git config
时用--global
选项,读写的就是这个文件。- 当前项目的 Git 目录中的配置文件(也就是工作目录中的
.git/config
文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config
里的配置会覆盖/etc/gitconfig
中的同名变量。
1.6.2.1、Git 用户信息
配置个人的用户名称和电子邮件地址:
[root@armcli2 ~]# git config --global user.name 'Brinnatt'
[root@armcli2 ~]# git config --global user.email 'brinnatt@gmail.com'
-
如果用了 --global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。
-
如果要在某个特定的项目中使用其他名字或者电邮,只要去掉 --global 选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。
1.6.2.2、文本编辑器
设置 Git 默认使用的文本编辑器,一般可能会是 Vi 或者 Vim。如果你有其他偏好,比如 Emacs 的话,可以重新设置
[root@armcli2 ~]# git config --global core.editor vim
1.6.2.3、差异分析工具
还有一个比较常用的是,在解决合并冲突时使用哪种差异分析工具。比如要改用 vimdiff 的话:
[root@armcli2 ~]# git config --global merge.tool vimdiff
- Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge 和 opendiff 等合并工具的输出信息。当然,你也可以指定使用自己开发的工具。
1.6.2.4、查看配置信息
要检查已有的配置信息,可以使用 git config --list 命令:
[root@armcli2 ~]# git config --list
user.name=Brinnatt
user.email=brinnatt@gmail.com
core.editor=vim
merge.tool=vimdiff
[root@armcli2 ~]#
有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig 和 ~/.gitconfig),不过最终 Git 实际采用的是最后一个。
这些配置我们也可以在 ~/.gitconfig 或 /etc/gitconfig 看到,如下所示:
[root@armcli2 ~]# cat ~/.gitconfig
[user]
name = Brinnatt
email = brinnatt@gmail.com
[core]
editor = vim
[merge]
tool = vimdiff
[root@armcli2 ~]#
也可以直接查阅某个环境变量的设定,只要把特定的名字跟在后面即可,像这样:
[root@armcli2 ~]# git config user.name
Brinnatt
1.6.3、Git 使用
1.6.3.1、SSH 连接
- 本地生成 SSH 密钥对。
[root@armcli2 ~]# rm -rf .ssh/
[root@armcli2 ~]# ssh-keygen -t rsa -b 4096 -N '' -f /root/.ssh/id_rsa -q
[root@armcli2 ~]# ls .ssh/
id_rsa id_rsa.pub
[root@armcli2 ~]# cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDYbtRw0Sq2LOxPRJsVbL5xgaY8aVjsK0M22GWc2vZGv3yek0pYCyTAudPiC43Q29yquRkRMZoyZI/hasq6PKZH0LUrkRJM1eH1umpMr7YobHwU2nxsowzLdOGZWe1y80LmTiUQBbLt7NIG0rvDn0xWm/f1sdfsedgwesdg23dtytssdglTwOzyAuPYI8A3+mxZoKPbTL5ZNTVhxuLbPBkZQXFf0gD0NJjf4BnvvHnvbuTzKIa8P/ALOBQPD63HZAJ9uuqO0mCDhb1OADUJQ0DuQFUPaIYi0Bzvevm22QTv+BYHXTUnZON6AWeZDMqNuHUqLsgdrEOhBSnURo1HV7eTSUmS1wf+4L7YaxQGLn2pyezzV+LihHu+3LbHSrR+iwDhJW3o9R2BrVAbyYlzboZqT5FAmjNrmd+gM1v7jP/y2xIEecvSxhh8gFscsSTOGQdyxDvh6bPBnCCsWPHhsmDB41VZrvbrsBNOsAC9TvJC+EvldrWfdb6PsNvKT6UBojhknY3nfsTDVW7/f/UCia2xi9JVbwVlu4H+6oZL/9GTxv+hnF/2x4zD5CsKOxvle0/ltLrYLzYxr7q80hOug3MjbHw/r8Nc6324E3G3CLWWaDx4WEHhzC1MNkoTym+0EYve7TQE+MRurrx3vOKU+bCFrMnMPgPsHZpB14VJtZ/Vw== root@armcli2
[root@armcli2 ~]#
- 将 SSH 公钥复制到 github 账号对应的剪贴板上。
- 测试 SSH 密钥认证是否成功。
[root@armcli2 ~]# ssh -T git@github.com
The authenticity of host 'github.com (20.205.243.166)' can't be established.
ECDSA key fingerprint is SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM.
ECDSA key fingerprint is MD5:7b:99:81:1e:4c:91:a5:0d:5a:2e:2e:80:13:3f:24:ca.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,20.205.243.166' (ECDSA) to the list of known hosts.
Hi liangtiansheng! You've successfully authenticated, but GitHub does not provide shell access.
[root@armcli2 ~]#
- 用我的 github 账号做一个测试,注意使用 ssh clone 的方式。当然,如果使用 https clone 也没有关系,在本地修改一下 url 的连接方式即可。
[root@armcli2 ~]# git clone git@github.com:liangtiansheng/pipework.git
[root@armcli2 ~]# ls
pipework
[root@armcli2 ~]# cd pipework/
[root@armcli2 pipework]# cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = git@github.com:liangtiansheng/pipework.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[root@armcli2 pipework]# echo "for i in {1..10};do echo $i;done" > mytest.sh # 增加一个文件,写点代码
[root@armcli2 pipework]# git add mytest.sh # 加到缓存
[root@armcli2 pipework]# git commit -m "try to change source code" # 提交到本地版本库
*** Please tell me who you are. # 要说明一下是谁修改的代码
Run
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
to set your account's default identity.
Omit --global to set the identity only in this repository.
fatal: unable to auto-detect email address (got 'root@armcli2.(none)')
[root@armcli2 pipework]#
[root@armcli2 pipework]# git config user.name "Jack" # 随便取一个名字
[root@armcli2 pipework]# git config user.email "Jackie@gmail.com" # 给一个邮箱地址
[root@armcli2 pipework]# git commit -m "try to change source code" # 可以提交到本地版本库了
[master 6d8cb58] try to change source code
1 file changed, 1 insertion(+)
create mode 100644 mytest.sh
[root@armcli2 pipework]# git push -u origin master # 基于 ssh key 直接提交到 github 账号仓库
Counting objects: 4, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 300 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To git@github.com:liangtiansheng/pipework.git
ae42f1b..6d8cb58 master -> master
Branch master set up to track remote branch master from origin. # 去 github 账号下检查代码提交情况
[root@armcli2 pipework]#
1.6.3.2、token 连接
本人用得少,后面再补充。
1.6.3.3、Git 身份验证
[root@armcli2 ~]# git config --global user.name 'Brinnatt'
[root@armcli2 ~]# git config --global user.email 'brinnatt@gmail.com'
- 注意:设定本机用户名,绑定邮箱,让远程服务器知道来者的身份,无论是提交到自己的仓库还是提交到别人的仓库,需要自报代码修改者的家门。
1.6.3.4、Git 本地与远程项目交互
1.6.3.4.1、克隆 github 项目
[root@armcli ~]# git clone https://github.com/liangtiansheng/pipework.git # 这里是项目的地址,将远程服务器的内容完全复制过来
[root@armcli ~]# cd pipework/ # clone 之后进入该项目的文件夹
[root@armcli pipework]# echo "for i in {1..10};do echo $i;done" > mytest.sh # 创建 mytest.sh 写点东西进去
[root@armcli pipework]# git add mytest.sh # 将新的文件添加到 git 的暂存区
[root@armcli pipework]# git commit -m "try to change source code" # 将暂存区的文件提交到某一个版本保存下来,并加上注释
[root@armcli pipework]# git push -u origin master # 将本地的更改提交到远程服务器
Username for 'https://github.com': liangtiansheng
Password for 'https://liangtiansheng@github.com':
remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.
fatal: Authentication failed for 'https://github.com/liangtiansheng/pipework.git/'
[root@armcli pipework]#
- 最后一步将本地版本库中的代码提交到远程服务器失败,这是 github 从 2021.8.13 日起禁止使用用户名和密码认证。
- 参见上面的 ssh 密钥认证,然后再 push 即可。
# 把 https url 改成 ssh url
[root@armcli2 pipework]# grep "url" .git/config
url = https://github.com/liangtiansheng/pipework.git
[root@armcli2 pipework]#
[root@armcli2 pipework]# git remote set-url origin git@github.com:liangtiansheng/pipework.git
[root@armcli2 pipework]#
[root@armcli2 pipework]# grep "url" .git/config
url = git@github.com:liangtiansheng/pipework.git
[root@armcli2 pipework]#
[root@armcli2 pipework]# git push -u origin master
1.6.3.4.2、本地关联 github 项目
- 用 github 账号创建一个名叫 gitlearning 的测试仓库。
git@github.com:liangtiansheng/gitlearning.git
- 本地创建一个项目根目录,取名 localsource,并在该项目中写一些测试代码。
[root@armcli2 ~]# mkdir localsource
[root@armcli2 ~]#
[root@armcli2 ~]# cd localsource/
[root@armcli2 localsource]#
[root@armcli2 localsource]# vim echo.sh
#!/bin/bash
for i in {1..9}; do
echo $i
done
- 关联 github 账号,提交本地代码到远程 github 账号对应项目下。
[root@armcli2 localsource]# git init # 初始化,准备 git 管理
[root@armcli2 localsource]# git remote add origin git@github.com:liangtiansheng/gitlearning.git # 关联 github 账号项目
[root@armcli2 localsource]# git config user.name 'Brinnatt'
[root@armcli2 localsource]# git config user.email "brinnatt@gmail.com"
[root@armcli2 localsource]#
# 先要把原仓库的代码拉下来合并,不然直接被github服务器拒绝,因为非clone情况下会对比本地和远程服务器代码差异
[root@armcli2 localsource]# git pull origin master # 下载github远程代码同时合并本地代码
[root@armcli2 localsource]# git add .
[root@armcli2 localsource]# git commit -m "my source to master"
[master a6b2265] my source to master
1 file changed, 4 insertions(+)
create mode 100644 echo.sh
[root@armcli2 localsource]#
[root@armcli2 localsource]# git push -u origin master # 提交代码到 github 账号项目下
Counting objects: 4, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 323 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:liangtiansheng/gitlearning.git
af2b709..a6b2265 master -> master
Branch master set up to track remote branch master from origin.
[root@armcli2 localsource]#
1.6.3.4.3、多人关联 github 项目
接着 1.6.3.4.2 小节实验,再找一台主机 armcli,同样先配置好 ssh 密钥认证(见上文),准备好要提交的本地代码。
- 本地创建一个项目根目录,取名 nativesource,并在该项目中写一些测试代码。
[root@armcli ~]# mkdir nativesource
[root@armcli ~]#
[root@armcli ~]# cd nativesource/
[root@armcli nativesource]#
[root@armcli nativesource]# vim echo.sh # 这个文件 1.6.3.4.2 小节已经 push 到远程 github 上了,修改了一点
#!/bin/bash
for i in {1..9}; do
echo $i
done
echo "succeed!"
[root@armcli nativesource]# vim count.sh # 新增一个文件
#!/bin/bash
ls /etc | wc -l
- 关联 github 账号,提交本地代码到远程 github 账号对应项目下。
[root@armcli nativesource]# git init
[root@armcli nativesource]# git remote add origin git@github.com:liangtiansheng/gitlearning.git # 关联 github 账号项目
[root@armcli nativesource]# git config user.name 'Susan' # 自报家门
[root@armcli nativesource]# git config user.email 'susan@gmail.com'
[root@armcli nativesource]#
[root@armcli nativesource]# git add . # 添加该文件夹中所有的文件到 git 的暂存区
[root@armcli nativesource]# git commit -m "revise code by Susan" # 提交所有代码到本机的版本库
[root@armcli nativesource]# git push -u origin master # 直接提交本地版本库代码到github远程服务器
To git@github.com:liangtiansheng/gitlearning.git
! [rejected] master -> master (fetch first) # 拒绝
error: failed to push some refs to 'git@github.com:liangtiansheng/gitlearning.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first merge the remote changes (e.g.,
hint: 'git pull') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
- 很明显,当多人直接提交自己代码的时候会被拒绝,按照错误提示,需要合并操作。
- git clone 过来的时候,git 不会对比本地和服务器的文件,也就不会有冲突。
- 建议确定完全覆盖本地的时候用 clone,不确定会不会有冲突的时候用 git pull,将远程服务器的代码 download 下来。
- git pull = git fetch + git merge
- 为了解决多人提交代码可能被拒绝的问题,可以使用以下步骤进行处理。
本地机器在提交自己代码之前做 fetch 操作:
[root@armcli nativesource]# git fetch origin master:test
warning: no common commits
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:liangtiansheng/gitlearning
* [new branch] master -> test
[root@armcli nativesource]#
- fetch 是把远程代码作为本地的一个其他分支下载到本地,并不更新本地分支,这里的命令是把远程的 "master" 分支下载到本地作为一个新的分支 "test" 存在。
查看本地文件并没有发生变化
[root@armcli nativesource]# ls
count.sh echo.sh
[root@armcli nativesource]# cat echo.sh
#!/bin/bash
for i in {1..9}; do
echo $i
done
echo "succeed!"
[root@armcli nativesource]# cat count.sh
#!/bin/bash
ls /etc | wc -l
[root@armcli nativesource]#
用 diff 查看本地 master 分支和 fetch 下来的 test 分支有什么区别:
[root@armcli nativesource]# git diff master test
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c464c7b
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# gitlearning
\ No newline at end of file
diff --git a/count.sh b/count.sh
deleted file mode 100644
index f1f7f2d..0000000
--- a/count.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-ls /etc | wc -l
diff --git a/echo.sh b/echo.sh
index e7e933c..7969251 100644
--- a/echo.sh
+++ b/echo.sh
@@ -2,5 +2,3 @@
for i in {1..9}; do
echo $i
done
-
-echo "succeed!"
[root@armcli nativesource]#
如果发现 fetch 下来的代码没什么问题,可以选择和本地分支进行合并
[root@armcli nativesource]# git merge test
Auto-merging echo.sh
CONFLICT (add/add): Merge conflict in echo.sh
Automatic merge failed; fix conflicts and then commit the result.
[root@armcli nativesource]#
- 发现 echo.sh 这个文件有冲突,这是我们预设的冲突点,上一小节有人提交过 echo.sh,这一小节另外一个主机新建了一个 echo.sh,代码还不完全一样,所以出现了冲突。
查看一下当前的状态和 git 表达 echo.sh 冲突的文件格式,然后手动修改代码,再
# 当前状态
[root@armcli nativesource]# git status
# On branch master
# You have unmerged paths.
# (fix conflicts and run "git commit")
#
# Changes to be committed:
#
# new file: README.md
#
# Unmerged paths:
# (use "git add <file>..." to mark resolution)
#
# both added: echo.sh
#
[root@armcli nativesource]#
# git 表达冲突的格式
[root@armcli nativesource]# cat echo.sh
#!/bin/bash
for i in {1..9}; do
echo $i
done
<<<<<<< HEAD
echo "succeed!"
=======
>>>>>>> test
# 修改 echo.sh
[root@armcli nativesource]# vim echo.sh
#!/bin/bash
for i in {1..9}; do
echo $i
done
echo "succeed!"
# 修改好冲突后,再次提交
[root@armcli nativesource]# git add echo.sh
[root@armcli nativesource]# git commit -m "fix echo.sh confliction"
[master 72cc489] fix echo.sh confliction
[root@armcli nativesource]#
[root@armcli nativesource]# git status
# On branch master
nothing to commit, working directory clean
[root@armcli nativesource]#
[root@armcli nativesource]# git push -u origin master
Counting objects: 8, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 636 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To git@github.com:liangtiansheng/gitlearning.git
a6b2265..72cc489 master -> master
Branch master set up to track remote branch master from origin.
[root@armcli nativesource]#
1.6.4、常用的 git 命令
git 命令可以实现很复杂的软件版本管理系统,但是一般中小型公司很难维护这么复杂的系统,成本太高,所以学习一些基本的用法就足够了。
参见官方手册:https://git-scm.com/book/zh/v2。
待补充...
1.6.4.1、基本用法
上面的四条命令在工作目录、暂存目录(也叫做索引)和仓库之间复制文件。
git add files
把当前文件放入暂存区域。git commit
给暂存区域生成快照并提交。git reset
命令用于回退版本,可以指定退回某一次提交的版本。git checkout
命令用于在不同的分支之间切换、恢复文件、创建新分支等操作。- git checkout 命令在 Git 2.23 版本后引入了 git switch 和 git restore 命令,分别用于分支切换和文件恢复,以提供更清晰的语义和错误检查。
你可以用 git reset -p
, git checkout -p
,or git add -p
进入交互模式。
也可以跳过暂存区域直接从仓库取出文件或者直接提交代码。
git commit -a
相当于运行git add
把所有当前目录下的文件加入暂存区域再运行git commit
。git commit files
进行一次包含最后一次提交加上工作目录中文件快照的提交。并且文件被添加到暂存区域。git checkout HEAD -- files
回滚到复制最后一次提交。
1.6.4.2、命令图解
后文中以下面的形式使用图片。
绿色的 5 位字符表示提交的 ID,分别指向父节点。分支用橘色显示,分别指向特定的提交。当前分支由附在其上的 HEAD 标识。 这张图片里显示最后 5 次提交,ed489 是最新提交。 main 分支指向此次提交,另一个 stable 分支指向祖父提交节点。
1.6.4.2.1、Diff
有许多种方法查看两次提交之间的变动。下面是一些示例。
1.6.4.2.2、Commit
提交时,git 用暂存区域的文件创建一个新的提交,并把此时的节点设为父节点。然后把当前分支指向新的提交节点。下图中,当前分支是 main。 在运行命令之前,main 指向 ed489,提交后,main 指向新的节点 f0cec 并以 ed489 作为父节点。
即便当前分支是某次提交的祖父节点,git 会同样操作。下图中,在 main 分支的祖父节点 stable 分支进行一次提交,生成了 1800b。 这样,stable 分支就不再是 main 分支的祖父节点。此时,合并(或者衍合)是必须的。
如果想更改一次提交,使用 git commit --amend
。git 会使用与当前提交相同的父节点进行一次新提交,旧的提交会被取消。
另一个例子是分离 HEAD 提交,后文讲。
1.6.4.2.3、Checkout
checkout 命令用于从历史提交(或者暂存区域)中拷贝文件到工作目录,也可用于切换分支。
当给定某个文件名(或者打开 -p 选项,或者文件名和 -p 选项同时打开)时,git 会从指定的提交中拷贝文件到暂存区域和工作目录。比如,git checkout HEAD~ foo.c
会将提交节点 HEAD~
(即当前提交节点的父节点)中的 foo.c
复制到工作目录并且加到暂存区域中。(如果命令中没有指定提交节点,则会从暂存区域中拷贝内容。)注意当前分支不会发生变化。
当不指定文件名,而是给出一个(本地)分支时,那么 HEAD 标识会移动到那个分支(也就是说,我们“切换”到那个分支了),然后暂存区域和工作目录中的内容会和 HEAD 对应的提交节点一致。新提交节点(下图中的a47c3)中的所有文件都会被复制(到暂存区域和工作目录中);只存在于老的提交节点(ed489)中的文件会被删除;不属于上述两者的文件会被忽略,不受影响。
如果既没有指定文件名,也没有指定分支名,而是一个标签、远程分支、SHA-1 值或者是像 main~3 类似的东西,就得到一个匿名分支,称作 detached HEAD(被分离的 HEAD 标识)。这样可以很方便地在历史版本之间互相切换。比如说你想要编译 1.6.6.1 版本的 git,你可以运行 git checkout v1.6.6.1
(这是一个标签,而非分支名),编译,安装,然后切换回另一个分支,比如说 git checkout main
。然而,当提交操作涉及到 “分离的 HEAD” 时,其行为会略有不同,详情见下面。
HEAD 标识处于分离状态时的提交操作
当 HEAD 处于分离状态(不依附于任一分支)时,提交操作可以正常进行,但是不会更新任何已命名的分支。(你可以认为这是在更新一个匿名分支。)
一旦此后你切换到别的分支,比如说 main,那么这个提交节点(可能)再也不会被引用到,然后就会被丢弃掉了。注意这个命令之后就不会有东西引用 2eecb。
但是,如果你想保存这个状态,可以用命令 git checkout -b name
来创建一个新的分支。
1.6.4.2.4、Reset
reset 命令把当前分支指向另一个位置,并且有选择的变动工作目录和索引。也用来在从历史仓库中复制文件到索引,而不动工作目录。
如果不给选项,那么当前分支指向到那个提交。如果用 --hard
选项,那么工作目录也更新,如果用 --soft
选项,那么都不变。
如果没有给出提交点的版本号,那么默认用 HEAD。这样,分支指向不变,但是索引会回滚到最后一次提交,如果用 --hard
选项,工作目录也同样。
如果给了文件名(或者 -p
选项),那么工作效果和带文件名的 checkout 差不多,除了索引被更新。
1.6.4.2.5、Merge
merge 命令把不同分支合并起来。合并前,索引必须和当前提交相同。如果另一个分支是当前提交的祖父节点,那么合并命令将什么也不做。 另一种情况是如果当前提交是另一个分支的祖父节点,就导致 fast-forward 合并。指向只是简单的移动,并生成一个新的提交。
否则就是一次真正的合并。默认把当前提交( ed489 如下所示)和另一个提交(33104)以及他们的共同祖父节点(b325c)进行一次三方合并。结果是先保存当前目录和索引,然后和父节点 33104 一起做一次新提交。
1.6.4.2.6、Cherry Pick
cherry-pick 命令"复制"一个提交节点并在当前分支做一次完全一样的新提交。
1.6.4.2.7、Rebase
衍合是合并命令的另一种选择。合并把两个父分支合并进行一次提交,提交历史不是线性的。衍合在当前分支上重演另一个分支的历史,提交历史是线性的。 本质上,这是线性化的自动的 cherry-pick。
上面的命令都在 topic 分支中进行,而不是 main 分支,在 main 分支上重演,并且把分支指向新的节点。注意旧提交没有被引用,将被回收。
要限制回滚范围,使用 --onto
选项。下面的命令在 main 分支上重演当前分支从 169a6 以来的最近几个提交,即 2c33a。
同样有 git rebase --interactive
让你更方便的完成一些复杂操作,比如丢弃、重排、修改、合并提交。没有图片体现这些,细节看这里:git-rebase(1)。
说明:
文件内容并没有真正存储在索引(.git/index)或者提交对象中,而是以 blob 的形式分别存储在数据库中(.git/objects),并用 SHA-1 值来校验。 索引文件用识别码列出相关的 blob 文件以及别的数据。
对于提交来说,以树(tree)的形式存储,同样用对于的哈希值识别。树对应着工作目录中的文件夹,树中包含的树或者 blob 对象对应着相应的子目录和文件。每次提交都存储下它的上一级树的识别码。
如果用 detached HEAD 提交,那么最后一次提交会被 the reflog for HEAD 引用。但是过一段时间就失效,最终被回收,与 git commit --amend
或者 git rebase
很像。
1.7、Gitlab Server 部署
aarch64 版本的 Gitlab 在 Centos8 以后都支持,可以直接通过 rpm 包安装,如果是 Centos8 以前,需要手动编译 aarch64 版本,当然也可以使用 x86 版本。下面介绍 Gitlab 一般使用方法,详细教程请参考官方文档 https://docs.gitlab.com/。
下载地址:https://packages.gitlab.com/gitlab/gitlab-ce
1.7.1、环境配置
关闭防火墙、SELinux
[root@cide ~]# setenforce 0
[root@cide ~]# yum remove firewalld NetworkManager -y
开启邮件服务
[root@cide ~]# systemctl start postfix
[root@cide ~]# systemctl enable postfix
1.7.2、部署 Gitlab
1.7.2.1、安装 gitlab 依赖包
centos7:
[root@cide ~]# yum install -y curl openssh-server openssh-clients postfix cronie policycoreutils-python
centos8:
[root@cide ~]# yum install -y curl openssh-server openssh-clients postfix cronie policycoreutils-python-utils
- gitlab-ce 10.x.x 以后的版本需要依赖 policycoreutils-python。
1.7.2.2、添加官方源
[root@cide ~]# curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
因为官方源太慢,可以使用国内 yum 源,配置如下:
[root@cide ~]# vim /etc/yum.repos.d/gitlab-ce.repo
[gitlab-ce]
name=Gitlab CE Repository
baseurl=https://mirrors.cloud.tencent.com/gitlab-ce/yum/el$releasever/
gpgcheck=0
enabled=1
1.7.2.3、安装 Gitlab
[root@cide ~]# yum -y install gitlab-ce # 自动安装最新版
或:
[root@cide ~]# yum -y install gitlab-ce-x.x.x # 安装指定版本Gitlab
1.7.2.4、配置 Gitlab
- 查看 Gitlab 版本
[root@cide ~]# head -1 /opt/gitlab/version-manifest.txt
gitlab-ce 14.8.2
- Gitlab 配置登录链接
[root@cide ~]# vim /etc/gitlab/gitlab.rb
......
# 没有域名,可以设置为本机 IP 地址
external_url 'http://172.17.0.61'
......
# 绑定监听的域名或 IP
[root@cide ~]# grep "^external_url" /etc/gitlab/gitlab.rb
external_url 'http://192.168.114.129'
- 初始化 Gitlab
gitlab 要求语言环境为英文环境,必须切换,切换方法如下:
可以先尝试以下方案
[root@cide ~]# echo "export LC_ALL=en_US.UTF-8" >> /etc/profile
- 语言环境问题:如果碰到之后的解决方案如上操作,需要重新登录。
如果上面的方案不可以,再使用下面的方案
[root@cide ~]# yum install langpacks-zh_CN langpacks-en langpacks-en_GB -y
[root@cide ~]# cat > /etc/profile.d/locale.sh<<-EOF
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LC_COLLATE=C
export LC_CTYPE=en_US.UTF-8
EOF
[root@cide ~]# source /etc/profile.d/locale.sh
- 退出终端重新登陆
第一次使用配置时间较长
[root@cide ~]# gitlab-ctl reconfigure
.....
1.7.2.5、启动 Gitlab 服务
[root@cide ~]# gitlab-ctl start
ok: run: alertmanager: (pid 3187) 40s
ok: run: gitaly: (pid 3206) 39s
ok: run: gitlab-exporter: (pid 3160) 43s
ok: run: gitlab-kas: (pid 3130) 44s
ok: run: gitlab-workhorse: (pid 3141) 44s
ok: run: grafana: (pid 3215) 39s
ok: run: logrotate: (pid 2223) 261s
ok: run: nginx: (pid 2699) 152s
ok: run: node-exporter: (pid 3150) 43s
ok: run: postgres-exporter: (pid 3201) 40s
ok: run: postgresql: (pid 2417) 238s
ok: run: prometheus: (pid 3170) 42s
ok: run: puma: (pid 2618) 170s
ok: run: redis: (pid 2254) 255s
ok: run: redis-exporter: (pid 3162) 42s
ok: run: sidekiq: (pid 2635) 164s
[root@cide ~]#
[root@cide ~]# lsof -i:80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 2699 root 7u IPv4 25593 0t0 TCP *:http (LISTEN)
nginx 2700 gitlab-www 7u IPv4 25593 0t0 TCP *:http (LISTEN)
nginx 2701 gitlab-www 7u IPv4 25593 0t0 TCP *:http (LISTEN)
nginx 2702 gitlab-www 7u IPv4 25593 0t0 TCP *:http (LISTEN)
[root@cide ~]#
1.7.2.6、Gitlab 设置 HTTPS 方式
如果想要 https 方式正常生效使用,则需要把 letsencrypt 自动生成证书的配置打开,这样在执行重新让配置生效命令 (gitlab-ctl reconfigure) 的时候会自动给域名生成免费的证书并自动在 gitlab 自带的 nginx 中加上相关的跳转配置,都是全自动的,非常方便。
[root@cide ~]# vim /etc/gitlab/gitlab.rb
[root@cide ~]# vim /etc/gitlab/gitlab.rb
letsencrypt['enable'] = false
letsencrypt['contact_emails'] = ['1062817308@qq.com']
- Gitlab 可以集成 Let’s Encrypt,需要域名支持,我们这里测试用的是 IP 地址,所以设置为 false,参见 https://docs.gitlab.com/omnibus/settings/ssl.html。
1.7.2.7、Gitlab 添加 smtp 邮件功能
[root@cide ~]# vim /etc/gitlab/gitlab.rb
......
### Email Settings
gitlab_rails['gitlab_email_enabled'] = true
gitlab_rails['gitlab_email_from'] = '1062817308@qq.com'
gitlab_rails['gitlab_email_display_name'] = 'gitlab'
gitlab_rails['gitlab_email_reply_to'] = '1062817308@qq.com'
gitlab_rails['gitlab_email_subject_suffix'] = '[gitlab]'
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "1062817308@qq.com"
gitlab_rails['smtp_password'] = "kktohrvdryglbjjh" # 这是我的 qq 邮箱授权码
gitlab_rails['smtp_domain'] = "smtp.qq.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
......
# 修改配置后需要初始化配置,先关掉服务再重新初始化
[root@cide ~]# gitlab-ctl stop
[root@cide ~]# gitlab-ctl reconfigure
[root@cide ~]# gitlab-ctl start
- 前面虽然安装了 postfix,但是这里不打算使用;实际上官方建议使用外部 SMTP Server 方式进行配置,上面就是借用 qq smtp 配置邮件服务器来实现通知;参见 https://docs.gitlab.com/omnibus/settings/smtp.html。
- qq 邮箱授权码要到自己的 qq 邮箱 -> 设置 -> 账户 -> 开启 smtp 服务,进行设置。
1.7.2.8、Gitlab 发送邮件测试
[root@cide ~]# gitlab-rails console
--------------------------------------------------------------------------------
Ruby: ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-linux]
GitLab: 14.8.2 (c7be43f6dd3) FOSS
GitLab Shell: 13.23.2
PostgreSQL: 12.7
------------------------------------------------------------[ booted in 28.17s ]
Loading production environment (Rails 6.1.4.6)
// 输入测试命令,回车
irb(main):001:0> Notify.test_email('1062817308@qq.com', 'Message Subject', 'Message Body').deliver_now
Delivered mail 62275913aa0c4_49e55a64307a9@cide.mail (2163.2ms)
=> #<Mail::Message:270420, Multipart: false, Headers: <Date: Tue, 08 Mar 2022 21:24:35 +0800>, <From: gitlab <1062817308@qq.com>>, <Reply-To: gitlab <1062817308@qq.com>>, <To: 1062817308@qq.com>, <Message-ID: <62275913aa0c4_49e55a64307a9@cide.mail>>, <Subject: Message Subject>, <Mime-Version: 1.0>, <Content-Type: text/html; charset=UTF-8>, <Content-Transfer-Encoding: 7bit>, <Auto-Submitted: auto-generated>, <X-Auto-Response-Suppress: All>>
irb(main):002:0>
- 去 qq 邮箱 web 界面查看是否收到邮件,经查看已收到邮件,测试成功。
1.7.3、Gitlab 的使用
在浏览器中输入 https://192.168.114.129/,然后 change password,并使用 root 用户登录即可(后续动作根据提示操作)。
1.7.3.1、Gitlab 命令行修改密码
[root@cide ~]# gitlab-rails console -e production
--------------------------------------------------------------------------------
Ruby: ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-linux]
GitLab: 14.8.2 (c7be43f6dd3) FOSS
GitLab Shell: 13.23.2
PostgreSQL: 12.7
------------------------------------------------------------[ booted in 35.98s ]
Loading production environment (Rails 6.1.4.6)
irb(main):001:0>
irb(main):021:0> user = User.where(id: 1).first # id 为 1 的是超级管理员
=> #<User id:1 @root>
irb(main):022:0> user.password = 'Greatwall487X' # 密码必须至少8个字符
=> "Greatwall487X"
irb(main):023:0> user.password_confirmation = 'Greatwall487X'
=> "Greatwall487X"
irb(main):024:0> user.save! # 保存如没有问题 返回 true
=> true
irb(main):025:0>
1.7.3.2、Gitlab 服务管理
# gitlab-ctl start # 启动所有 gitlab 组件;
# gitlab-ctl stop # 停止所有 gitlab 组件;
# gitlab-ctl restart # 重启所有 gitlab 组件;
# gitlab-ctl status # 查看服务状态;
# gitlab-ctl reconfigure # 初始化服务;
# vim /etc/gitlab/gitlab.rb # 修改默认的配置文件;
# gitlab-ctl tail # 查看日志;
1.7.3.3、登陆 Gitlab
如果需要手工修改 nginx 的 port ,可以在 gitlab.rb 中设置 nginx['listen_port'] = 8000 ,然后再次 gitlab-ctl reconfigure 即可。
登录 gitlab 如下所示(首次登陆设置 root 密码):
1.7.3.4、创建项目组 group
创建一个名叫 Adapted 项目组:
1.7.3.5、打开用户注册
Menu -> Admin -> Settings -> Sign-up restrictions 如下图勾选,然后拉到最下面保存,重新登录。
1.8、Gitlab 开发代码提交流程
1.8.1、公司代码提交合并流程
-
PM(项目主管/项目经理)在 gitlab 创建任务,分配给开发人员。
-
开发人员领取任务后,在本地使用 git clone 拉取代码库。
-
开发人员创建开发分支(git checkout -b dev),并进行开发。
-
开发人员完成之后,提交到本地仓库(git commit )。
-
开发人员在 gitlab 界面上申请分支合并请求(Merge request)。
-
PM 在 gitlab 上查看提交和代码修改情况,确认无误后,确认将开发人员的分支合并到主分支(master)。
-
开发人员在 gitlab 上 Mark done 确认开发完成,并关闭 issue。这一步在提交合并请求时可以通过描述中填写 "close #1" 等字样,可以直接关闭 issue。
1.8.2、创建项目管理用户 Brinnatt
Menu -> Admin -> Overview -> Users -> New user 创建用户 Brinnatt,如下图所示:
同样的方法,再创建 Eric 、Hellen 用户。用户添加完毕后,gitlab 会给用户发一封修改密码的邮件,各用户需要登录自己的邮箱,并点击相关的链接,设置新密码。
1.8.3、Brinnatt 设为组管理员
Menu -> Admin -> Groups -> Adapted,选择 Brinnatt 用户,角色设为 Owner,点击 Add users to group。
1.8.4、Eric、Hellen 设为组 Developer
Menu -> Admin -> Groups -> Adapted,选择 Eric、Hellen 用户,角色设为 Developer,点击 Add users to group。
1.8.5、Brinnatt 登陆创建 Project
1.8.6、指定项目的存储路径和项目名称
1.8.7、为项目创建 Dev 分支
左上角 GitLab -> 选择 Projects -> 左菜单 Repository -> Branched -> New branch,创建 dev 分支,如下图:
1.8.8、客户端创建 Brinnatt 用户
[root@cide ~]# useradd Brinnatt
[root@cide ~]# passwd Brinnatt
Changing password for user Brinnatt.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
[root@cide ~]# su - Brinnatt
[Brinnatt@cide ~]$
[Brinnatt@cide ~]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/Brinnatt/.ssh/id_rsa):
Created directory '/home/Brinnatt/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/Brinnatt/.ssh/id_rsa.
Your public key has been saved in /home/Brinnatt/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:hslPBZSGrqb8/d67o4RRajl65XhKAe81MsiSKKOQISY Brinnatt@cide
The key's randomart image is:
+---[RSA 2048]----+
| oo. |
| . o. |
|E. .. .. . |
|++ o =.* . |
|* o o.# S |
|+. .o+ / . |
|.. o. * = |
| o + + .. |
| .. oo+.++ |
+----[SHA256]-----+
[Brinnatt@cide ~]$
[Brinnatt@cide ~]$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDaJfDilzrSzjbcmhOwH83FOKFkSRf0WpG34IXjLjkbDrDQEZDApTbbmNKLTgN29WZTT2cpT2dfcpS6m+l2NTWIKVACYpSlTjIYmQBawULqIQzZx3lxnFdGRNbPK2aJvs8uw89oTZaD9F0IsiSkyGljMww0KuUAvJ61eiD9mvkkBfahduJWxRhqSeCAIXr6//ESVIrkbxPa9VcfcuDQW5GFw3/5MgSQW6J/zmnQOQOv62M13+WV4esNUAZXMDw0Bca+YOu2Dkzy6tBR+DkAUH7WVSnunI4twZ3Hmmw6rEb5awrgp6PWEAAnkU+x3Nnm5Qax9k/END6kALeUkLY8PkBT Brinnatt@cide
1.8.9、公钥复制到 gitlab 中
右上角用户菜单 Brinnatt -> Edit profile -> SSH Keys,按提示粘贴公钥,如下图:
1.8.10、Brinnatt 用户配置 git
[Brinnatt@cide ~]$ git config --global user.email 'brinnatt@gmail.com'
[Brinnatt@cide ~]$ git config --global user.name 'brinnatt'
[Brinnatt@cide ~]$
[Brinnatt@cide ~]$ git clone git@192.168.114.129:adapted/arm64v8.git
Cloning into 'arm64v8'...
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 7 (delta 1), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (7/7), done.
Resolving deltas: 100% (1/1), done.
[Brinnatt@cide ~]$ cd arm64v8/
[Brinnatt@cide arm64v8]$
[Brinnatt@cide arm64v8]$ ls
README.md
[Brinnatt@cide arm64v8]$
1.8.11、修改代码并提交到 main 分支
[Brinnatt@cide arm64v8]$ vim echo.sh
#!/bin/bash
echo "brinnatt code to greatwall project whose owner is Brinnatt"
# 注意:可以先查看一下当前分支,如果想提交代码的分支不同会报错,需要手动 checkout 分支
[Brinnatt@cide arm64v8]$ git branch
* main
[Brinnatt@cide arm64v8]$ git add .
[Brinnatt@cide arm64v8]$ git commit -m "first commit"
[main 1142737] first commit
1 file changed, 2 insertions(+)
create mode 100644 echo.sh
[Brinnatt@cide arm64v8]$
[Brinnatt@cide arm64v8]$ git push -u origin main
Counting objects: 4, done.
Delta compression using up to 3 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 335 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@192.168.114.129:adapted/arm64v8.git
14f3e19..1142737 main -> main
Branch main set up to track remote branch main from origin.
[Brinnatt@cide arm64v8]$
- gitlab 和 github 以后都默认使用 main 分支,不叫 master。
1.8.12、Eric 用户上传公钥到 gitlab
[root@cide ~]# useradd Eric && echo 'Greatwall487X' | passwd --stdin Eric
Changing password for user Eric.
passwd: all authentication tokens updated successfully.
[root@cide ~]#
[root@cide ~]# su - Eric
[Eric@cide ~]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/Eric/.ssh/id_rsa):
Created directory '/home/Eric/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/Eric/.ssh/id_rsa.
Your public key has been saved in /home/Eric/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:+G/FQv61E/W3yN7FyPhTi+ybwAmDqtzv9R4J3IN7ArM Eric@cide
The key's randomart image is:
+---[RSA 2048]----+
| |
| |
| |
| .o + .|
| .+SO + ..|
| ..+ O *ooo+|
| . E.+ @+.=+*|
| . o ..= +**o.|
| o .oo .ooo=o+ |
+----[SHA256]-----+
[Eric@cide ~]$
# 需要上传 Eric 公钥到 gitlab Eric 账户 SSH Key 下
[Eric@cide ~]$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDkV2T9di6S//LiH6LhxBTxfeI5+ako4PPe5MMvRQ34L2q5GWFm8AWGnvTYDbXbfLg4rBejBRnPoo0Nx5jLUms3IDcPCWJWiNb/bgy0AzpKtCBkUM59RSYFfCdybCE+8ptyP78OCvUyekq18oJoneGLC+SV4+Z9v2EjzoVVB6sAlfjkcX/7x6MTH6qla3ysQrRjU2gw8kQ8J7sfGQ6yN6E8S0fu0JCLspz5H9GSAlROCHGtMptrKS8AoDuxYebmOcALrpCb/J1WKztDRsZpnNhyZmAcA7+3Q9joKklX9OCx6+daCHJa+PnkBjleZTB359gp8R6X95bm8+2XGhoP+eJ Eric@cide
[Eric@cide ~]$
1.8.13、Eric 用户 clone 项目
[Eric@cide ~]$ git config --global user.email 'brinnatt@163.com'
[Eric@cide ~]$ git config --global user.name 'Eric'
[Eric@cide ~]$
[Eric@cide ~]$ git clone git@192.168.114.129:adapted/arm64v8.git
Cloning into 'arm64v8'...
The authenticity of host '192.168.114.129 (192.168.114.129)' can't be established.
ECDSA key fingerprint is SHA256:VabnUICGwCT+kVr32Jybbvvpc9VmUSq7Psd0JJv+Jfg.
ECDSA key fingerprint is MD5:18:4f:e6:94:52:5b:b9:98:ca:e3:3c:10:77:ab:a8:d7.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.114.129' (ECDSA) to the list of known hosts.
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 10 (delta 1), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (10/10), done.
Resolving deltas: 100% (1/1), done.
[Eric@cide ~]$
1.8.14、Eric 提交代码到 dev 分支
[Eric@cide ~]$ cd arm64v8/
[Eric@cide arm64v8]$ git branch
* main
[Eric@cide arm64v8]$ ls
echo.sh README.md
[Eric@cide arm64v8]$
[Eric@cide arm64v8]$ git checkout dev
Branch dev set up to track remote branch dev from origin.
Switched to a new branch 'dev'
[Eric@cide arm64v8]$
[Eric@cide arm64v8]$ git branch
* dev
main
[Eric@cide arm64v8]$ ls
README.md
[Eric@cide arm64v8]$
[Eric@cide arm64v8]$ vim eric.sh
[Eric@cide arm64v8]$ cat eric.sh
#!/bin/bash
echo "eric code"
[Eric@cide arm64v8]$
[Eric@cide arm64v8]$ git add .
[Eric@cide arm64v8]$ git commit -m "eric devlop"
[dev 0bf9864] eric devlop
1 file changed, 2 insertions(+)
create mode 100644 eric.sh
[Eric@cide arm64v8]$
[Eric@cide arm64v8]$
[Eric@cide arm64v8]$ git push -u origin dev
Counting objects: 4, done.
Delta compression using up to 3 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 296 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for dev, visit:
remote: https://192.168.114.129/adapted/arm64v8/-/merge_requests/new?merge_request%5Bsource_branch%5D=dev
remote:
To git@192.168.114.129:adapted/arm64v8.git
fd95b3a..0bf9864 dev -> dev
Branch dev set up to track remote branch dev from origin.
[Eric@cide arm64v8]$
默认情况下,Developer 角色没有权限提交代码到 main 分支,如下:
[Eric@cide arm64v8]$ git branch
* dev
main
[Eric@cide arm64v8]$ git checkout main
Switched to branch 'main'
[Eric@cide arm64v8]$ ls
echo.sh README.md
[Eric@cide arm64v8]$ vim ericmain.sh
[Eric@cide arm64v8]$ cat ericmain.sh
#!/bin/bash
echo "Eric tries to push code to main"
[Eric@cide arm64v8]$
[Eric@cide arm64v8]$ git branch
dev
* main
[Eric@cide arm64v8]$ git add .
[Eric@cide arm64v8]$ git commit -m "eric to main"
[main c73eaee] eric to main
1 file changed, 2 insertions(+)
create mode 100644 ericmain.sh
[Eric@cide arm64v8]$ git push -u origin main
Counting objects: 4, done.
Delta compression using up to 3 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 346 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: GitLab: You are not allowed to push code to protected branches on this project.To git@192.168.114.129:adapted/arm64v8.git
! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'git@192.168.114.129:adapted/arm64v8.git'
[Eric@cide arm64v8]$
1.8.15、Eric 通过 gitlab web 创建合并请求
1.8.16、Brinnatt 审查执行 merge
1.9、Gitlab 备份与恢复
1.9.1、查看系统版本和软件版本
[root@cide ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
[root@cide ~]#
[root@cide ~]# cat /opt/gitlab/embedded/service/gitlab-rails/VERSION
14.8.2
1.9.2、数据备份
1.9.2.1、查看备份相关的配置项
[root@cide ~]# vim /etc/gitlab/gitlab.rb
gitlab_rails['manage_backup_path'] = true
gitlab_rails['backup_path'] = "/data/gitlab/backups"
[root@cide ~]# mkdir /data/gitlab/backups -pv
[root@cide ~]# gitlab-ctl reconfigure
- 该项定义了默认备份文件的路径,可以通过修改该配置,并执行 gitlab-ctl reconfigure 重载配置。
1.9.2.2、执行备份命令进行备份
[root@cide ~]# /opt/gitlab/bin/gitlab-rake gitlab:backup:create
1.9.2.3、添加到 crontab 中定时执行
[root@cide ~]# crontab -e
0 2 * * * bash /opt/gitlab/bin/gitlab-rake gitlab:backup:create
- 可以到 /data/gitlab/backups 找到备份包,解压查看,会发现备份的还是比较全面的,数据库、repositories、build、upload 等分类还是比较清晰的。
1.9.2.4、设置备份保留时长
防止每天执行备份,有目录被爆满的风险,打开 /etc/gitlab/gitlab.rb 配置文件,找到如下配置:
[root@cide ~]# vim /etc/gitlab/gitlab.rb
gitlab_rails['backup_keep_time'] = 604800
-
设置备份保留 7 天(7 x 3600 x 24 = 604800),秒为单位,如果想增大或减小,可以直接在该处配置,并通过 gitlab-ctl reconfigure 重载配置。
-
备份完成,会在备份目录中生成一个当天日期的 tar 包。
1.9.3、数据恢复
1.9.3.1、安装部署 gitlab server
具体步骤参见上面:gitlab server 搭建过程
1.9.3.2、恢复 gitlab
1.9.3.2.1、查看备份相关的配置项
[root@cide ~]# vim /etc/gitlab/gitlab.rb
gitlab_rails['backup_path'] = "/data/gitlab/backups"
- 该路径就是备份时输出备份文件的路径,恢复时需要该路径下的备份文件。
1.9.3.2.2、恢复前需要先停掉数据连接服务
[root@cide ~]# gitlab-ctl stop unicorn
[root@cide ~]# gitlab-ctl stop sidekiq
ok: down: sidekiq: 0s, normally up
- 如果是台新搭建的主机,不需要操作,理论上不停这两个服务也可以。停这两个服务是为了保证数据一致性。
1.9.3.2.3、同步备份文件到新服务器
将老服务器 /data/gitlab/backups 目录下的备份文件拷贝到新服务器上的 /data/gitlab/backups。
[root@cide ~]# rsync -avz 1646911227_2022_03_10_14.8.2_gitlab_backup.tar 192.168.114.130:/data/gitlab/backups/
注意权限:600 权限是无权恢复的。 实验环境可改成了 777,生产环境建议修改属主属组。
[root@cide ~]# cd /data/gitlab/backups/
[root@cide backups]# chown -R git.git 1646911227_2022_03_10_14.8.2_gitlab_backup.tar
[root@cide backups]# ll
total 392
-rw------- 1 git git 399360 Mar 10 19:20 1646911227_2022_03_10_14.8.2_gitlab_backup.tar
1.9.3.2.4、执行命令进行恢复
后面再输入两次 yes 就完成恢复了。
[root@cide backups]# gitlab-rake gitlab:backup:restore BACKUP=1646911227_2022_03_10_14.8.2
- 后面再输入两次 yes 就完成恢复了。
恢复的时候可能报下面的错误,当前使用的是 gitlab v14.8.2 版本。
Restoring PostgreSQL database gitlabhq_production ... ERROR: must be owner of extension pg_trgm
ERROR: must be owner of extension btree_gist
ERROR: must be owner of extension btree_gist
ERROR: must be owner of extension pg_trgm
使用下面的步骤解决:
- 修改 postgresql 配置
[root@cide ~]# vim /var/opt/gitlab/postgresql/data/postgresql.conf
listen_addresses = '*' # what IP address(es) to listen on;
# 新增下面两行
[root@cide ~]# vim /var/opt/gitlab/postgresql/data/pg_hba.conf
local all all trust
host all all 127.0.0.1/32 trust
- 重启 gitlab 服务
[root@cide ~]# gitlab-ctl restart
ok: run: alertmanager: (pid 29316) 1s
ok: run: gitaly: (pid 29330) 0s
ok: run: gitlab-exporter: (pid 29346) 0s
ok: run: gitlab-kas: (pid 29348) 1s
ok: run: gitlab-workhorse: (pid 29358) 0s
ok: run: grafana: (pid 29367) 1s
ok: run: logrotate: (pid 29382) 0s
ok: run: nginx: (pid 29388) 1s
ok: run: node-exporter: (pid 29395) 0s
ok: run: postgres-exporter: (pid 29401) 0s
ok: run: postgresql: (pid 29410) 1s
ok: run: prometheus: (pid 29422) 0s
ok: run: puma: (pid 29439) 0s
ok: run: redis: (pid 29444) 1s
ok: run: redis-exporter: (pid 29450) 0s
ok: run: sidekiq: (pid 29533) 1s
[root@cide ~]#
- 修改 gitlab 账号为超级用户
[root@cide ~]# su - gitlab-psql
Last login: Thu Mar 10 20:51:03 CST 2022 on pts/0
-sh-4.2$ /opt/gitlab/embedded/bin/psql -h 127.0.0.1 gitlabhq_production
psql (12.7)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
gitlabhq_production=# ALTER USER gitlab WITH SUPERUSER;
ALTER ROLE
gitlabhq_production=# \q
-sh-4.2$
- 再次执行恢复命令,不会出现该错误。
1.9.3.2.5、恢复完成启动服务
恢复完成后,启动刚刚的两个服务,或者重启所有服务,再打开浏览器进行访问,发现数据和之前的一致:
[root@cide ~]# gitlab-ctl start unicorn
[root@cide ~]# gitlab-ctl start sidekiq
ok: run: sidekiq: (pid 27384) 0s
[root@cide ~]#
注意:通过备份文件恢复 gitlab 必须保证两台主机的 gitlab 版本一致,否则会提示版本不匹配。