代码编写阶段,我们需要将不同版本的代码存储到一个仓库中,大多数企业采用的版本控制系统就是 git 或者 svn,相比之下, git 作为版本控制系统居多,而远程仓库,GitLab 也是大多数企业的首先,因为它开源且活跃。
Git、Github、Gitlab 的区别
- Git:开源的分布式版本控制系统,是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件,据说只用了7天时间写出来的
- Github:基于 Git 的代码托管服务,是在线的,提供付费和免费,区别在于只有付费的才可以创建私有的代码仓库,不过现在都是免费了,之前是收费的
- GitLab:代码托管平台,功能和 Github 差不多,是完全免费的开源软件,按照MIT许可证分发,支持本地部署
Git、SVN 的区别
-
Git 是分布式的,SVN 不是:Git 和其它非分布式的版本控制系统(SVN、CVS)等,最核心的区别
-
Git 把内容按元数据方式存储,而 SVN 是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里
-
Git 分支和 SVN 的分支不同:分支在 SVN 中一点不特别,就是版本库中的另外的一个目录
-
Git 没有一个全局的版本号,而 SVN 有:目前为止这是跟 SVN 相比 GIit 缺少的最大的一个特征
-
Git 的内容完整性要优于 SVN:Git 的内容存储使用的是 SHA-1哈希算法,这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏
-
Git 是分布式的版本控制器 没有客户端和服务器端的概念
-
SVN 它是 C/S 结构的版本控制器,有客户端和服务器端的概念,服务器宕机对版本库的破坏性比较大
Git 的安装(一)
在 DevOps 的 Code 阶段,作为编码,我们一般会在 windows 环境下进行一个代码版本控制,所以这里作为在 windows 下安装 Git 作为一个演示
git 官网
Git (git-scm.com)
下载 windows 安装包
打开安装包安装即可
Git 的安装(二)
Git 官方网站上有在各种 Unix 发行版的系统上安装步骤,网址:https://git-scm.com/download/linux
Centos7 安装 Git
使用第三方存储库IUS来安装更新版本的git
第一步:安装第三方存储库 IUS
curl https://setup.ius.io | sh
第二步:开启 IUS 存储库
sed -i 's/enabled = 0/enabled = 1/g' ius-archive.repo
第三步:安装 Git
yum -y install git2u
第四步:验证 Git 版本
git --version
Git 的基础配置
初次运行 Git 前的配置说明
git config 工具来控制 Git 外观和行为的配置变量,这些变量存储在三个不同的位置:
- /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果在执行 git config 时带上 --system 选项,那么它就会读写该文件中的配置变量。 (由于它是系统配置文件,因此你需要管理员或超级用户权限来修改它。)
- ~/.gitconfig 或 ~/.config/git/config 文件:只针对当前用户。 你可以传递 --global 选项让 Git 读写此文件,这会对你系统上所有的仓库生效。
- 当前使用仓库的 Git 目录中的 config 文件(即 .git/config):针对该仓库。 你可以传递 --local 选项让 Git 强制读写此文件,虽然默认情况下用的就是它。(当然,你需要进入某个 Git 仓库中才能让该选项生效。)
可以通过git config --list --show-origin
命令查看所有的配置以及它们所在的文件
windwos 自动安装的默认路径:
用户信息
安装完 Git 之后,首要的需要设置用户名和邮箱,每一个 Git 提交都会使用这些信息
# 如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置
git config --global user.name "yunmx"
git config --global user.email 565616251@qq.com
对于不同的项目目录,我们可以不使用–global选项的命令来配置:
# 创建一个文件夹来测试
# 初始化Git
# 配置用户名信息
git init
git config user.name "yunmx2"
git config user.email yunmx2@qq.com
# 查看对应项目文件夹下的.git/config文件就能看到相关信息了
Git 的简单演示
新建一个项目文件夹并进入
右键空白处选择:Git Bash Here
操作和 linux 下的文件操作一样
初始化一个项目文件夹:git init
单独为这个项目设置基本信息
git config user.name “whale”
git config user.email 565616254@qq.com
Git 工作流程
一般工作流程如下:
- 克隆 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 ” 命令时,会直接从暂存区删除文件,工作区则不做出改变。
-
当执行 “git checkout .” 或者 “git checkout – ” 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。
-
当执行 “git checkout HEAD .” 或者 “git checkout HEAD ” 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
Git 常用命令演示
创建版本库
- 隐藏文件夹 git 目录是 Git 用来跟踪管理版本的,不要乱动这个文件夹,可能会因为操作不当破坏版本仓库的
[root@vm-99 demo2]# git init
已初始化空的 Git 仓库于 /home/git-demo/demo2/.git/
[root@vm-99 demo2]# ls -a
. .. .git
[root@vm-99 demo2]#
添加文件到暂存区
[root@vm-99 demo2]# vim test.md
[root@vm-99 demo2]# cat test.md
# HEAD1
[root@vm-99 demo2]# git add test.md
[root@vm-99 demo2]# git status
位于分支 master
尚无提交
要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)
新文件: test.md
[root@vm-99 demo2]#
提交到本地仓库
[root@vm-99 demo2]# git commit -m "first commit"
[master(根提交) 0dea6e4] first commit
1 file changed, 3 insertions(+)
create mode 100644 test.md
[root@vm-99 demo2]#
查看是否有文件可提交到暂存区
[root@vm-99 demo2]# git status
位于分支 master
无文件要提交,干净的工作区
[root@vm-99 demo2]# vim test.md
[root@vm-99 demo2]# git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: test.md
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@vm-99 demo2]#
比较文件内容
[root@vm-99 demo2]# git diff test.md
diff --git a/test.md b/test.md
index e2c87fb..46a5696 100644
--- a/test.md
+++ b/test.md
@@ -1,3 +1,3 @@
# HEAD1
-
+## Head2
[root@vm-99 demo2]#
查看历史记录
从最近到最远的显示日志
[root@vm-99 demo2]# git log
commit 108f8bbe8c93f6004cc360ca64e62be6377acaba (HEAD -> master)
Author: demo1 <565616251@qq.com>
Date: Sun Sep 18 09:51:23 2022 +0800
second commit
commit 0dea6e426ff630dad2cacc7ff3f6492f6d29c5e5
Author: demo1 <565616251@qq.com>
Date: Sun Sep 18 09:47:53 2022 +0800
first commit
[root@vm-99 demo2]# git log --pretty=oneline
108f8bbe8c93f6004cc360ca64e62be6377acaba (HEAD -> master) second commit
0dea6e426ff630dad2cacc7ff3f6492f6d29c5e5 first commit
[root@vm-99 demo2]#
回退版本
[root@vm-99 demo2]# cat test.md
# HEAD1
## Head2
[root@vm-99 demo2]# git log --pretty=oneline
108f8bbe8c93f6004cc360ca64e62be6377acaba (HEAD -> master) second commit
0dea6e426ff630dad2cacc7ff3f6492f6d29c5e5 first commit
[root@vm-99 demo2]# git reset --hard HEAD~1
HEAD 现在位于 0dea6e4 first commit
[root@vm-99 demo2]# cat test.md
# HEAD1
[root@vm-99 demo2]# git reflog
0dea6e4 (HEAD -> master) HEAD@{0}: reset: moving to HEAD~1
108f8bb HEAD@{1}: commit: second commit
0dea6e4 (HEAD -> master) HEAD@{2}: commit (initial): first commit
[root@vm-99 demo2]# git reset --hard 108f8bb
HEAD 现在位于 108f8bb second commit
[root@vm-99 demo2]# cat test.md
# HEAD1
## Head2
[root@vm-99 demo2]#
撤销修改
#########未提交到暂存区#########
#########1.可以回退到上一个版本#########
#########2.或者手动修改回内容#########
#########3.可以git checkout#########
[root@vm-99 demo2]# git status
位于分支 master
无文件要提交,干净的工作区
[root@vm-99 demo2]# vim test.md
[root@vm-99 demo2]# cat test.md
# HEAD1
## Head2
### Head3
[root@vm-99 demo2]# git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: test.md
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@vm-99 demo2]# git checkout -- test.md
[root@vm-99 demo2]# cat test.md
# HEAD1
## Head2
[root@vm-99 demo2]# git status
位于分支 master
无文件要提交,干净的工作区
[root@vm-99 demo2]#
删除文件
[root@vm-99 demo2]# ls
su.info test.md
[root@vm-99 demo2]# rm su.info
rm:是否删除普通文件 "su.info"?y
[root@vm-99 demo2]# git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add/rm <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
删除: su.info
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@vm-99 demo2]# git add su.info
[root@vm-99 demo2]# git commit -m "fourth commit"
[master 4e95e9b] fourth commit
1 file changed, 1 deletion(-)
delete mode 100644 su.info
[root@vm-99 demo2]#
[root@vm-99 demo2]# git reflog
4e95e9b (HEAD -> master) HEAD@{0}: commit: fourth commit
081bad8 HEAD@{1}: commit: third commit
108f8bb HEAD@{2}: reset: moving to 108f8bb
0dea6e4 HEAD@{3}: reset: moving to HEAD~1
108f8bb HEAD@{4}: commit: second commit
0dea6e4 HEAD@{5}: commit (initial): first commit
[root@vm-99 demo2]# git reflog
4e95e9b (HEAD -> master) HEAD@{0}: commit: fourth commit
081bad8 HEAD@{1}: commit: third commit
108f8bb HEAD@{2}: reset: moving to 108f8bb
0dea6e4 HEAD@{3}: reset: moving to HEAD~1
108f8bb HEAD@{4}: commit: second commit
0dea6e4 HEAD@{5}: commit (initial): first commit
[root@vm-99 demo2]# git reset --hard 081bad8
HEAD 现在位于 081bad8 third commit
[root@vm-99 demo2]#
[root@vm-99 demo2]# ls
su.info test.md
[root@vm-99 demo2]# cat su.info
This is a summary message!
[root@vm-99 demo2]#
远程仓库
演示“github"
【登录 github】-【新建空仓库】
【设置公钥】
本地推送
[root@vm-99 demo2]# git remote add origin git@github.com:yunmx/demo2.git
[root@vm-99 demo2]# git push -u origin main
error: src refspec main does not match any.
error: 无法推送一些引用到 'git@github.com:yunmx/demo2.git'
[root@vm-99 demo2]# git push -u origin master
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.
对象计数中: 4, 完成.
Delta compression using up to 12 threads.
压缩对象中: 100% (2/2), 完成.
写入对象中: 100% (4/4), 287 bytes | 287.00 KiB/s, 完成.
Total 4 (delta 0), reused 0 (delta 0)
To github.com:yunmx/demo2.git
* [new branch] master -> master
分支 'master' 设置为跟踪来自 'origin' 的远程分支 'master'。
[root@vm-99 demo2]#
查看 git 远程仓库
修改内容后再次推送一次
[root@vm-99 demo2]# vim su.info
[root@vm-99 demo2]# git status
位于分支 master
您的分支与上游分支 'origin/master' 一致。
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: su.info
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@vm-99 demo2]# git commit -a -m "second commit"
[master 08fbfdd] second commit
1 file changed, 1 insertion(+)
[root@vm-99 demo2]# git push origin master
对象计数中: 3, 完成.
Delta compression using up to 12 threads.
压缩对象中: 100% (3/3), 完成.
写入对象中: 100% (3/3), 290 bytes | 290.00 KiB/s, 完成.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:yunmx/demo2.git
0fd4cb2..08fbfdd master -> master
[root@vm-99 demo2]#
克隆远程仓库
[root@vm-99 opt]# git clone git@github.com:yunmx/demo2.git
正克隆到 'demo2'...
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 7 (delta 0), reused 7 (delta 0), pack-reused 0
接收对象中: 100% (7/7), 完成.
[root@vm-99 opt]# cd demo2/
[root@vm-99 demo2]# git reflog
08fbfdd (HEAD -> master, origin/master, origin/HEAD) HEAD@{0}: clone: from git@github.com:yunmx/demo2.git
[root@vm-99 demo2]#
分支的创建与合并
创建分支并切换使用
[root@vm-99 demo2]# ls -a
. .. .git su.info test.md
[root@vm-99 demo2]# git checkout -b branch1
切换到一个新分支 'branch1'
[root@vm-99 demo2]# git branch
* branch1
master
[root@vm-99 demo2]#
在分支上修改文件内容
[root@vm-99 demo2]# vim su.info
[root@vm-99 demo2]# cat su.info
This is a summary message!
This is a summary message!
This is a summary message!
[root@vm-99 demo2]#
提交到分支
[root@vm-99 demo2]# git add su.info
[root@vm-99 demo2]# git commit -m "first commit to branch"
[branch1 fce1b35] first commit to branch
1 file changed, 1 insertion(+)
[root@vm-99 demo2]#
切换到master后查看分支修改的内容
[root@vm-99 demo2]# git checkout master
切换到分支 'master'
您的分支与上游分支 'origin/master' 一致。
[root@vm-99 demo2]# git branch
branch1
* master
[root@vm-99 demo2]# cat su.info
This is a summary message!
This is a summary message!
[root@vm-99 demo2]#
分支内容合并到master
[root@vm-99 demo2]# git merge branch1
更新 08fbfdd..fce1b35
Fast-forward
su.info | 1 +
1 file changed, 1 insertion(+)
[root@vm-99 demo2]# cat su.info
This is a summary message!
This is a summary message!
This is a summary message!
[root@vm-99 demo2]#
删除分支
[root@vm-99 demo2]# git branch -d branch1
已删除分支 branch1(曾为 fce1b35)。
[root@vm-99 demo2]# cat su.info
This is a summary message!
This is a summary message!
This is a summary message!
[root@vm-99 demo2]#
分支冲突
创建一个分支
[root@vm-99 demo2]# git checkout -b branch1
切换到一个新分支 'branch1'
[root@vm-99 demo2]# git branch
* branch1
master
[root@vm-99 demo2]#
分支下修改一个文件的内容
[root@vm-99 demo2]# vim su.info
[root@vm-99 demo2]# git add su.info
[root@vm-99 demo2]# git commit -m "commit to branch1"
[branch1 c55a0b0] commit to branch1
1 file changed, 1 insertion(+), 1 deletion(-)
[root@vm-99 demo2]#
切换到master 并修改文件内容
[root@vm-99 demo2]# git checkout master
切换到分支 'master'
您的分支领先 'origin/master' 共 7 个提交。
(使用 "git push" 来发布您的本地提交)
[root@vm-99 demo2]# vim su.info
[root@vm-99 demo2]# git add su.info
[root@vm-99 demo2]# git commit -m "commit to master"
[master 5b7f0a5] commit to master
1 file changed, 1 insertion(+), 1 deletion(-)
[root@vm-99 demo2]#
合并分支
[root@vm-99 demo2]# git merge branch1
自动合并 su.info
冲突(内容):合并冲突于 su.info
自动合并失败,修正冲突然后提交修正的结果。
[root@vm-99 demo2]#
分析分支冲突
[root@vm-99 demo2]# git status
位于分支 master
您的分支领先 'origin/master' 共 8 个提交。
(使用 "git push" 来发布您的本地提交)
您有尚未合并的路径。
(解决冲突并运行 "git commit")
(使用 "git merge --abort" 终止合并)
未合并的路径:
(使用 "git add <文件>..." 标记解决方案)
双方修改: su.info
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@vm-99 demo2]#
查看冲突文件内容
Git 用<<<<<<<,=======,>>>>>>> 标记出不同分支的内容
[root@vm-99 demo2]# cat su.info
This is a summary message!
This is a summary message!
This is a summary message!
This is a summary message!
<<<<<<< HEAD
This is a b summary message!
=======
This is a a summary message!
>>>>>>> branch1
[root@vm-99 demo2]#
修改后再合并
分支下修改成和mster一样的文件内容再进行合并
Bug 分支的使用
Git 提供了一个 stash 功能,可以把当前工作现场 ”隐藏起来”,等以后恢复现场后继续工作,这样就可以实现临时 Bug 分支的场景使用
现在我在一个分支下工作,且有内容未提交
现在也没法提交,因为这个分支有很多东西没完成
[root@vm-99 demo2]# git branch
* master
[root@vm-99 demo2]# git checkout -b demo1
切换到一个新分支 'demo1'
[root@vm-99 demo2]# git branch
* demo1
master
[root@vm-99 demo2]# vim test.md
[root@vm-99 demo2]# git status
位于分支 demo1
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: test.md
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@vm-99 demo2]#
可以将当前工作情况隐藏起来
隐藏起来以后,我们就可以新建一个bug分支,完成后可以就行分支合并,然后删除为修复Bug而创建的临时分支
[root@vm-99 demo2]# git stash
保存工作目录和索引状态 WIP on demo1: 1714188 test
[root@vm-99 demo2]# git status
位于分支 demo1
无文件要提交,干净的工作区
[root@vm-99 demo2]#
查看隐藏的工作区并恢复
[root@vm-99 demo2]# git stash list
stash@{0}: WIP on demo1: 1714188 test
[root@vm-99 demo2]#
[root@vm-99 demo2]# git stash apply
位于分支 demo1
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: test.md
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@vm-99 demo2]# git status
位于分支 demo1
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: test.md
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@vm-99 demo2]#
查看是否和建立临时分区之前是否一致
多人协作
工作模式一般是这样的:
- 首先,可以试图用 git push origin branch-name 推送自己的修改
- 如果推送失败,则因为远程分支比你的本地更新早,需要先用 git pull 试图合并
- 如果合并有冲突,则需要解决冲突,并在本地提交。再用 git push origin branch-name 推送