版本控制
什么是版本控制
版本控制(Version Control)是一种记录文件内容变化,以便将来查阅特定版本修订情况的系统。它可以帮助我们:
追踪文件的修改历史,查看谁在何时做了什么更改
恢复到之前的版本,当出现错误时可以快速回滚
多人协作时管理代码,避免文件冲突和覆盖
并行开发不同功能,最后再合并到一起
简单来说,版本控制就像给你的项目创建了一系列"快照",你可以随时回到过去的任何一个状态。
版本控制系统的类型
1.本地版本控制系统
在本地磁盘上保存文件的不同版本
例如:RCS(通过补丁集记录文件差异)
2.集中式版本控制系统
所有版本数据存储在中央服务器
开发者从中央服务器拉取代码,完成后再推回
例如:SVN、CVS
缺点:中央服务器故障时无法协作,数据有丢失风险
3.分布式版本控制系统
每个开发者的本地都有完整的版本库副本
无需联网即可提交、查看历史
拥有更强的分支管理能力
例如:Git、Mercurial、Bazaar
优势:容错性高,协作灵活,支持离线工作
版本控制系统区别
Git了解
什么是Git
Git是目前最流行的分布式版本控制系统,设计目标是:
速度快
支持非线性开发(强大的分支能力)
完全分布式
能高效处理大型项目(如Linux内核)
Git与其他版本控制系统的主要区别在于:它对待数据的方式更像是一个"快照流",而不是文件变化的列表。每次提交,Git都会对当时的全部文件创建一个快照并保存引用,而不是只记录差异。
Git核心概念
1.工作区(Working Directory)
你当前正在编辑的文件目录
这些文件可能处于未跟踪或已修改状态
2.暂存区(Staging Area)
一个文件(通常位于.git/index),用于临时保存你打算提交的修改
可以理解为待提交内容的缓冲区
3.本地仓库(Local Repository)
存储所有版本历史的数据库
位于工作区的.git目录中
包含所有提交记录、分支信息等
4.远程仓库(Remote Repository)
托管在网络上的仓库(如GitHub、GitLab)
用于多人协作时同步代码
5.提交(Commit)
对工作区修改的一次永久记录
每个提交都有一个唯一的哈希值作为标识
6.分支(Branch)
指向某个提交的指针
默认分支通常名为main或master
可以创建多个分支并行开发不同功能
工作流程
1.修改文件:在工作区编辑文件
2.暂存修改:将需要提交的修改添加到暂存区(git add)
3.提交修改:将暂存区的内容提交到本地仓库(git commit)
4.同步远程:将本地仓库的修改推送到远程仓库(git push),或从远程拉取他人的修改(git pull)
Git优点
性能卓越:Git的所有操作几乎都是本地执行,速度极快
强大的分支管理:创建和合并分支非常高效,支持复杂的工作流
分布式架构:每个开发者都有完整副本,不怕数据丢失
广泛采用:几乎成为行业标准,大量开源项目和企业使用
丰富的生态:有GitHub、GitLab等平台提供托管服务,以及众多工具支持
Git工作流
集中式工作流:类似SVN,所有人在同一个分支上工作
功能分支工作流:每个功能在单独分支开发,完成后合并到主分支
GitFlow工作流:有严格的分支模型,区分功能开发、发布准备和bug修复
Forking工作流:适合开源项目,通过Fork和Pull Request协作
Git常用命令
一、基础配置(首次使用必做)
Git 首次安装后需配置用户信息(关联提交记录),可通过 --global 配置全局(所有仓库生效),或不加该参数配置当前仓库。
二、仓库操作(初始化/克隆/查看状态)
包括本地仓库初始化、从远程克隆仓库,以及查看仓库文件状态。
1. 初始化与克隆
2. 查看仓库状态
三、分支管理(核心操作)
Git 分支是并行开发的核心,常用命令包括创建、切换、合并、删除分支等。
四、提交与撤销(代码暂存/提交/回滚)
代码从“工作区”到“暂存区”再到“本地仓库”的流程,以及错误操作后的撤销方法。
1. 暂存与提交
交互式暂存:按“代码块”选择文件内容进行暂存,适合只提交文件中部分修改的场景(如同一文件修改了两个功能,只想提交其中一个)。执行后会逐块显示修改内容,按提示操作:
y:暂存当前块
n:跳过当前块
q:退出交互补充提交 若上一次提交遗漏了文件或需修改提交信息:
git add 遗漏的文件.js # 先暂存遗漏的文件 git commit --amend # 合并到上一次提交
2. 撤销操作
四种回滚的区别
⚠️ 核心避坑:代码已推送到远程时,禁用 reset,改用 git revert(生成新提交来抵消旧修改)。
五、远程协作(与远程仓库交互)
团队协作中,需与 GitHub/GitLab 等远程仓库同步代码(拉取/推送/关联)。
常用命令实例
git status/git status -s
查看状态
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
尚无提交
无文件要提交(创建/拷贝文件并使用 "git add" 建立跟踪)
# 创建三个空文件分别命名为a b c
[root@zuolaoshi git_data]# touch a b c
# 查看是否有这三个文件
[root@zuolaoshi git_data]# ls
a b c
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
尚无提交
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
a
b
c
提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪) git add
暂存内容
# 将当前工作目录下的所有更改一次性全部添加到暂存区
[root@zuolaoshi git_data]# git add a
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
尚无提交
要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)
新文件: a
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
b
c
# 查看当前目录下 .git 文件夹内部的内容
[root@zuolaoshi git_data]# ll .git/
总用量 16
drwxr-xr-x 2 root root 6 4月 3 05:34 branches
-rw-r--r-- 1 root root 92 4月 3 05:34 config
-rw-r--r-- 1 root root 73 4月 3 05:34 description
-rw-r--r-- 1 root root 23 4月 3 05:34 HEAD
drwxr-xr-x 2 root root 301 4月 3 05:34 hooks
-rw-r--r-- 1 root root 96 4月 5 06:05 index
# 你会发现index的时间产生了变化,这意味着,我们使用git add命令将文件提交到了暂存区域
drwxr-xr-x 2 root root 21 4月 3 05:34 info
drwxr-xr-x 5 root root 40 4月 5 06:05 objects
# Git 会把 a、b、c 这三个文件的内容压缩打包,变成一个个“对象(Objects)”存入 .git/objects 文件夹中,并生成一个哈希值(Hash)来作为它们的唯一身份标识
drwxr-xr-x 4 root root 31 4月 3 05:34 refs
# 查看 Git 仓库的底层数据库(对象库)中实际存储了哪些数据
[root@zuolaoshi git_data]# ll .git/objects/
总用量 0
drwxr-xr-x 2 root root 52 4月 5 06:05 e6
drwxr-xr-x 2 root root 6 4月 3 05:34 info
drwxr-xr-x 2 root root 6 4月 3 05:34 pack
# 查看e6 这个文件夹里面的东西
[root@zuolaoshi objects]# ls e6
9de29bb2d1d6434b8b29ae775ad8c2e48c5391
# 上边这个乱码本质上是一个哈希值,但在文件系统里,Git 把它当成了文件名来用
[root@zuolaoshi objects]# cat e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
# 在objects目录中可以看到已元数据形式存储的a文件,这个我们看不懂,我们可以将数据都添加
# 将当前目录及所有子目录下的所有更改,一次性添加到暂存区
[root@zuolaoshi git_data]# git add . #可以使用.也可以使用*
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
尚无提交
要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)
新文件: a
新文件: b
新文件: cgit rm
将文件从暂存区撤回到工作区(变成未跟踪的)、然后再删除文件;也可以直接从暂存区删除
# 将文件 c 从 Git 的暂存区(版本控制)中移除,但保留你电脑本地硬盘上的这个文件
[root@zuolaoshi git_data]# git rm --cached c
rm 'c'
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
尚无提交
要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)
新文件: a
新文件: b
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
c
# 强制删除c文件
[root@zuolaoshi git_data]# rm -fr c
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
尚无提交
要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)
新文件: a
新文件: b
# 将文件 b 从 Git 的暂存区(版本控制)中移除,同时把你电脑本地硬盘上的文件 b 也彻底删除
[root@zuolaoshi git_data]# git rm -f b
rm 'b'
# 查看状态 是否删除成功
[root@zuolaoshi git_data]# git status
位于分支 master
尚无提交
要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)
新文件: a
# 将暂存区中所有准备好的更改(比如你之前添加的文件 a)正式提交到本地 Git 仓库中,并附带一条提交说明
[root@zuolaoshi git_data]# git commit -m " new a"
# 成功后显示
[master(根提交) 6ac34be] a
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a
# 查看提交后的状态
[root@zuolaoshi git_data]# git status
位于分支 master
无文件要提交,干净的工作区git mv
将暂存区里的数据改名或移动
1.使用mv命令配合git
# 将文件 a 重命名为 a.txt
[root@zuolaoshi git_data]# mv a a.txt
# 查看是否修改成功
[root@zuolaoshi git_data]# git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add/rm <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
删除: a
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
a.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
# 从暂存区删除a 【但是还有这个文件】
[root@zuolaoshi git_data]# git rm --cached a
rm 'a'
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
删除: a
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
a.txt
# 将新文件 a.txt 添加到 Git 的暂存区(Staging Area),准备在下一次提交时将其纳入版本控制
[root@zuolaoshi git_data]# git add a.txt
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
重命名: a -> a.txt ########识别到a和a.txt是重命名的文件
# 将刚才在暂存区准备好的“重命名操作”正式、永久地保存到本地 Git 仓库中
[root@zuolaoshi git_data]# git commit -m "rename a to a.txt"
# 提交后显示
[master 47a267c] a.txt
1 file changed, 0 insertions(+), 0 deletions(-)
rename a => a.txt (100%)
2.使用git mv直接重命名
# 将文件 a.txt 重命名回 a,并且自动将这次重命名操作加入暂存区
[root@zuolaoshi git_data]# git mv a.txt a
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
重命名: a.txt -> a
# 将刚才使用 git mv 准备好的“重命名操作”正式、永久地保存到本地 Git 仓库中
[root@zuolaoshi git_data]# git commit -m "rename a.txt to a"
# 提交后显示
[master a714e37] a
1 file changed, 0 insertions(+), 0 deletions(-)
rename a.txt => a (100%)git diff
git status 只能查看区域状态的不同 ,不能查看文件内容的变化。
git diff 查看内容的不同
# 查看文件差异
[root@zuolaoshi git_data]# git diff #没有变化时不显示内容
# 修改a文件
[root@zuolaoshi git_data]# vim a
hello
abc
# 将文件 a 当前的修改状态添加到 Git 的暂存区
[root@zuolaoshi git_data]# git add a
# 修改文件a
[root@zuolaoshi git_data]# vim a
hello
test
test1
# 调整完成文件后,对比本地工作目录和暂存区文件的差异【主要看自己改了那些 决定是否加入暂存区】
[root@zuolaoshi git_data]# git diff a
diff --git a/a b/a
# git格式的diff命令,进行比较的是a版本的a文件和b版本的a文件
index e69de29..ce01362 100644
# 两个版本的哈希值,100644表示是对象是普通文件,权限是644
--- a/a #---表示变动前,也就是a版本的a文件
+++ b/a #+++表示变动后,也就是b版本的a文件
@@ -1,2 +1,3 @@ ## 以@符号开始和结束“-1,2”表示前一个文件从第一行开始的连续两行;“+1,3”表示后一个文件的从第一行开始连续的3行(-表示前一个文件,+表示后一个文件)
hello
-abc #-表示去掉的内容
+test
+test1 #+表示新增的内容
# 对比暂存区和最新一次提交的差异
[root@zuolaoshi git_data]# git diff --cached a
diff --git a/a b/a
index e69de29..0e3af97 100644
--- a/a
+++ b/a
@@ -0,0 +1,2 @@
+hello
+abcgit commit -m
将暂存区内容提交到本地仓库-m后面是描述信息
# 将a文件的最新修改提交到本地Git仓库中并标记为第二个版本
[root@zuolaoshi git_data]# git commit -m "version2 a"
# 显示如下
[master 8f01c62] version2 a
1 file changed, 2 insertions(+)
# 查看文件 a 在“暂存区”与“最新一次提交”之间的差异
[root@zuolaoshi git_data]# git diff --cached a
# 打开一个文本编辑器,让你编写详细的提交信息
git commit
# 相当于虚拟机的镜像、任何操作都被做了一次快照 ,可恢复到任意一个位置git commit -am
快速提交到本地仓库
# 查看当前文件内容
[root@zuolaoshi git_data]# cat a
haha
# 确认一下工作区是否有文件
[root@zuolaoshi git_data]# git diff
# 追加内容到a文件
[root@zuolaoshi git_data]# echo hello >> a
# 查看差异报告【前面的加号表示新增】
[root@zuolaoshi git_data]# git diff
diff --git a/a b/a
index 5ad28e2..5c06d49 100644
--- a/a
+++ b/a
@@ -1 +1,2 @@
haha
+hello
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: a
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
# 将a文件放入暂存区
[root@zuolaoshi git_data]# git add a
# 提交到本地仓库
[root@zuolaoshi git_data]# git commit -m "add hello"
# 提交后显示
[master 2add75e] add hello
1 file changed, 1 insertion(+)
# 确认工作区是否有文件
[root@zuolaoshi git_data]# git diff
# 在a文件中添加haha
[root@zuolaoshi git_data]# echo haha >> a
# 将文件 a 的最新修改自动加入暂存区,并直接提交到本地仓库
[root@zuolaoshi git_data]# git commit -am "add haha"
# 也可以使用-am直接提交到仓库,相当于先git add再git commit -m,但必须是跟踪状态的文件,参数a必须在m前面,否则会报错,无法提交。
# 提交后显示
[master f3d6391] add haha
1 file changed, 1 insertion(+)
# 查看工作区状态
[root@zuolaoshi git_data]# git diff
[root@zuolaoshi git_data]# git status
位于分支 master
无文件要提交,干净的工作区
# 查看提交历史
[root@zuolaoshi git_data]# git log --oneline
f3d6391 (HEAD -> master) add haha
2add75e add hellogit checkout –
检出,重写工作区数据
# 在a文件中添加haha
[root@zuolaoshi git_data]# echo haha >> a
# 查看a文件的内容
[root@zuolaoshi git_data]# cat a
hello
test
test1
123
haha
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: a
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
# 将文件 a 恢复到暂存区(或最新一次提交)的状态,直接丢弃你在本地工作区对它做的所有修改
[root@zuolaoshi git_data]# git checkout -- a
# 查看状态
[root@zuolaoshi git_data]# git status
位于分支 master
无文件要提交,干净的工作区
# 查看文件
[root@zuolaoshi git_data]# cat a
hello
test
test1
123git reset HEAD
本地仓库覆盖暂存区域
# 将a的内容清空
[root@zuolaoshi git_data]# echo "" > a
# 提交到暂存区
[root@zuolaoshi git_data]# git add a
# 提交到仓库
[root@zuolaoshi git_data]# git commit -m "test head"
提交后显示
[master dd7925f] test head
1 file changed, 1 insertion(+), 1 deletion(-)
# 添加内容到a
[root@zuolaoshi git_data]# echo haha > a
# 提交到暂存区
[root@zuolaoshi git_data]# git add a
# 确认没有差异
[root@zuolaoshi git_data]# git diff a
# 用本地仓库的数据将暂存区数据覆盖
[root@zuolaoshi git_data]# git reset HEAD a
重置后取消暂存的变更:
M a
# 比较工作区和暂存区的数据差异
[root@zuolaoshi git_data]# git diff a
diff --git a/a b/a
index 8b13789..5ad28e2 100644
--- a/a
+++ b/a
@@ -1 +1 @@
-
+hahagit reset --hard 哈希头名
Git服务程序中有一个叫做HEAD的版本指针,当用户申请还原数据时,其实就是将HEAD指针指向到某个特定的提交版本,但是因为Git是分布式版本控制系统,为了避免历史记录冲突,故使用了SHA‐1计算出十六进制的哈希字串来区分每个提交版本,另外默认的HEAD版本指针会指向到最近的一次提交版本记录,,注意恢复版本后代表的是在这个版本之前的内容全在(包括工作目录和暂存),本版本之后的都没了
# 以极其简洁的“单行格式”查看 Git 提交历史记录
[root@zuolaoshi git_data]# git log --oneline
f3d6391 (HEAD -> master) add haha
2add75e add hello
ff77333 aaa
dd7925f test head
e2e2131 head test
644d678 test head
326e57a v2 a
8f01c62 version2 a
a714e37 a
47a267c a.txt
6ac34be a
# 将当前分支的指针强制回退到哈希值以 e2e2 开头的那个提交版本,并彻底丢弃该版本之后的所有修改和提交记录。
[root@zuolaoshi git_data]# git reset --hard e2e2
HEAD 现在位于 e2e2131 head test
# 查看 Git 提交历史记录
[root@zuolaoshi git_data]# git log --oneline
2add75e (HEAD -> master) add hello
ff77333 aaa
dd7925f test head
e2e2131 head test
644d678 test head
326e57a v2 a
8f01c62 version2 a
a714e37 a
47a267c a.txt
6ac34be a
# 查看文件内容
[root@zuolaoshi git_data]# cat a
test
# git reset --mixed:此为默认方式,不带任何参数的git reset,即是这种方式,移动head指针,改变暂存区内容,但不会改变工作区
# git reset --soft:回退到某个版本,仅移动当前Head指针,不会改变工作区和暂存区的内容
# git reset --hard:彻底回退到某个版本,head指针、工作区和暂存区内容全部改变
--soft用处不是很多;当执行git commit之后想撤回,但还不想覆盖工作区内容时,使用--mixed;当想完全回滚时,使用--hard来覆盖工作区。git reflog
# 查看文件内容,发现恢复错了,本来是想恢复到“add haha”这个位置的
# 查看文件内容
[root@zuolaoshi git_data]# cat a
test
# 使用log查看,发现没有“add haha”的内容了
# 查看 Git 提交历史记录
[root@zuolaoshi git_data]# git log --oneline
e2e2131 (HEAD -> master) head test
644d678 test head
326e57a v2 a
8f01c62 version2 a
a714e37 a
47a267c a.txt
6ac34be a
# 原因很简单,因为我们当前的工作版本是历史的一个提交点,这个历史提交点还没有发生过add bbb更新记录,所以当然就看不到了 ,要是想”还原到未来”的历史更新点 ,可以用git reflog命令来查看所有的历史记录
# 查看 HEAD 指针的“所有移动历史”
[root@zuolaoshi git_data]# git reflog
# 使用git reflog 可查看总历史内容(注意这里面也是所有的commit之后,也就是放到本地仓后的记录)再结合git reset --hard 哈希头部恢复版本快照 ,所有的数据根本就不可能丢失,随便删除,随便恢复(前提是已提交仓库的的内容)
e2e2131 (HEAD -> master) HEAD@{0}: reset: moving to e2e2
2add75e HEAD@{1}: reset: moving to 2add75e
f3d6391 HEAD@{2}: commit: add haha
2add75e HEAD@{3}: commit: add hello
ff77333 HEAD@{4}: commit: aaa
dd7925f HEAD@{5}: commit: test head
e2e2131 (HEAD -> master) HEAD@{6}: commit: head test
644d678 HEAD@{7}: commit: test head
326e57a HEAD@{8}: commit: v2 a
8f01c62 HEAD@{9}: commit: version2 a
a714e37 HEAD@{10}: commit: a
47a267c HEAD@{11}: commit: a.txt
6ac34be HEAD@{12}: commit (initial): a
# 使用reset恢复到“add haha”的版本
[root@zuolaoshi git_data]# git reset --hard f3d6
HEAD 现在位于 f3d6391 add haha
# 查看
[root@zuolaoshi git_data]# cat a
haha
hello
hahaGIT了解及指令操作
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法