1 Git的相关理论知识
(1) 什么是Git
Git的本质使用"快照+引用链"串联所有的历史
- 快照:项目中所有文件的完整切片,被修改的文件会被完整记录,没有被修改的文件会复用(通过 "硬链接复用"------ 未修改的文件)
- 引用链:每次git commit,都会生成一个提交对象,这个提交对象包含三个数据区域(一个父指针、一个快照指针、还有一些元数据);父指针记录前一个提交的指针,快照指针记录当前提交时刻的快照对象,元数据包含提交时的注释、提交时间、作者信息等;
(2)分支介绍
A 分支的本质
分支的本质是指向提交对象的指针,所以创建分支的本质就是:创建一个指向提交对象的指针罢了(该提交对象由当前分支所指向的对象)
B HEAD分支
HEAD分支的本质也是一个直接指向或间接指向某个提交对象的指针,它的核心作用就是告诉Git:我现在正在操作所指向的提交对象
C 分支合并
基于两个分支的「共同祖先-某一个提交对象」,提取并整合各自的新增变更(处理冲突),生成一个记录 "合并关系"的特殊提交对象,最终让目标分支指针指向这个合并结果
D 分支切换
分支切换的本质是将HEAD指针指向对应分支指针所指向的提交对象上(间接指向),并将工作区进行覆盖
(3) Git的作用
- 版本追溯与回滚:通过快照+引用链便可实现版本追溯和版本回滚,避免"改坏了无法复原"或"错误操作致严重后果"等不可控因素造成损失
- 多人协作:多个开发者共同开发同一个项目,能够自动处理或提示冲突
- 分支隔离开发:在不影响主分支的情况下创建分支开发新功能或修复Bug,开发完成后再合并,避免"未完成的代码污染正式版本",支持"并行开发多个需求"
- 备份与恢复:分布式特性让每个节点都有完整的版本库,哪怕服务器崩溃,也能从任意节点恢复完整的项目
- 轻量临时试验:通过临时分支或stash暂存工作,快速尝试新方案,不行就丢弃
(4) 为什么Git能有上述作用
A 为什么能实现"版本追溯与回滚"
因为每次git commit之后,都会自动生成一个快照对象+提交对象,快照对象 记录了整个项目的完整状态(未修改的通过硬链接复用);提交对象记录三个信息(一个父指针、一个快照指针、还有一些元数据);所有提交对象通过父指针形成一条完整的链条,当希望回滚版本时,只需要找到目标版本的提交对象,将对应的快照覆盖掉当前的工作区文件即可实现
B 为什么能实现"分支隔离开发"
每个分支有专属指针,提交只延伸当前分支的历史链,操作只影响当前分支,绝不会影响其他任何分支
C 为什么能支持"多人协作"
要明白为什么Git能够支持"多人协作",咱们就得先弄明白多人协作完成一个项目的必要前提条件有哪些:第一得拥有同一份完整项目;第二得有冲突检测机制;第三为了避免频繁地解决冲突,应该有能够起到隔离作用的独立开发环境。
知道了多人协作必要的前提条件之后,我们接着探讨为什么Git能够支持多人协作开发:
- 首先,每个开发人员都拥有完整的项目副本,即用分布式让多人并行无依赖
- 其次,指针分支机制能够完全隔离每个开发人员的开发流程,哪怕有冲突,也只会在合并的时候暴露冲突
- 再者,哈希确保变更精准提交同步,每一个提交对象都有一个唯一标识的哈希值(我们把它称为哈希ID),这样在Pull和Push时能够实现所有开发者的数据同步
- 最后,合并+冲突检测机制能够自动整合无冲突的部分,还能够标记出冲突的部分
D 为什么能实现"备份与恢复"
明白上上面三个"为什么"之后,就很容易回答这个"为什么"了!因为提交链+暂存区+工作区的机制,能够轻松地备份历史提交对象,也就能够轻松地实现提交恢复了
2 Git的实践联系理论
(1) 配置Git的工作规则及开发者信息
A 配置Git的工作行为
-
编辑器配置:core.editor(指定 Git 调用的编辑器,比如解决冲突、写提交信息时用 VS Code);
示例:git config --global core.editor "code --wait";
-
指令别名:alias(给常用指令起缩写,比如用 git st 代替 git status);
示例:git config --global alias.st status、git config --global alias.co checkout;
B 开发者身份配置
这是最基础也最重要的配置,直接决定「提交对象」中记录的开发者信息 ------ 多人协作时,别人能通过这个信息识别 "谁提交了这段代码"
- 配置项:user.name(你的名字 / 昵称)、user.email(你的邮箱); 示例:git config --global user.name "lv"、git config --global user.email "lv@xxx.com";
- 关联底层:你执行 git commit 时,生成的提交对象会自动包含这两个字段(存在 .git/objects 的提交对象中),通过 git log 能看到每个提交的作者和邮箱,是协作中追溯责任的关键
C 远程连接(关联)
配置 Git 与远程仓库(如 GitHub/GitLab)的连接规则,确保 git push/git pull 能正常工作
- 关联远程仓库:remote.origin.url(本地仓库绑定的远程仓库地址,比如 git remote add origin xxx 本质就是添加这个配置)
- 代理配置:http.proxy/https.proxy(如果网络需要代理才能访问远程仓库,配置代理地址); 示例:git config --global http.proxy "http://127.0.0.1:7890"
- 凭证缓存:credential.helper(缓存远程仓库的账号密码 / Token,避免每次推送都输入); 示例:git config --global credential.helper cache(缓存 15 分钟)
git config 配置的是「Git 工具的行为规则、你的身份信息、协作连接方式」,作用于 Git 本身,不修改工作区的代码或目录;它的核心目的是 "让 Git 适配你的使用习惯和协作需求",而非 "配置工作区环境"------ 工作区的核心是代码文件,而 Git 配置的核心是工具运行逻辑
查看配置:git config --list(所有配置);git config user.email(单个配置)
(2) 仓库操作
核心作用:初始化本地仓库、克隆远程仓库、管理远程仓库关联(对应分布式仓库的「数据中枢」逻辑)
A 初始化本地仓库
git init 仓库名(新建仓库目录并初始化)
本质是创建 .git 文件夹(包含版本库、指针、暂存区等核心文件),让目录成为 Git 可管理的仓库
B 克隆远程仓库
克隆时会复制远程仓库的「所有提交对象、分支指针、快照」,本地生成完整版本库,无需额外初始化
- HTTPS 克隆:
-git clone https://github.com/xxx/project.git - SSH 克隆(需配置密钥):
git clone git@github.com:xxx/project.git - 克隆指定分支:
git clone -b dev https://xxx/project.git
C 管理远程仓库关联
「远程仓库」是协作的核心,origin 是默认远程仓库名称,可自定义
- 查看远程仓库:
git remote(仅显示名称,默认 origin)
git remote -v(显示名称 + 地址) - 添加远程仓库:
git remote add origin https://xxx/project.git - 修改远程仓库地址:
git remote set-url origin https://xxx/new-url.git - 删除远程仓库:
git remote rm origin
D 查看远程仓库
显示远程仓库的分支、提交、同步状态等信息:git remote show origin
(3) 核心开发流程
核心作用:管理【修改→暂存→提交】的链路(对应暂存区、提交对象的底层逻辑),是日常开发最常用的指令组
-
查看工作区 / 暂存区状态: git status
告诉你:哪些文件未暂存、哪些已暂存未提交、是否有冲突,是开发中「避坑必备」
git status(详细状态)
git status -s(精简状态,A= 新增,M= 修改,D= 删除)
-
将工作区修改加入暂存区:git add
本质是更新暂存区(.git/index)的文件快照引用,让 Git 记录待提交的修改清单
- 添加单个文件: git add a.js
- 添加多个文件: git add a.js b.js
- 添加当前目录所有修改:git add .(含新增 / 修改,不含删除);git add -A(含新增 / 修改 / 删除)
- 交互式添加(部分修改): git add -p a.js
-
将暂存区内容提交到版本库:git commit
生成新的「提交对象」(含快照集合、父指针、提交信息),并移动当前分支指针到新提交
- 常规提交(编辑器写说明):
git commit - 一行提交(快速提交):
git commit -m "feat: 新增登录功能" - 跳过暂存区直接提交(已跟踪文件):
git commit -a -m "fix: 修复按钮点击bug" - 补充上一次提交(不新增提交):
git commit --amend
- 常规提交(编辑器写说明):
-
撤销暂存区修改(不影响工作区):git reset
本质是将暂存区的「文件快照引用」恢复为当前分支最新提交的状态,工作区修改不变
git reset HEAD <文件>(取消单个文件暂存)
git reset HEAD .(取消所有文件暂存)
-
撤销工作区未暂存的修改:
用暂存区的文件快照覆盖工作区文件,未暂存的修改会丢失,慎用
git checkout -- a.js
-
删除文件(工作区 + 暂存区): git rm
- 删除文件并从暂存区移除:
git rm a.js - 仅从暂存区移除(保留工作区文件):
git rm --cached a.js
若文件已提交到版本库,git rm 后需 git commit 提交删除操作
- 删除文件并从暂存区移除:
-
重命名/移动文件 : git mv
git mv a.js src/a.js(移动并改名)
等价于「mv a.js src/a.js + git add src/a.js + git rm a.js」,一步完成文件迁移并更新暂存区
(4) 分支操作
核心作用:创建、切换、合并、删除分支(对应分支指针的独立移动、历史链隔离的底层逻辑)
注意:没有初始化的提交对象,那么就不存在分支,因为分支的本质是指向提交对象的一个指针,当对象不存在,自然就没有所指向的对象
A 查看分支
git branch: 查看本地分支和当前分支
git branch -v: 显示分支的最新提交
git brakch -a: 查看所有分支
B 创建分支
git branch dev: 创建新分支dev,此时不会跳转
C 删除分支
git branch -d/D dev: 删除分支dev
D 切换分支
切换分支的本质是「移动 HEAD 指针 + 同步暂存区 / 工作区」,若有未提交修改且冲突,Git 会阻止切换
git checkout dev:切换到dev分支
git checkout -b lufy:创建并切换分支lufy
git checkout -b dev origin/dev:把远程的 dev 分支'复制'到本地,同时切换过去,并且绑定好关联关系
E 合并分支
本质是「提取两分支差异 + 整合 + 生成双父指针的合并提交」,无冲突自动合并,有冲突需手动解决后 git add + git commit
- git checkout main && git merge dev:将 dev 分支上的所有开发成果(提交记录),合并到 main 主分支
- git merge --no-ff dev:在 main 分支(当前分支)合并 dev 分支时,无论是否能 "快进",都强制生成一个新的 合并提交记录(Merge Commit),从而保留 dev 分支的 "分支历史轨迹"(让提交记录能清晰看到 dev 分支的存在和合并过程)
- git merge --abort:放弃合并(当发生合并冲突的时候可以输入此命令)
F 变基合并
让开发分支dev包含分支feature的最新修改
举个例子:
分支feature: A->B->C->D
分支dev: A->B->C->E->F
执行执行: git checkout dev && git rebase feature之后分支的链条如下:
feature: A->B->C->D
dev: A->B->C->D->E'->F'(其中E'和F'是E和F是重新应用后的新提交)
注意:如果 dev 之前推送到过远程,变基后必须用 git push --force-with-lease 强制推送(因为远程的 dev 还保留着原 E、F 提交,与本地新提交冲突)
G 挑选单个 / 多个提交应用到当前分支
相当于「微型合并」,仅应用指定提交的变更,适合复用其他分支的单个功能 / 修复,不影响原分支历史;本质是精准复制单个提交
举个例子:想要将dev的提交abc123dev复制到feature分支上
- step01: 切换到目标分支feature git checkout/switch feature
- step02: 拉取远程 dev 分支的最新提交(本地 dev 已有则跳过) git fetch origin dev
- step03: 复制 dev 分支的 abc123dev 提交到当前 feature 分支 git cherry-pick abc123dev
通过以上操作即可将dev分支的abc123dev的提交对象拷贝到feature上面
H 绑定本地分支与远程分支(跟踪分支)
绑定后可直接用 git pull/git push,无需指定远程分支(如 git pull 等价 git pull origin dev)
git branch --set-upstream-to=origin/dev dev
(5)提交历史操作类(查看 / 回退 / 撤销提交)
核心作用:查看提交历史、回退版本、撤销已提交的修改(对应提交对象、历史链的底层逻辑)
A 查看提交历史
- 基础查看:git log(按时间倒序,显示提交哈希、作者、时间、信息)
- 精简查看(一行一条):git log --oneline
- 显示分支合并关系(图形化):git log --graph --oneline --all
- 显示指定分支历史:git log dev
- 显示最近 N 次提交:git log -n 3
B 查看文件
查看文件提交的变更统计: git log --stat

C 版本回退之git reset
- 软回退(保留工作区 / 暂存区):
git reset --soft 哈希(仅移动分支指针,暂存区和工作区不变) - 混合回退(默认,保留工作区):
git reset --mixed 哈希(移动分支指针 + 重置暂存区,工作区不变) - 硬回退(丢弃所有修改):
git reset --hard 哈希(移动分支指针 + 重置暂存区 + 覆盖工作区)
注意:「硬回退」会丢失指定版本后的所有提交和未提交修改,已推送的分支禁止使用(会导致协作冲突)
D 版本回退之git revert
撤销指定提交(生成新提交,不修改历史)
与 git reset 不同:revert 不会删除历史提交,而是生成一个「反向修改」的新提交,适合撤销已推送的提交(不影响协作)
E 查看Git操作日志
git relog: 记录所有 git 操作(切换分支、提交、回退等),可通过日志中的哈希找回「被删除的分支」或「硬回退后丢失的提交」
(6) 协作同步类(和远程仓库交互)
核心作用:拉取远程变更、推送本地变更(对应分布式仓库的「精准同步」逻辑,基于哈希识别提交)
A 拉取远程仓库的所有变更(不合并)
- 拉取所有远程分支变更:
git fetch origin - 拉取指定远程分支变更:
git fetch origin dev
仅下载远程新增的提交对象和分支指针,不修改本地分支和工作区,需后续 git merge 合并
B 拉取远程变更并合并到当前分支
- 拉取并合并对应远程分支:
git pull(需绑定跟踪分支) - 拉取指定远程分支并合并:
git pull origin dev - 拉取并变基(替代合并):
git pull --rebase origin dev
本质是「git fetch + git merge」,若拉取的变更与本地修改冲突,需先解决冲突再完成合并
C 推送本地分支变更到远程仓库
- 推送当前分支到远程对应分支:
git push(需绑定跟踪分支) - 推送指定本地分支到远程:
git push origin dev - 强制推送(修改已推送历史后):
git push -f origin dev(慎用,会覆盖远程分支) - 推送标签:
git push origin --tags
推送时 Git 会通过哈希验证提交唯一性,仅推送远程没有的提交;若远程分支有新增提交(本地未拉取),会推送失败(避免覆盖远程变更)
D 删除远程分支
git push --delete origin feature: 仅删除远程仓库的分支指针feature,本地分支不受影响
E 暂存工作区 / 暂存区的未提交修改
- 暂存修改:
git stash(默认备注)
git stash save "暂存登录功能修改"(自定义备注) - 查看暂存列表:
git stash list - 恢复暂存(保留暂存记录):
git stash apply stash@{0}(stash@{0} 是暂存索引) - 恢复并删除暂存记录:
git stash pop stash@{0} - 删除所有暂存:
git stash clear
适合「切换分支前暂存未提交修改」,避免冲突阻止切换,暂存的修改会保存在 .git/stash 中
(7) 冲突处理类(合并 / 拉取时解决冲突)
核心作用:处理「变更重叠导致的冲突」(对应 Git 冲突检测的底层逻辑)
-
查看冲突\] git status: 冲突文件会标记为 both modified(双方都修改),需优先处理这些文件
-
标记冲突已经解决\] git add conflict.txt: 告诉 Git 该文件冲突已处理,更新暂存区的快照引用
-
放弃合并/变基\] git merge --abort / git rebase --abort: 恢复到合并 / 变基前的状态,暂存区和工作区回到冲突前的样子
基础配置:git config --global user.name/email
仓库操作:git init、git clone、git remote -v
开发流程:git add .、git commit -m "xxx"、git status
分支操作:git branch、git checkout -b/git switch -c、git merge
协作同步:git pull、git push、git stash/git stash pop
历史查看:git log --oneline、git diff
冲突处理:编辑冲突文件→git add→git commit