1、Git介绍
git就是一个分布式的版本控制软件,直接记录快照,而非差异比较。Git 和其它版本控制系统(包括 Subversion 和近似工具)的主要差别在于 Git 对待数据的方法。 从概念上来说,其它大部分系统以文件变更列表的方式存储信息(基于差异的版本控制)。Git 不按照以上方式对待或保存数据。反之,Git 更像是把数据看作是对小型文件系统的一系列快照。 在 Git 中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。 为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个快照流。
1.1、分布式版本控制的优点
—客户端保存自己的所有版本,同时上传服务器,保存所有版本,支持离线操作。
—每个开发者都是一个仓库的完整克隆,每个人都是服务器
—支持断网操作
1.2、Git的三种状态
已修改(modified) 表示修改了文件,但还没保存到数据库中。
已暂存(staged) 表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
已提交(committed) 表示数据已经安全地保存在本地数据库中。
1.2、Git的三个阶段
—Git仓库:保存所有数据的地方
—工作区:从仓库中提取出来的文件,放在磁盘上供你使用或修改
—暂存区:就是一个文件,索引文件,保存了下次将提交的文件列表信息
2、Git安装
2.1、服务器端部署
2.1.1、环境准备
git服务器:192.168.4.20 (git_server)
关闭selinux和防火墙
2.1.2、安装git软件
[root@git_server ~]# yum -y install git
2.1.3、创建一个目录,名称可以任意
[root@git_server ~]# mkdir /var/lib/git
2.1.4、创建一个空仓库,用来存放文档,历史资料的共享目录
[root@git_server ~]# git init /var/lib/git/project --bare
初始化空的 Git 版本库于 /var/lib/git/project/
[root@git_server ~]# ls /var/lib/git/project/ # 如果有问题,可以rm删除整个目录,重来
branches config description HEAD hooks info objects refs
备注:创建一个仓库project为仓库名称,bare为空仓库,空仓库里面没有文件,但是有配置文件
2.2、客户端部署
2.2.1、环境准备
客户端:192.168.4.10 (develop)
关闭selinux和防火墙
2.2.2、安装git软件
[root@develop ~]# yum -y install git
2.2.3、将服务器的仓库克隆到本地
[root@develop ~]# git clone root@192.168.4.20:/var/lib/git/project
正克隆到 'project'...
The authenticity of host '192.168.4.20 (192.168.4.20)' can't be established.
ECDSA key fingerprint is SHA256:8DaehIVDPXOcaevTRJFuWYDmNuZwjYuRHs8LX54rsic.
ECDSA key fingerprint is MD5:c6:de:92:91:95:30:5b:54:35:3a:7e:89:a2:82:47:a5.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.4.20' (ECDSA) to the list of known hosts.
root@192.168.4.20's password: # 输入密码
warning: 您似乎克隆了一个空版本库
2.2.4、查看,多了一个project目录
[root@develop ~]# ls
project
2.2.5、查看克隆的git仓库的信息
[root@develop ~]# cd project/
[root@develop project]# git remote -v
origin root@192.168.4.20:/var/lib/git/project (fetch)
origin root@192.168.4.20:/var/lib/git/project (push)
注意:客户端做任何git命令都必须先cd进入仓库,否则报错!
2.2.6、git仓库初始化
[root@develop project]# git config --global user.email "jy@163.com" # 定义git用户
[root@develop project]# git config --global user.name "jiangying" # 定义git使用的邮箱
[root@develop project]# git config --global color.ui true # 定义语法高度
[root@develop project]# ls -a # 命令会自动创建一个配置文件
. .. .git
[root@develop project]# cat ~/.gitconfig
[user]
email = jy@163.com
name = test
[color]
ui = true
[root@develop project]# git config --list # 查看git定义的信息
注意:/root/project/就是工作区,/root/project/.git就是本地仓库
2.3、git仓库数据管理机状态
工作流程
- git提交数据到仓库流程:本地仓库为工作目录下/root/project/.git
1. 先git add把新文件提交到暂存区;
2. 再git commit 存到仓库;
3. 最后使用git push提交到远程仓库;
- 用户使用则通过以下命令拉取到本地
1. 使用git clone/git pull将数据同步到本地仓库,再使用相关命令进行操作
git四种状态
untracked:未跟踪的,也就是一个文件没有被git管理、监控起来
unmodified:未修改的文件
modified:已修改的文件
staged:已暂存的文件
工作目录下文件总的可分两种状态:已跟踪 或 未跟踪。
- 已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后, 它们的状态可能是未修改,已修改或已放入暂存区。简而言之,已跟踪的文件就是 Git 已经知道的文件。
- 未跟踪文件,它们既不存在于上次快照的记录中,也没有被放入暂存区。 初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态,因为 Git 刚刚检出了它们, 而你尚未编辑过它们。
- 编辑过某些文件之后,由于自上次提交后你对它们做了修改,Git 将它们标记为已修改文件。 在工作时,你可以选择性地将这些修改过的文件放入暂存区,然后提交所有已暂存的修改,如此反复。
2.3.1、检查当前文件状态
[root@develop project]# git status
# 位于分支 master
#
# 初始提交
#
无文件要提交(创建/拷贝文件并使用 "git add" 建立跟踪)
备注:这说明你现在的工作目录相当干净。换句话说,所有已跟踪文件在上次提交后都未被更改过。 此外,上面的信息还表明,当前目录下没有出现任何处于未跟踪状态的新文件,否则 Git 会在这里列出来。
- 在项目下创建一个新的 README 文件。 如果之前并不存在这个文件,使用 git status 命令,你将看到一个新的未跟踪文件:
[root@develop project]# echo test > README
[root@develop project]# git status
# 位于分支 master
#
# 初始提交
#
# 未跟踪的文件:
# (使用 "git add <file>..." 以包含要提交的内容)
#
# README
提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)
备注:在状态报告中可以看到新建的 README 文件出现在 “未跟踪的文件” 下面。 未跟踪的文件意味着 Git 在之前 的快照(提交)中没有这些文件;Git 不会自动将之纳入跟踪范围,除非你明明白白地告诉它“我需要跟踪该文件”。
2.3.2、跟踪新文件
[root@develop project]# git add README
[root@develop project]# git status
# 位于分支 master
#
# 初始提交
#
# 要提交的变更:
# (使用 "git rm --cached <file>..." 撤出暂存区)
#
# 新文件: README
#
备注:只要在 Changes to be committed 或者“要提交的变更”这行下面的,就说明是已暂存状态。 如果此时提交,那么该文件在你运 行git add时的版本将被留存在后续的历史记录中。
2.3.3、暂存已修改的文件
[root@develop project]# echo aaa >> README
[root@develop project]# git status
# 位于分支 master
#
# 初始提交
#
# 要提交的变更:
# (使用 "git rm --cached <file>..." 撤出暂存区)
#
# 新文件: README
#
# 尚未暂存以备提交的变更:
# (使用 "git add <file>..." 更新要提交的内容)
# (使用 "git checkout -- <file>..." 丢弃工作区的改动)
#
# 修改: README
#
备注:现在我们来修改一个已被跟踪的文件。出现在Changes not staged for commit或者“尚未暂存以备提交的变更”这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。 要暂存这次更新,需要运行 git add 命令。 这是个多功能命令:可以用它开 始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。
2.3.4、使用git status -s查看
[root@develop project]# git status -s
AM README
- ?? 新添加的未跟踪文件
- A 新添加到暂存区中的文件
- M 修改过的文件
2.4、git常用指令
指 令 | 作 用 |
git status/git status -s | 查看状态 |
git diff <文件> | 查看内容的不同 |
git diff --cached <文件> | 对比暂存区和本地仓库的差异 |
git add <文件> | 暂存内容,可以使用.也可以使用* |
git rm -f <文件> | 将文件从暂存区撤回到工作区(变成未跟踪的)、然后再删除文件;也可以直接从暂存区删除 |
git rm --cached <文件> | 取消暂存 |
git mv | 将暂存区里的数据改名或移动 |
git commit -m <文件描述> | 将暂存区内容提交到本地仓库-m后面是描述信息 |
git commit -am | 快速提交到本地仓库,使用-am直接提交到仓库,相当于先git add再git commit -m,但必须是跟踪状态的文件,参数a必须在m前面,否则会报错,无法提交 |
git checkout -- <文件> | 丢弃工作区的改动 |
git reset HEAD <文件> | 用本地仓库的数据将暂存区数据覆盖 |
git reset 选项 <哈希头名> | 选项: --mixed:默认方式,不带任何参数的git reset,即是这种方式,移动head指针,改变暂存区内容,但不会改变工作区 --soft:回退到某个版本,仅移动当前Head指针,不会改变工作区和暂存区的内容 --hard:彻底回退到某个版本,head指针、工作区和暂存区内容全部改变 备注: --soft用处不是很多;当执行git commit之后想撤回,但还不想覆盖工作区内容时,使用--mixed;当想完全回滚时,使用--hard来覆盖工作区。 |
git reflog | 可查看总历史内容(注意这里面也是所有的commit之后,也就是放到本地仓后的记录)再结合git reset --hard 哈希头部恢复版本快照 ,所有的数据根本就不可能丢失,随便删除,随便恢复(前提是已提交仓库的的内容) |
git log | 查看历史的git commit快照操作 |
git log -p | 显示具体变化的内容,调用了git diff |
git log -<数字> | 显示最近几条内容 |
2.4.1、操作案例
2.4.1.1、新建一个文件(文件名任意,内容任意)
[root@develop project]# echo init data > init.txt
2.4.1.2、创建一个目录,拷贝文件进到目录里面
[root@develop project]# mkdir demo
[root@develop project]# cp /etc/hosts demo
2.4.1.3、文件提交暂存区
[root@develop project]# git add .
2.4.1.4、文件存到本地仓库
[root@develop project]# git commit -m "first"
[master(根提交) 65c9371] first
2 files changed, 3 insertions(+)
create mode 100644 demo/hosts
create mode 100644 init.txt
备注:-m后面是注释,可以任意。所有备份都是以数据库的形式保存,无法直接查看。此时,所有资料都是在自己的电脑备份,如果还想备份一份到服务器
2.4.1.5、提交到远程服务器
[root@develop project]# git config --global push.default simple # 设置提交资料到服务器的方式
[root@develop project]# git push # 开始回传资料到服务器
root@192.168.4.20's password: <需要输入密码>
备注:服务器也是以数据库的形式保存,无法直接查看
2.4.1.6、从服务器拉取数据
[root@develop project]# git pull
root@192.168.4.20's password: <密码>
Already up-to-date.
备注:如果有其他同事修改文件,上传了服务器,而自己手里没有新资料,则可以pull从服务器拉取更新的新资料。
2.4.1.7、查看备份的历史日志
[root@develop project]# git log
commit 65c93719e3d6acb9ed06bca3e038c21f05b2b6af
Author: jinagying <jy@163.com>
Date: Sat Jul 9 14:13:13 2022 +0800
first
[root@develop project]# git log --pretty=oneline
65c93719e3d6acb9ed06bca3e038c21f05b2b6af first
[root@develop project]# git log --oneline
65c9371 first
2.5、代码合并分支
合并分支 ,A分支上合并另一分支B,则B的所有内容都合并到了A上,如果分支和主干相差太多,合并就会容易报错,所以通常的操作就是分支合并后就删除分支然后再重新创建分支(完全拷贝主支信息)后再进行后续的合并,依次循环。
2.5.1、查看当前分支
[root@develop project]# git branch
* master
2.5.2、创建分支
[root@develop project]# git branch test
[root@develop project]# git branch test-01
2.5.3、删除分支
[root@develop project]# git branch -d test-01
已删除分支 test-01(曾为 65c9371)。
[root@develop project]# git branch
* master
test
2.5.4、 切换分支
[root@develop project]# git checkout master
已经位于 'master'
[root@develop project]# git branch
* master
test
2.5.5、合并分支
[root@develop project]# git merge test
备注:
1、修改哪个分支的内容,就切换进入哪个分支;
2、想将B的内容合并到A,就必须先切换到A(想合并到哪个分支,就先进入该分支);
2.5.6、冲突合并
[root@develop project]# echo master >> a
[root@develop project]# git add .
[root@develop project]# git commit -m "add master to a"
[master 0f41277] add master to a
1 file changed, 1 insertion(+)
create mode 100644 a
[root@develop project]# git checkout test
切换到分支 'test'
[root@develop project]# echo test >> a
[root@develop project]# git add .
[root@develop project]# git commit -m "add test to a"
[test 0362888] add test to a
1 file changed, 1 insertion(+)
create mode 100644 a
[root@develop project]# git checkout master
切换到分支 'master'
您的分支领先 'origin/master' 共 1 个提交。
(使用 "git push" 来发布您的本地提交)
[root@develop project]# git merge -m "master&test" test
自动合并 a
冲突(添加/添加):合并冲突于 a
自动合并失败,修正冲突然后提交修正的结果。
[root@develop project]# cat a
<<<<<<< HEAD
master
=======
test
>>>>>>> test
2.5.6.1、手动更改冲突内容
[root@develop project]# vim a
[root@develop project]# git commit -am "merge test to master"
[master 8ee7d20] merge test to master
[root@develop project]# cat a
master
test
[root@develop project]# git log --oneline
8ee7d20 merge test to master
0362888 add test to a
0f41277 add master to a
65c9371 first
备注:如果分支和主干相差太多,合并就会容易报错,所以通常的操作就是分支合并后就删除分支然后再重新创建分支(完全拷贝主支信息)后再进行后续的合并,依次循环。
2.6、git标签
标签也是指向了一次commit提交,是一个里程碑式的标签,回滚打标签直接加标签号,不需要加唯一字符串,不用记唯一字符串,与指针的变动(reset)原理相似,也能通用git reset --hard命令。
2.6.1、查看历史记录
[root@develop project]# git log --oneline
8ee7d20 merge test to master
0362888 add test to a
0f41277 add master to a
65c9371 first
2.6.2、打标签
[root@develop project]# git tag -a v1.0 65c9 -m "first to v1.0"
[root@develop project]# git tag -a v2.0 0362 -m "add test to v2.0"
备注:-a:指定标签,标签为v1.0,对应的哈希值为65c9;-m定义描述信息。
2.6.3、查看已有的标签
[root@develop project]# git tag
v1.0
v2.0
2.6.4、查看指定标签的内容
[root@develop project]# git show v1.0
2.6.5、数据回滚到指定标签的位置
[root@develop project]# git reset --hard v1.0
2.6.6、删除标签
[root@develop project]# git tag -d v2.0
2.7、git仓库的免密操作
2.7.1、git服务器操作:创建一个名称为web的空仓库
- git服务器可以基于SSH,也可以基于http或https
[root@git_server ~]# git init --bare /var/lib/git/web
初始化空的 Git 版本库于 /var/lib/git/web/
2.7.2、客户端操作:生成密钥
- 默认情况下clone需要密码,不想使用密码,则可以做ssh密钥
[root@develop ~]# ssh-keygen -f /root/.ssh/id_rsa -N ''
备注:-f:后面指定将创建的密钥文件存放到哪里;-N:后面是空,不对生成的密钥文件加密(两个单引号)。
2.7.2.1、拷贝密钥给git服务器
[root@develop ~]# ssh-copy-id 192.168.4.20
root@192.168.4.20's password: <输入密码>
2.7.2.2、再次clone下载仓库,不需要密码
[root@develop ~]# git clone root@192.168.4.20:/var/lib/git/web
正克隆到 'web'...
warning: 您似乎克隆了一个空版本库。
2.7.2.3、对下载的仓库做一些简单的文件操作,然后push,不需要密码就可以回传资料给git服务器
[root@develop ~]# cd web/
[root@develop web]# echo help > README.md
[root@develop web]# git add .
[root@develop web]# git commit -m "readme"
[master(根提交) 2d498a3] readme
1 file changed, 1 insertion(+)
create mode 100644 README.md
[root@develop web]# git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 207 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To root@192.168.4.20:/var/lib/git/web
* [new branch] master -> master
2.7.3、客户端操作:查看服务器信息
[root@develop web]# git remote -v
origin root@192.168.4.20:/var/lib/git/web (fetch)
origin root@192.168.4.20:/var/lib/git/web (push)
备注:所有资料都是从192.168.4.20的/var/lib/git/web目录下载下来的,后面的IP和账户和目录太长,给这个服务器取一个别名,别名叫origin。
2.7.3.1、客户端push回传资料
[root@develop web]# git push origin master
备注:
- 因为服务器有名字,所以push回传资料可以指定回传到origin服务
- 指定只传master分支(也可以是其他分支,--all代表所有分支)
- 不写,则默认是master分支
2.7.3.2、修改服务器信息
[root@develop web]# git remote rename origin haha # 把origin改为haha
[root@develop web]# git remote -v
haha root@192.168.4.20:/var/lib/git/web (fetch)
haha root@192.168.4.20:/var/lib/git/web (push)
2.7.3.3、删除指定的服务器信息
[root@develop web]# git remote remove haha
[root@develop web]# git remote -v # 输出为空
2.7.3.4、删除后想再添加回来
[root@develop web]# git remote add origin root@192.168.4.20:/var/lib/git/web
[root@develop web]# git remote -v
origin root@192.168.4.20:/var/lib/git/web (fetch)
origin root@192.168.4.20:/var/lib/git/web (push)
2.7.3.5、push回传资料的时候,也可以加一个-u选项(upstream:上游服务器)
[root@develop web]# git push -u origin master
[root@develop web]# git push -u origin --all # --all:表示提交所有分支到服务器