[版本控制器Git] Git 版本控制 | 三区模型与版本回退 | 分支管理

一、Git 解决的是什么问题

版本控制器记录了文件历史与发展过程、方便多人协同的系统,最主流的就是 Git;只是它只能跟踪文本文件的改动,知道第 5 行加了个词,而图片视频这类二进制文件只会告诉你体积变了,改了什么无从得知。

二、安装与最小配置

bash 复制代码
sudo apt install git        # Ubuntu;CentOS 用 yum install git
git --version               # 验证安装
git config --global user.name "Your Name"
git config --global user.email "email@example.com"

装完第一件事是配置身份,否则提交会报错;加 --global 表示这台机器上所有仓库都生效(全局)。

三、三个区与 .git 目录

  • 工作区:写代码、放文件的目录
  • 暂存区:英文 stage 或 index,文件就是 .git/index,所以也叫索引
  • 版本库:工作区里的隐藏目录 .git,里面的文件才受 Git 跟踪

执行 git init 会看到 Initialized empty Git repository。.git 里有四样值得记住:index 是暂存区,HEAD 里存着 ref: refs/heads/master,refs/heads/master 存该分支最新的 commit id,objects 是对象库。

关键结论:往目录里粘贴文件不等于向仓库加文件,必须 add + commit 才算入库

四、add 与 commit 的边界

常用操作:

  1. git add [file] 把改动加入暂存区
  2. git commit -m "描述" 再把暂存区整体写进版本库
  3. 查状态用 git status
  4. 看改动用 git diff(暂存区&工作区的区别)
  5. 看历史用 git log --pretty=oneline

只有被 add 过的改动,才会被这次 commit 带走

git diff使用:

五、objects 里究竟存了什么

commit id 不是 1、2、3 递增的数字,而是 SHA1 算出的十六进制串,前 2 位是目录名、后 38 位是文件名,就藏在 .git/objects/ 下;文件被加密不能直接看,用 git cat-file -p 解开:

复制代码
tree 830a8c9feefbdc098bbae2cdc25e5034ce1920d7
parent c61428926f3853d4ec6dde904415b0e6c1dabcc6
author hyb91 <2689241679@qq.com> 1683343652 +0800
add 3 files

展开 tree 能看到各文件对应的 blob,再展开就是文件内容。所以一次 commit 是"提交对象 → tree → blob"的树状结构,内容相同则 blob 相同

查找object:两部分组成(目录+文件名)

六、版本回退:reset 三兄弟与 reflog

版本写法:HEAD 是当前版本,HEAD^ 与 HEAD~1 是上一个版本,HEAD^^ 是上上一个,也可以直接写 commit id,甚至只写前 7 位。

bash 复制代码
git reset [--soft | --mixed | --hard] [HEAD]
  • --soft:只回退版本库,工作区与暂存区不动;
  • --mixed:默认参数,回退版本库与暂存区,工作区不变;
  • --hard:三者一起回退,工作区有未提交代码时慎用,回滚了就找不回来。

用了 --hard 想再回去,git log 已看不到被丢弃的提交,git reflog 记录了本地每条命令,从中把 id 捞出来即可。

版本回退:

暂存区和工作区都回退到指定版本

reflog查看操作记录:

七、撤销修改与删除文件

撤销分三种情况:

  • 只改了工作区、没 add:git checkout -- [file] 回到最近一次 add 或 commit 的状态,-- 不能省;
  • 已经 add、没 commit:先用 git reset HEAD [file] 把暂存区退回,再用上一条清掉工作区改动;
  • add 也 commit 了:git reset --hard HEAD^,前提是还没推送到远程。

删除文件也是一次修改。直接 rm file5 只删了工作区,git status 提示 deleted,仓库里并没少;误删用 git checkout -- file5 恢复,确实要删则 git rm file5 再 commit。

撤销修改:

强制删除文件:(同时从工作区和暂存区中删除)

八、分支:一个会移动的指针

分支像科幻片里的平行宇宙:这条线上的你在写 C++,那条线上的你在写 Java,互不干扰,将来一合并,两边成果都是你的。每次提交都串成一条时间线,这条线就是一个分支,默认那条叫 master。

HEAD 严格来说不指向提交,而是指向 master,由 master 去指向提交:

bash 复制代码
cat .git/HEAD              # ref: refs/heads/master
cat .git/refs/heads/master # 5476bde...(当前最新 commit id)

8.1 创建、切换与查看

  • git branch:查看本地所有分支,带 * 的是当前分支;
  • git branch dev:新建分支,它和 master 指向同一个 commit;
  • git checkout dev:切换;git checkout -b dev3 则是新建并切换。

切换后工作区内容会跟着变:在 dev 上提交后切回 master,新增内容不见了,因为 master 指针根本没动;再切回 dev 又回来了。

创建和切换分支:

8.2 合并与 Fast-forward

在 master 上执行 git merge dev;若 master 期间没动过,结果是 Fast-forward,直接把 master 指到 dev 的当前提交,速度极快,合并完用 git branch -d dev1 删掉分支。但快进合并后再删分支,历史里就看不出曾有过分支;加 --no-ff 禁用快进,merge 会多生成一个 commit,痕迹得以保留。

合并分支:

8.3 冲突

两边都提交过时,合并必然冲突,Git 用 <<<<<<<、=======、>>>>>>> 标出双方内容;手动改完后还必须重新 add 并 commit,冲突才算真正解决。

合并冲突:

解决冲突:

使用fastforward策略:(不推荐)

禁用fastforward策略:(推荐,新建提交,可以看到提交分支,不会因为分支的删除丢失)

8.4 stash:把现场存起来

正在 dev 上开发一半,突然发现 master 有 bug 要修,代码却还没法提交。此时,需要用git stash 把工作区现场储藏起来,这样git status 立刻干净,可以放心去修 bug;回来用 git stash list 查看、git stash pop 恢复(该条同时删除;用 apply 则保留,需要再次 drop 清除stash)。

修bug的步骤:正在开发的dev分支设置stash -> 另外新建fix_bug分支 -> 修好后在master分支合并删除fix_bug分支 -> 在dev分支与新的master分支合并,恢复stash -> 解决冲突 -> 回到master分支合并没有冲突的dev分支

8.5 分支到底有什么用

要开发一个新功能、需要两周:写一半就提交,不完整的代码会影响别人;等全写完再提交,又怕丢掉每天的进度。有了分支就不怕了------你在自己的分支上干活,别人看不到,想提交就提交,开发完再合并回去;无论版本库有一个还是一万个文件,Git 创建、切换、删除分支都在一秒内完成。

九、总结

  • 三区:工作区改文件、暂存区做缓冲、版本库落库,add 与 commit 缺一不可;
  • 对象库:commit 里包着 tree、tree 里包着 blob,内容相同则 blob 相同;
  • 回退:reset 的 soft/mixed/hard 决定动哪几个区,id 丢了找 reflog;
  • 撤销与删除:分三种情况对症下药,删文件走 git rm 加 commit;
  • 分支:HEAD 指分支、分支指提交,合并有快进与 --no-ff 两种,冲突须手动改完再提交。
相关推荐
王琦03182 小时前
git使用手册
大数据·git·elasticsearch
曦夜日长3 小时前
Git系统篇,Git远程仓库(三):本地仓库与远程仓库的交互
linux·服务器·网络·git·交互
曦夜日长11 小时前
Git系统篇,Git本地使用(一):从“究极进化版“到三个区域的底层原理
大数据·linux·git·elasticsearch
宵时待雨14 小时前
GIT版本管理2:远程操作与多人协作
git
鬼手点金14 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
青柠之夏cc21 小时前
YCM插件与Vim9.1.0496+兼容性问题解析
插件·版本·兼容
csdn2015_1 天前
git多分支切换修改
git
小巫山云子1 天前
Git的用法
大数据·git·elasticsearch
开发者联盟league1 天前
git pull拉取失败UNPROTECTED PRIVATE KEY FILE
git