主要内容:
版本控制(集中式、分布式)、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 的基本工作流程
- 克隆仓库:从远程仓库克隆一份完整的代码库到本地。
- 创建分支:在本地仓库创建一个新的分支并进行开发工作(工作区),包括:添加、修改数据文件。
- 添加和提交更改:将更改添加到暂存区(add),然后提交到本地仓库(commit)。
- 合并分支:将开发分支合并到主分支,解决可能的冲突。
- 推送更改:将本地仓库的更改推送到远程仓库(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 指针的作用:
指示当前分支:通常情况下,
HEAD
指针指向当前分支的最新提交。例如,如果你在main
分支上工作,HEAD
指针会指向main
分支的最新提交。指示特定提交:在某些情况下,
HEAD
指针可以直接指向一个特定的提交,而不是一个分支。这种情况通常发生在使用git checkout
命令切换到一个特定的提交时,这时你的工作目录会进入“分离 HEAD”状态。
常见的 HEAD 操作:
- 切换分支:使用
git checkout branch_name
命令可以将HEAD
指针移动到指定的分支。 - 切换到特定提交:使用
git checkout commit_hash
命令可以将HEAD
指针移动到指定的提交,进入分离 HEAD 状态。 - 创建新分支:使用
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支持按功能模块、时间、版本等标准创建分支,分支可以让开发分多条主线同时进行,每条主线互不影响,在避免分支冲突的情况下也可实现分支合并;
常见的分支命名规范:
- MASTER分支(MASTER是主分支,是代码的核心)
- DEVELOP分支(DEVELOP最新开发成果的分支)
- RELEASE分支(为发布新产品设置的分支)
- HOTFIX分支(为修复软件BUG缺陷的分支)
- 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:毕竟两个人的智慧大于一个人的智慧,如果你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不要害羞和回避,可以向他人请教,花点时间直到你真正的理解