Bootstrap

Linux云计算 |【第二阶段】AUTOMATION-DAY1

主要内容:

版本控制(集中式、分布式)、Git基础(服务端、客户端部署,基础命令操作、文档版本管理)、Git进阶(数据恢复、分支、冲突管理)

一、版本控制概念

版本控制是一种记录文件变化的方法,以便开发者可以随时查看特定版本的文件内容,或者回溯到之前的版本。版本控制系统(VCS)可以帮助开发者管理代码库的历史记录,协作开发,以及解决代码冲突。

1)版本库(典型的客户/服务器系统,即C/S架构)

  • 版本库是版本控制的核心
  • 允许任意数量客户端连接(主要针对开发者)
  • 客户端通过读写数据库分享代码

2)版本控制主要两大类型

① 集中式版本控制系统(CVCS):如 SVN(Subversion),CVS(Concurrent Versions System)。这些系统有一个中央服务器,存储所有的版本和历史记录,开发者从中央服务器获取代码,提交更改也需要通过中央服务器。

  • 开发者之间共用一个仓库服务器(repository);
  • 客户端所有操作需要联网;无法连接服务器则导致无法保存数据对版本记录,导致每个用户手中都是最新版本,且没有数据所有的历史版本;
  • 常用软件:CVS、SVN(Subversion)

② 分布式版本控制系统(DVCS):如 Git,Mercurial。在分布式版本控制系统中,每个开发者的工作目录都是一个完整的代码仓库,包含所有的版本和历史记录。开发者可以在本地进行提交,然后再将更改推送到中央服务器或其他开发者的仓库。

  • 每个开发者都是一个仓库的完整克隆,每个人都是服务器;
  • 支持断网操作,且每一个用户手中都有所有的历史版本
  • 常用软件:Git、BitKeeper(收费)

1、什么是Git

Git 是一个分布式版本控制系统,用于跟踪文件的更改,协调多个开发者之间的工作。它最初由 Linus Torvalds 于 2005 年开发,目的是为了更好地管理 Linux 内核的开发。Git 允许开发者存储代码的不同版本,跟踪这些版本之间的变化,并在需要时恢复到之前的版本。

Git 的主要特点:

  • 分布式:每个开发者的工作目录都是一个完整的仓库,包含所有的历史记录和版本。
  • 分支和合并:Git 支持快速创建和合并分支,使得并行开发和实验性工作变得容易。
  • 轻量级:Git 的分支和标签是轻量级的,创建和切换分支非常快速。
  • 数据完整性:Git 使用 SHA-1 哈希算法来确保数据的完整性和一致性。
  • 安全性:Git 提供了多种安全机制,如签名提交、加密传输等。

1.1 Git 的四个工作区域

Git Repository本地版本库(资源库):安全存放数据的位置,里面有提交到所有版本的数据。其中HEAD指针指向最新放入仓库的版本数据;(隐藏目录 .git)

② Workspace 工作区:平时存放项目代码的位置,从本地版本库中提取出来文件放在磁盘上供用户使用或修改(数据依旧最新版本)

Index / Stage 缓存区:用于临时存放数据的改动的位置,事实上它只是一个文件,保存即将提交到文件列表信息,一般存放在.git目录下的index文件(.git/index)中

Remote 远程版本库:用于托管代码的服务器

1.2 Git 的基本工作流程

  1. 克隆仓库:从远程仓库克隆一份完整的代码库到本地。
  2. 创建分支:在本地仓库创建一个新的分支并进行开发工作(工作区),包括:添加、修改数据文件。
  3. 添加和提交更改:将更改添加到暂存区(add),然后提交到本地仓库(commit)。
  4. 合并分支:将开发分支合并到主分支,解决可能的冲突。
  5. 推送更改:将本地仓库的更改推送到远程仓库(push)。

因此,Git管理的文件三种状态:已修改(modified),已暂存(staged),已提交(committed)

  • 已修改:表示修改了文件,但还没保存到数据库中。

  • 已暂存:表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。

  • 已提交:表示数据已经安全地保存在本地数据库中。

这会让我们的 Git 项目拥有三个阶段:工作区、暂存区以及 Git 目录。

二、Git 基础

1、部署Git服务器

1)安装Git软件包

2)设置防火墙、SELinux

3)创建服务器版本仓库(服务器是一台多人协作的中心服务器)

格式:git init project --bare    //初始化一个空仓库(没有具体数据)

 

2、客户端访问方式

本地访问

git clone file:///var/lib/git/

远程ssh访问(最安全的)

git clone root@服务器IP:/var/lib/git (格式类似SCP)

git服务器方式

git clone git://服务器IP/var/lib/git

Web访问(服务器需要额外配置Web服务器;客户端可以浏览器访问)

git clone http://服务器IP/git仓库

git clone https://服务器IP/git仓库

客户端命令行工具(Git支持的子命令操作)

  • git clone     将远程服务器的仓库克隆到本地仓库
  • git config    修改git配置(--global全局)
  • git add        添加修改到缓存区(暂存区)
  • git commit  提交修改到本地仓库
  • git push      提交修改到远程服务器

 

3、Git基本命令操作

① Clone克隆服务器仓库到本地仓库

② Config修改git配置

  • 客户端用户标记信息(跟Git账户和密码无关),不标记用户信息,则无法进行commit
  • 存放用户标记信息目录:.gitconfig

③ 导入数据,add提交本地暂存区

告诉计算机有哪些文件需要备份(暂存区不是用来备份数据的,提交仓库才是备份)

注意:必须进入工作区目录才能进行git操作

命令:git add .      //【.】表示当前工作区目录所有文件

④ Commit提交本地仓库

命令:git commit -m ”注释”      //-m提交修改的注释(必须加注释,否则查看版本日志难以分辨)

⑤ Push将本地修改提交远程服务器仓库

push.default 定义如何推送(simple更安全的推送)(针对RHEL7、8版本可直接Push操作)

命令:git push    //适用于Clone方式创建的版本库,已关联远程版本库服务器,默认分支master

命令:git push [-u] 服务器标签 分支[all]     //要求远程分支存在,否则无法关联

命令:git push --set-upstream 服务器标签 分支[all]     //自动创建分支实现关联

⑥ 从远程下载使用Pull命令

命令:git pull [服务器] [分支]

⑦ Status查看本地仓库中数据的状态

命令:git status

⑧ Log查看历史日志

命令:git log

⑨ remote查看远程分支

命令:git remote [-v]      //[-v],列出详细信息,查看对应的远程克隆地址

  • git remote 不带参数,列出已经存在的远程地址
  • git remote [-v | --verbose] 列出详细信息,在每一个名字后面列出其远程url,显示对应的克隆地址

案例:Git快速搭建Git服务器并测试版本控制软件

整体思路:安装Git软件、创建版本库、客户端克隆版本仓库到本地、本地工作目录修改数据、提交本地修改到服务器;

环境要求:

  • 1)准备两台RHEL8虚拟机,主机名分别为develop和git;
  • 2)develop(客户端):IP地址为192.168.4.10
  • 3)git(服务器):IP地址为192.168.4.20
  • 4)给develop和git两台主机配置可用的YUM源;

备注:跨网段走路由,相同网段不需要配置网关就可以互联互通!


步骤1:部署Git服务器(Git主机,192.168.4.20)

1)YUM安装Git软件

[root@gitlab ~]# yum -y install git
[root@gitlab ~]# git version
git version 2.18.2

2)创建存放仓库目录 /var/lib/git/project/、初始化一个空仓库 

[root@gitlab ~]# mkdir -p /var/lib/git    //存放git仓库的目录
[root@gitlab ~]# git init /var/lib/git/project --bare    //初始化一个空仓库
Initialized empty Git repository in /var/lib/git/project/
[root@gitlab ~]# ls /var/lib/git/project/
HEAD  branches  config  description  hooks  info  objects  refs

补充:仓库数据非明文方式存储,存储在版本库的数据库中;

3)设置防火墙信任所有,设置SELinux放行所有

[root@gitlab ~]# firewall-cmd --set-default-zone=trusted   //设置trusted区域
success
[root@gitlab ~]# firewall-cmd --get-default-zone    //查看默认区域
trusted
[root@gitlab ~]# setenforce 0    //设置SELinux模式为permissive
[root@gitlab ~]# getenforce
Permissive
[root@gitlab ~]# sed -i '/SELINUX/s/enforcing/permissive/' /etc/selinux/config

步骤2:部署客户端本地Git(Develop主机,192.168.4.10)

1)设置防火墙信任所有,设置SELinux放行所有

[root@develop ~]# firewall-cmd --set-default-zone=trusted
[root@develop ~]# setenforce 0
[root@develop ~]# sed -i '/SELINUX/s/enforcing/permissive/' /etc/selinux/config

2)YUM安装Git软件

[root@develop ~]# yum -y install git

3)使用clone指令克隆服务器仓库到【本地仓库】

[root@develop ~]# git clone [email protected]:/var/lib/git/project
Are you sure you want to continue connecting (yes/no)?  //第一次远程需输入yes
[email protected]'s password:  //克隆git主机的资料,需要输入git主机的密码

[root@develop ~]# ls     //未指定存放目录位置,默认保存当前目录
anaconda-ks.cfg  project

[root@develop ~]# cd project/ ; pwd
/root/project        //project为工作区
[root@develop project]# ls -a
.  ..  .git         //.git为本地仓库(隐藏文件),用于存放所有版本数据

[root@develop project]# git remote -v  //remote代表远程,可查看对应的克隆地址
origin [email protected]:/var/lib/git/project (fetch)
origin [email protected]:/var/lib/git/project (push)
  • ① git remote 不带参数,列出已经存在的远程地址
  • ② git remote [-v | --verbose] 列出详细信息,在每一个名字后面列出其远程url,显示对应的克隆地址

4)修改git配置(客户端用户标记信息)

[root@develop project]# git config --global user.email "[email protected]"  //邮箱
[root@develop project]# git config --global user.name "AJ"   //用户名
[root@develop project]# cat ~/.gitconfig
[user]
email = [email protected]
name = AJ
[root@develop project]# git config --list
user.name=AJ
[email protected]

5)在本地【工作区】对数据进行增删改查(必须要先进入仓库再操作数据)

[root@develop project]# echo "init date" > init.txt    //创建文件
[root@develop project]# mkdir demo      //创建目录
[root@develop project]# cp /etc/hosts demo/
[root@develop project]# ls
demo  init.txt

6)查看本地仓库中数据的状态

[root@develop project]# git status     //查看本地仓库数据状态
On branch master      //在Master分支
 
No commits yet
 
Untracked files:
  (use "git add <file>..." to include in what will be committed)
 
demo/
init.txt
 
nothing added to commit but untracked files present (use "git add" to track)

如图所示:(由于数据在工作区存在随时被修改风险,无法记录历史版本,所以呈现红色)

7)将工作区的修改提交到【暂存区】

[root@develop project]# git add .     //【.】为当前目录(工作区所有文件)
[root@develop project]# git status     //查看本地仓库数据状态
On branch master
 
No commits yet
 
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
 
new file:   demo/hosts
new file:   init.txt

如图所示:(工作区数据提交到暂存区,作为待提交数据并记录版本,呈现颜色绿色)

8)将暂存区修改提交到本地仓库

[root@develop project]# git commit -m "My file: init date"
[master (root-commit) 2cd7fe4] My file: init date
 2 files changed, 3 insertions(+)
 create mode 100644 demo/hosts
 create mode 100644 init.txt
[root@develop project]# git status     //查看本地仓库数据状态
On branch master   //表示在master分支
Your branch is based on 'origin/master', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)
 
nothing to commit, working tree clean     //干净的工作区

9)将本地仓库中的数据推送到远程服务器(Develop主机将数据推送到Git主机)

[root@develop project]# git config --global push.default simple   //简单push

补充:push.default simple,只有在RHEL7需要运行否则会报错,RHEL8可直接push

[root@develop project]# git push    //将本地数据推送给服务器仓库
[email protected]'s password:
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 361 bytes | 361.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To 192.168.4.20:/var/lib/git/project
 * [new branch]      master -> master

[root@develop project]# git remote -v    //查看远程服务器的信息
origin [email protected]:/var/lib/git/project (fetch)
origin [email protected]:/var/lib/git/project (push)
## 补充:git push不需要再指定远程仓库,因客户端在克隆本地仓库时已对应克隆地址
 
[root@develop project]# git push origin    //将数据推送至服务器(origin标签)
[email protected]'s password:
Everything up-to-date
## 补充:remote远程、遥远的;origin起源、源头

验证:推送到远程服务端仓库的文件无法查看,为方便辨认,可用du -sh查看文件大小

[root@gitlab ~]# du -sh /var/lib/git/project/    //推送前文件大小
92K /var/lib/git/project/
[root@gitlab ~]# du -sh /var/lib/git/project/    //推送后文件大小
104K /var/lib/git/project/

10)将服务器上的数据更新到本地(Git服务器的数据更新到Develop)

备注:可能其他人也在修改数据并提交git服务器,就会导致自己的本地数据为旧数据,且每次克隆需要完整克隆。使用pull指令就可以将服务器上新的数据更新到本地;

[root@develop project]# git pull    //服务端拉取到客户端
[email protected]'s password:
Already up to date.

11)查看版本日志(方便后期回滚数据)

[root@develop project]# git log    //查看历史日志
commit 2cd7fe49408b38467743e11be503b7d87ba601e7 (HEAD -> master, origin/master)
Author: AJ <[email protected]>
Date:   Mon Apr 19 12:00:44 2021 +0800
    My file: init date
补充:2cd7fe49408b38467743e11be503b7d87ba601e7为UUID标识
 
[root@develop project]# git log --pretty=oneline    //查看日志,--pretty精致
2cd7fe49408b38467743e11be503b7d87ba601e7 (HEAD -> master, origin/master) My file: init date
 
[root@develop project]# git log --oneline     //查看日志,更简洁
2cd7fe4 (HEAD -> master, origin/master) My file: init date
 
[root@develop project]# git reflog    //查看日志,显示HEAD指针
2cd7fe4 (HEAD -> master, origin/master) HEAD@{0}: commit (initial): My file: init date   //(initial): 初始化

[root@develop project]# git rev-parse HEAD    //查看当前所在版本
2cd7fe49408b38467743e11be503b7d87ba601e7

常见报错:执行git命令操作不再仓库工作区中

[root@gitlab ~]# git remote -v
fatal: not a git repository (or any of the parent directories): .git

常见报错:若不写用户标记,在commit给本地仓库时会提示

补充:git init与git init --bare区别

正常库/普通库:使用git init创建仓库,包含了工作区,可以正常的进行源文件的编写,提交等各种git常规操作。

裸库:使用git init --bare创建的是一个裸仓库,是没有工作区的,创建之后该库里有很多文件,主要用于记录git版本库提交的历史记录,不保存文件。作用就是作为分享库;

生成一类文件:用于记录版本库历史记录的.git目录下面的文件;而不会包含实际项目源文件的拷贝

三、Git进阶(HEAD指针、Git分支、分支冲突解决)

1、HEAD指针

在 Git 中,HEAD 指针是一个特殊的指针,它指向当前工作目录所基于的提交(commit)。简单来说,HEAD 指针指示了你当前所在的分支或提交。

HEAD 指针的作用:

  1. 指示当前分支:通常情况下,HEAD 指针指向当前分支的最新提交。例如,如果你在 main 分支上工作,HEAD 指针会指向 main 分支的最新提交。

  2. 指示特定提交:在某些情况下,HEAD 指针可以直接指向一个特定的提交,而不是一个分支。这种情况通常发生在使用 git checkout 命令切换到一个特定的提交时,这时你的工作目录会进入“分离 HEAD”状态。

常见的 HEAD 操作:

  1. 切换分支:使用 git checkout branch_name 命令可以将 HEAD 指针移动到指定的分支。
  2. 切换到特定提交:使用 git checkout commit_hash 命令可以将 HEAD 指针移动到指定的提交,进入分离 HEAD 状态。
  3. 创建新分支:使用 git checkout -b new_branch_name 命令可以创建一个新分支,并将 HEAD 指针移动到这个新分支。

HEAD指针是一个可以在任何分支和版本移动的指针,通过移动指针我们可以将数据还原至任何版本。每做一次提交操作都会导致git更新一个版本,HEAD指针也跟着自动移动

 

例如:假设有一个 Git 仓库,当前在 main 分支上,最新提交的哈希值是 abc123。此时,HEAD 指针指向 main 分支的最新提交 abc123

$ git log --oneline
abc123 (HEAD -> main) Add feature X
def456 Initial commit

如果你切换到一个特定的提交:

$ git checkout def456

此时,HEAD 指针会直接指向提交 def456,进入分离 HEAD 状态。

$ git log --oneline
def456 (HEAD) Initial commit

案例: HEAD指针操作

要求:查看Git版本信息、移动指针、通过移动HEAD指针恢复数据;

1)实验准备(模拟多次对数据仓库进行修改、提交操作,以产生多个版本)

[root@develop project]# echo "new file" > new.txt     //创建新文件1
[root@develop project]# git add .
[root@develop project]# git commit -m "add new.txt"

[root@develop project]# echo "first" >> new.txt     //第一次修改
[root@develop project]# git add .
[root@develop project]# git commit -m "new.txt:first line"

[root@develop project]# echo "second" >> new.txt    //第二次修改
[root@develop project]# git add .
[root@develop project]# git commit -m "new.txt:second"

[root@develop project]# echo "third" >> new.txt     //第三次修改
[root@develop project]# git add .
[root@develop project]# git commit -m "new.txt:third"
[root@develop project]# git push
 
[root@develop project]# echo "123" > num.txt   //创建新文件1
[root@develop project]# git add .
[root@develop project]# git commit -m "num.txt:123"

[root@develop project]# echo "456" > num.txt    //第一次修改
[root@develop project]# git add .
[root@develop project]# git commit -m "num.txt:456"

[root@develop project]# echo "789" > num.txt    //第二次修改
[root@develop project]# git add .
[root@develop project]# git commit -m "num.txt:789"
[root@develop project]# git push

2)查看Git版本信息日志(确定HEAD指针位置,还原版本)

[root@develop project]# git log --oneline
[root@develop project]# git reflog
b0e6f69 (HEAD -> master, origin/master) HEAD@{0}: commit: num.txt:789
21393dc HEAD@{1}: commit: num.txt:456
bd41550 HEAD@{2}: commit: num.txt:123
c6b3202 HEAD@{3}: commit: new.txt:third line
dd2c095 HEAD@{4}: commit: new.txt:second line
8dde818 HEAD@{5}: commit: new.txt:first line
d4e9325 HEAD@{6}: commit: add new.txt

3)移动HEAD指针,将数据还原到任意版本

提示:当前HEAD指针为HEAD@{0}

注意:还原版本目的是查看旧版本并备份所需内容,不能在旧版本直接修改覆盖新版本,否则push仓库时会产生报错;无论数据版本修改怎么样,哪怕有BUG,也不会从旧版本重新开始;

[root@develop project]# git reset --hard 2139    //指针移动到2139
HEAD is now at 21393dc num.txt:456
[root@develop project]# git reflog   //查看版本日志
21393dc (HEAD -> master) HEAD@{0}: reset: moving to 2139  //指针移动版本
b0e6f69 (origin/master) HEAD@{1}: commit: num.txt:789   //历史最后修改版本
21393dc (HEAD -> master) HEAD@{2}: commit: num.txt:456
bd41550 HEAD@{3}: commit: num.txt:123
c6b3202 HEAD@{4}: commit: new.txt:third line
dd2c095 HEAD@{5}: commit: new.txt:second line
8dde818 HEAD@{6}: commit: new.txt:first line
d4e9325 HEAD@{7}: commit: add new.txt
[root@develop project]# cat num.txt    //查看文件内容,已还原到456
456
 
[root@develop project]# git reset --hard d4e9     //指针再移动到d4e9
HEAD is now at d4e9325 add new.txt
[root@develop project]# git reflog    //查看版本日志
d4e9325 (HEAD -> master) HEAD@{0}: reset: moving to d4e9
21393dc HEAD@{1}: reset: moving to 2139
b0e6f69 (origin/master) HEAD@{2}: commit: num.txt:789
21393dc HEAD@{3}: commit: num.txt:456
bd41550 HEAD@{4}: commit: num.txt:123
c6b3202 HEAD@{5}: commit: new.txt:third line
dd2c095 HEAD@{6}: commit: new.txt:second line
8dde818 HEAD@{7}: commit: new.txt:first line
d4e9325 (HEAD -> master) HEAD@{8}: commit: add new.txt
 
[root@develop project]# git reset --hard b0e6    //回到最后一次修改的版本
HEAD is now at b0e6f69 num.txt:789
[root@develop project]# git reflog      //查看版本日志
b0e6f69 (HEAD -> master, origin/master) HEAD@{0}: reset: moving to b0e6
d4e9325 HEAD@{1}: reset: moving to d4e9    //指针移动历史
21393dc HEAD@{2}: reset: moving to 2139    //指针移动历史
b0e6f69 (HEAD -> master, origin/master) HEAD@{3}: commit: num.txt:789
21393dc HEAD@{4}: commit: num.txt:456
bd41550 HEAD@{5}: commit: num.txt:123
c6b3202 HEAD@{6}: commit: new.txt:third line
dd2c095 HEAD@{7}: commit: new.txt:second line
8dde818 HEAD@{8}: commit: new.txt:first line
d4e9325 HEAD@{9}: commit: add new.txt

常见报错:在同一分支的旧版本数据进行修改并直接push远程仓库时,会产生报错,注意不能在旧版本直接修改覆盖新版本

[root@develop project]# git push
[email protected]'s password:
To 192.168.4.20:/var/lib/git/project
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to '[email protected]:/var/lib/git/project'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

2、Git分支

概念:Git支持按功能模块、时间、版本等标准创建分支,分支可以让开发分多条主线同时进行,每条主线互不影响,在避免分支冲突的情况下也可实现分支合并;

常见的分支命名规范:

  1. MASTER分支(MASTER是主分支,是代码的核心)
  2. DEVELOP分支(DEVELOP最新开发成果的分支)
  3. RELEASE分支(为发布新产品设置的分支)
  4. HOTFIX分支(为修复软件BUG缺陷的分支)
  5. FEATURE分支(为开发新功能设置的分支)

补充:新建分支第一次创建前,将Master主分支的数据全部完整备份,然后以新建分支方式对备份的完整数据进行独立修改,且每条分支之间的修改互不影响;

管理多分支操作:

① 查看当前分支

  • 命令:git status
  • 命令:git branch -v     //【* master】表示为当前所在master分支

② 创建分支

  • 命令:git branch 分支    //分支名可随意,但尽量命名规范

③ 切换分支

  • 命令:git checkout 分支

④ 在新创建的分支上,可以继续修改代码,与主分支互不影响

  • 修改文件、创建文件等操作;
  • 正常add,commit提交版本库,也可push远程仓库;

⑤ 合并分支

  • 合并前一定要切换到需要合并的分支,执行merge命令合并分支
  • 命令:git merge 分支      //merge融合、合并


案例:Git分支操作

要求:查看分支、创建分支、切换分支、合并分支、解决分支的冲突

1)查看当前分支

[root@develop project]# git status   //查看本地仓库数据状态
On branch master     //所在分支为master
Your branch is up to date with 'origin/master'.
...
[root@develop project]# git branch -v     //【*】表示为当前所在分支
* master b0e6f69 num.txt:789

2)创建分支

[root@develop project]# git branch hotfix     //创建hotfix分支
[root@develop project]# git branch feature    //创建feature分支
[root@develop project]# git branch -v
  feature b0e6f69 num.txt:789
  hotfix  b0e6f69 num.txt:789
* master  b0e6f69 num.txt:789

3)切换分支

[root@develop project]# git checkout hotfix    //切换hotfix分支
Switched to branch 'hotfix'
[root@develop project]# git branch -v
  feature b0e6f69 num.txt:789
* hotfix  b0e6f69 num.txt:789
  master  b0e6f69 num.txt:789

4)在新的分支上可继续进行数据操作(增、删、改、查)(在hotfix分支操作)

[root@develop project]# echo "fix a bug" >> new.txt   //在新分支写入新数据
[root@develop project]# git add .
[root@develop project]# git commit -m "fix a bug"
[hotfix 01ee552] fix a bug
 1 file changed, 1 insertion(+)
[root@develop project]# git reflog     //查看版本日志
01ee552 (HEAD -> hotfix) HEAD@{0}: commit: fix a bug
b0e6f69 (origin/master, master, feature) HEAD@{1}: checkout: moving from master to hotfix
...

5)将hotfix修改的数据合并到master分支

注意:合并前必须要先切换到master分支,然后再执行merge命令

[root@develop project]# git checkout master   //切换分支
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
[root@develop project]# cat new.txt   //默认master分支中没有hotfix分支的数据
new file
first
second
third

[root@develop project]# git merge hotfix   //合并hotfix分支
Updating b0e6f69..01ee552
Fast-forward
 new.txt | 1 +
 1 file changed, 1 insertion(+)
[root@develop project]# cat new.txt     //查看合并分支后的数据内容
new file
first
second
third
fix a bug

补充:新建分支,可推送至远端版本库

[root@develop project]# git push origin hotfix    //push时指定分支

3、解决分支冲突

注意:修改了不同分支不同文件的行,系统可以进行合并分支;而修改了不同分支中相同文件的相同行,系统无法合并分支,产生恶劣冲突

解释:conflict冲突、矛盾;failed失败;fix修正

解决:首先查看有冲突的文件,直接将有冲突文件的内容修改为最终需要的文件内容,修改后,正常add,commit提交,解决冲突;


案例:解决分支冲突

1)在不同分支中修改相同文件的相同行数据,并进行分支合并,模拟数据冲突

[root@develop project]# git checkout hotfix     //切换hotfix分支
[root@develop project]# echo "AAA" > a.txt
[root@develop project]# git add .
[root@develop project]# git commit -m "add a.txt by hotfix"

[root@develop project]# git checkout master    //切换master分支
[root@develop project]# echo "BBB" > a.txt
[root@develop project]# git add .
[root@develop project]# git commit -m "add a.txt by master"
 
[root@develop project]# git merge hotfix    //合并hotfix分支,注意先切回master
Auto-merging a.txt
CONFLICT (add/add): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.
## 解释:
自动合并 a.txt
冲突(添加/添加):合并冲突于 a.txt(Merge conflict in a.txt)
自动合并失败(merge failed),修正冲突(fix conflicts)然后提交修正的结果

2)查看有冲突的文件内容,修改文件为最终版本的数据,解决冲突

[root@develop project]# cat a.txt    //查看文件中包含有冲突的内容
<<<<<<< HEAD
BBB
=======
AAA
>>>>>>> hotfix
[root@develop project]# vim a.txt
BBB        //修改文件为最终版本的数据,解决冲突
[root@develop project]# git add .
[root@develop project]# git commit -m "resolved"
[master 5307f4e] resolved
[root@develop project]# git merge hotfix    //再次合并时无报错
Already up to date.

归纳:分支与HEAD指针的关系

创建分支的本质是在当前提交上创建一个可以移动的指针(判断当前分支可根据HEAD这个特殊指针)

1)HEAD指针默认指向master分支

2)切换分支,HEAD指针指向testing分支(移动了HEAD指针)

3)在testing分支中修改并提交代码(不会影响master)

4)将分支切换回master分支

5)在master分支中修改数据,更新版本(不影响testing分支)

四、Git服务器访问形式

Git支持很多服务器协议形式,不同协议的Git服务器,客户端就可以使用不同的形式访问服务器。创建的服务器协议有SSH协议、Git协议、HTTP协议。

  • ① 基于SSH协议服务器(ssh)
  • ② 基于Git协议服务器(git-daemon)
  • ③ 基于HTTP协议服务器(http、https)

基于SSH协议

  • 服务器:安装git、使用git命令初始化版本仓库;

  • 客户端:使用SSH远程访问,需要密码认证访问(可读写权限)

① 客户端生成SSH密钥

② 将密钥拷贝给Git服务器

③ 测试上传代码到远程服务器是否需要密钥


案例1:Git服务器

步骤1:SSH协议服务器

1)创建基于密码验证的SSH协议服务器(Git主机,192.168.4.20操作)

[root@gitlib ~]# git init --bare /var/lib/git/web     //新建仓库web

2)客户端访问的方式(Develop主机,192.168.4.10操作)

[root@develop ~]# git clone [email protected]:/var/lib/git/web   //默认需要密码才能下载仓库中的资料
[root@develop ~]# rm -rf web    //将刚刚下载的仓库删除

3)客户端生成SSH密钥,实现免密码登陆git服务器(Develop主机操作)

[root@develop ~]# ssh-keygen -f /root/.ssh/id_rsa -N ''   //生成公私钥
## 补充:ssh-keygen命令选项(直接输入该命令会进入交互界面,-f和-n是非交互方式;)
[-f]  后面指定将创建的密钥文件存放到哪里
[-N]  后面是空,不对生成的密钥文件加密
[root@develop ~]# ssh-copy-id 192.168.4.20    //传递公钥给对端Git主机
[root@develop ~]# git clone [email protected]:/var/git/web   //生成完密钥并传递密钥后,再次克隆下载服务器的资料不需要输入密码
[root@develop ~]# ls
anaconda-ks.cfg  project  web
[root@develop ~]# cd web
[root@develop web]# git push    //将本地数据推送到git服务器也不需要密码(由于仓库的数据为空,推送到远程仓库时会有报错)
error: src refspec refs/heads/master does not match any.
error: failed to push some refs to '[email protected]:/var/lib/git/web'
[root@develop web]# cd ..
[root@develop ~]# rm -rf web    //删除本地仓库

步骤2:客户端部署新仓库

1)客户端在没有任何仓库资料的情况下,从服务器克隆部署新仓库

[root@develop ~]# git clone [email protected]:/var/git/web  

2)对本地工作区数据进行修改,并将数据推送远程仓库

[root@develop ~]# cd web
[root@develop web]# touch README.md    //创建文件
[root@develop web]# git add .
[root@develop web]# git commit -m "readme"
[root@develop web]# git remote -v      //查看远程服务器信息
origin [email protected]:/var/lib/git/web (fetch)
origin [email protected]:/var/lib/git/web (push)
[root@develop web]# git push           //默认推送
[root@develop web]# git push -u origin master    //指定推送的服务器和分支
[root@develop web]# cd ..
[root@develop ~]# rm -rf web    //删除本地仓库

步骤3:在客户端现有的文件夹下创建仓库

[root@develop ~]# mkdir mygit    //创建测试目录
[root@develop ~]# cd mygit/
[root@develop mygit]# git init     //将当前目录初始化创建为git空仓库
Initialized empty Git repository in /root/mygit/.git/
[root@develop mygit]# ls -a    //本地文件夹初始化的版本仓库与远程clone方式的版本仓库类似(.git)
.  ..  .git
[root@develop mygit]# git remote -v    //由于本地创建仓库没有对应的远程服务器
[root@develop mygit]# git remote add origin 192.168.4.20:/var/lib/git/web //添加远程服务器,给远程服务器的web仓库标签命名为origin
[root@develop mygit]# git remote -v     //查看远程服务器信息
origin 192.168.4.20:/var/lib/git/web (fetch)
origin 192.168.4.20:/var/lib/git/web (push)

[root@develop mygit]# git pull origin master   //从origin服务器的master分支拉取数据
[root@develop mygit]# ls
REDAME.md
[root@develop mygit]# echo new > new.txt
[root@develop mygit]# git add .
[root@develop mygit]# git commit -m "newfile"
[root@develop mygit]# git push -u origin master   //推送数据到远程仓库
[root@develop mygit]# git reflog
a6cbd4c (HEAD -> master, origin/master) HEAD@{0}: commit: newfile
cd0bbf2 HEAD@{1}: initial pull

补充:一个空仓库的情况下,可利用git remote add 可添加多个远程服务器仓库 

步骤4:客户端在现有仓库基础上添加新Git仓库

[root@develop mygit]# git remote -v
origin 192.168.4.20:/var/lib/git/web (fetch)
origin 192.168.4.20:/var/lib/git/web (push)
[root@develop mygit]# git remote rename origin new-name  //将老服务器信息重命名
[root@develop mygit]# git remote add origin 192.168.4.20:/var/lib/git/web  //再添加新服务器关联
[root@develop mygit]# git remote -v
new-name 192.168.4.20:/var/lib/git/web (fetch)
new-name 192.168.4.20:/var/lib/git/web (push)
origin 192.168.4.20:/var/lib/git/web (fetch)
origin 192.168.4.20:/var/lib/git/web (push)
[root@develop mygit]# ls
REDAME.md  new.txt
[root@develop mygit]# git push -u origin --all   //推送数据至origin服务器所有分支
Branch 'master' set up to track remote branch 'master' from 'origin'.
Everything up-to-date

常见报错:表示没有Git本地仓库,无工作区无法执行相关git操作

[root@develop mygit]# git remote -v
fatal: not a git repository (or any of the parent directories): .git

常见报错:没有将本地的分支与远程仓库的分支进行关联

[root@develop mygit]# git push
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use

具体原因: 出现这种情况主要是由于远程仓库太多,且分支较多。在默认情况下,git push时一般会上传到origin下的master分支上,然而当repository和branch过多,而又没有设置关联时,git就会产生疑问,因为它无法判断你的push目标。

解决办法:

git push --set-upstream origin master

其中的origin是你在clone远程代码时,git为你创建的指向这个远程代码库的标签,它指向repository

git push -u origin master

同样根据自己的需要,替换origin和master

两个命令的区别是第一条命令是要保证你的远程分支存在,如果不存在,也就无法进行关联。而第二条指令即使远程没有你要关联的分支,它也会自动创建一个出来,以实现关联

思维导图:

扩展:尝试自己注册Github

概述:GitHub是一个ie面向开源及私有软件项目的托管平台,因为支持git作为唯一的版本库格式进行托管,故名为GitHub;

1.登陆网站 https://github.com,点击Sign up(注册)

2.填写注册信息(用户名,邮箱,密码)

3.初始化完成后,到邮箱中去激活Github账户

4.创建仓库、使用仓库

点击Start a project

填写项目名称(项目名称任意)

往仓库中上传文件或新建文件

下载仓库中的代码

5. 命令行操作(需要联网的主机,如真实机)

[root@pc001 ~]# yum -y install git
[root@pc001 ~]# git clone https://github.com/账户名称/仓库名称
#clone指令用于将服务器仓库中的资料打包下载到本地
[root@pc001 ~]# cd 仓库名称
[root@pc001 ~]# 任意修改文件,或新建文件
[root@pc001 ~]# git add .
#add添加新文件
[root@pc001 ~]# git commit -m "test"
[root@pc001 ~]# git push
#commit和push实现提交代码的功能
[root@pc001 ~]# git pull
#pull可以从githuab服务器拉取数据到本地

补充:提交在暂存区时,如果希望阻止某些文件加入到跟踪(100个文件,仅某一个文件不提交到暂存区),创建.gitignore隐藏文件;

[root@dev project]# vim .gitignore
plan.txt
*.swp

 

小结:

本篇章节为 【第二阶段】AUTOMATION-DAY1 的学习笔记,这篇笔记可以初步了解到 版本控制(集中式、分布式)、GIt基础(服务端、客户端部署,基础命令操作、文档版本管理)、Git进阶(数据恢复、分支、冲突管理)。除此之外推荐参考相关学习网址:


Tip:毕竟两个人的智慧大于一个人的智慧,如果你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不要害羞和回避,可以向他人请教,花点时间直到你真正的理解

;