超详细 Git 讲解(通俗易懂 + 全面覆盖)
超详细 Git 讲解(通俗易懂 + 全面覆盖)
一、先搞懂:为什么需要 Git?(5 分钟)
先从大一同学能理解的场景切入,避免一上来就讲技术:
- 场景 1:写代码改来改去,想回退到昨天的版本,却找不到旧文件;
- 场景 2:实验室多人合作写项目,改同一个文件互相覆盖,代码越改越乱;
- 场景 3:想同时开发两个功能(比如 “登录功能” 和 “注册功能”),改了登录的代码,注册的代码就没法测试。
Git 的核心作用:版本控制 + 多人协作,解决以上所有问题 —— 它就像代码的 “时光机”+“协作神器”,能记录每一次修改,还能让多人并行开发不冲突。
二、Git 核心概念:先把 “地基” 打牢(15 分钟)
1. 分布式 vs 集中式(通俗类比)
- 集中式(如 SVN):代码只有一个 “中央仓库”,所有人必须连网才能提交,中央仓库崩了就全完;
- 分布式(Git):每个人电脑上都有完整的仓库(本地仓库),连网后和远程仓库同步即可,离线也能写代码、提交修改。
2. Git 的 4 个核心区域(用 “快递打包” 类比,一看就懂)
区域 | 通俗解释 | 对应操作 |
工作区 | 你平时写代码的文件夹(未打包) | 编辑代码、新建 / 删除文件 |
暂存区 | 快递打包区(准备提交的代码) |
把工作区文件放到这里 |
本地仓库 | 自家仓库(已打包,有唯一编号) |
把暂存区文件存到这里 |
远程仓库 | 快递公司仓库(如 GitHub/Gitee) |
和本地仓库同步 |
核心逻辑:工作区 → 暂存区 → 本地仓库 → 远程仓库(开发流程);远程仓库 → 本地仓库 → 工作区(拉取代码流程)。
3. 提交(Commit):Git 的 “最小版本单位”
- 每个提交就是一次代码快照,有唯一的哈希 ID(如
a8f57c),包含:修改内容、提交人、时间、提交信息; - 提交信息必须 “有意义”,比如 “修复登录功能的空指针问题”,而非 “改了代码”
基础款写作口诀(记下来):
「动词 + 范围 + 具体内容」
- 动词:实现 / 修复 / 新增 / 删除 / 优化 / 注释(精准描述动作);
- 范围:文件 / 函数 / 模块(比如 tree.c、前序遍历函数、登录模块);
- 具体内容:改了什么、解决了什么问题。
进阶款:行业通用规范(Conventional Commits)
如果实验室有统一协作规范,可套用这个格式:
plaintext
<类型>: <描述> // 空一行(可选) <详细说明>(可选) // 空一行(可选) <关联信息>(可选,比如Fixes #123,关联issue编号)第一步:先记 5 个常用 “类型”(贴合 C 语言 / 实验室场景)
类型 | 含义 | 适用场景(大一同学举例) |
feat | 新增功能 | feat: 新增二叉树层次遍历函数 |
fix | 修复 bug | fix: 修复 tree.c 中 findNode 函数的数组越界问题 |
docs | 仅修改文档 / 注释 | docs: 给二叉树结构体添加字段说明注释 |
style | 仅格式调整(不影响逻辑) | style: 调整 tree.c 的代码缩进,统一 4 空格 |
refactor | 重构代码(不新增功能、不修复 bug) | refactor: 重构前序遍历函数,简化递归逻辑 |
第二步:描述部分 “简洁 + 精准”(不超过 50 个字)
- 开头小写(除了专有名词);
- 不用句号结尾;
- 只说 “做了什么”,不说 “我做了什么”(比如不说 “我修复了 bug”,直接说 “修复 bug”)。
第三步:详细说明(可选,复杂修改时加)
如果修改涉及多步逻辑、多个文件,可补充详细说明(比如 “为什么这么改”“改了哪些文件”)。
完整例子:
plaintext
fix: 修复二叉树销毁函数的内存泄漏问题 1. 原代码中仅free根节点,未递归free左右子节点; 2. 修改destroyTree函数,先递归销毁左右子树,再free根节点; 3. 新增空指针判断,避免段错误。 Fixes #5(实验室项目issue编号,可选)4. HEAD 指针:“当前在哪” 的标记
- HEAD 是一个特殊指针,永远指向 “你当前正在操作的版本 / 分支”;
- 比如你在
main分支,HEAD 就指向main分支的最新提交;回退版本时,HEAD 会跟着指向旧提交。
三、Git 环境配置:从安装到初始化
1. 安装(傻瓜式操作)
- Windows:官网下载 Git 安装包(https://git-scm.com/),一路下一步,记住勾选 “Git Bash Here”(右键能打开命令行);
- Linux:终端输
sudo apt install git(Ubuntu)/sudo yum install git(CentOS); - Mac:终端输
brew install git(需先装 Homebrew)。
验证安装:打开终端 / Git Bash,输git --version,显示版本号就是装好了。
2. 基础配置(必须做!否则无法提交)
Git 需要知道 “你是谁”,才能记录提交人:
bash
运行
# 全局配置(所有仓库生效) git config --global user.name "你的名字(如ZhangSan)" git config --global user.email "你的邮箱(如[email protected])" # 查看配置是否正确 git config --list- 可选优化:配置默认编辑器
bash
运行
# 用VSCode作为编辑器(需先装VSCode并配置环境变量) git config --global core.editor "code --wait" # 用记事本(Windows) git config --global core.editor "notepad++ -multiInst -notabbar -nosession -noPlugin"3. 初始化仓库(两种方式)
方式 1:本地新建仓库(从零开始)
bash
运行
# 1. 新建文件夹(比如lab-project),进入文件夹 mkdir lab-project && cd lab-project # 2. 初始化Git仓库(生成.git隐藏文件夹,核心文件都在这) git init- 注意:
.git文件夹不要删!删了就等于删了整个版本记录。
方式 2:克隆远程仓库(已有项目)
bash
运行
# 克隆仓库到本地(HTTPS方式,不用配密钥,适合新手) git clone https://gitee.com/你的账号/实验室项目.git # 克隆后自动生成文件夹,进入文件夹 cd 实验室项目- 补充:SSH 方式(免密推送,后续讲),先记住 HTTPS 足够用。
四、Git 本地核心操作:工作区→暂存区→本地仓库
1. 查看状态:git status(最常用命令之一)
- 每次操作后都可以输这个命令,看文件处于什么状态;
- 新手必看:
- 红色文字:文件在工作区(未暂存);
- 绿色文字:文件在暂存区(已暂存,待提交);
- 提示 “working tree clean”:工作区和暂存区一致,无未提交修改。
2. 暂存文件:git add(把代码放进 “打包区”)
bash
运行
# 暂存单个文件 git add main.c # 暂存所有修改的文件(常用) git add . # 暂存指定目录下的所有文件 git add src/ # 交互式暂存(选部分代码提交,进阶但实用) git add -p- 新手坑:
git add后文件只是进了暂存区,还没保存到仓库!
3. 撤销暂存:加错文件怎么办?
bash
运行
# 撤销单个文件的暂存(回到工作区) git reset HEAD main.c # 撤销所有暂存的文件 git reset HEAD .4. 提交修改:git commit(把打包的代码存进本地仓库)
bash
运行
# 基础提交(必须写提交信息) git commit -m "feat: 新增二叉树前序遍历函数" # 提交信息规范 # 类型: 描述(类型:feat=新增功能,fix=修复bug,docs=改文档,style=格式调整)- 补充操作:bash运行
# 修改最后一次提交的信息(还没推远程时用) git commit --amend # 把暂存区文件合并到最后一次提交(避免重复提交) git commit --amend --no-edit5. 查看提交历史:git log(看 “时光机” 记录)
bash
运行
# 完整日志(显示哈希ID、提交人、时间、信息) git log # 简洁日志(一行显示,适合看整体) git log --oneline # 图形化日志(带分支关系,后续讲分支时用) git log --graph --oneline --all # 显示每次提交的修改内容(看改了哪些代码) git log -p6. 版本回退:回到过去(核心!解决 “代码改崩了”)
第一步:找到要回退的版本 ID
输git log --oneline,会看到类似这样的记录:
plaintext
a8f57c (HEAD -> main) fix: 修复遍历空指针问题 7b92d1 feat: 新增中序遍历 5c68e1 init: 初始化项目,添加二叉树结构体- 每个版本的前 7 位字符就是 ID(如
5c68e1)。
第二步:执行回退(三种模式,通俗讲)
命令 | 效果(通俗版) | 适用场景 |
| 工作区 + 暂存区 + 仓库全回退,彻底回到旧版本 | 代码完全改崩,想从头再来 |
| 仓库 + 暂存区回退,工作区保留修改 | 想保留工作区代码,重新提交 |
| 仅仓库回退,暂存区 + 工作区都保留 | 只是提交信息写错,想重提交 |
- 示例:回退到初始化版本
bash
运行
git reset --hard 5c68e1第三步:恢复误回退的版本(救命!)
如果回退后后悔了,用git reflog(记录所有操作记录):
bash
运行
# 查看所有操作记录(包括回退、提交、切换分支) git reflog # 找到回退前的版本ID,再切回去 git reset --hard a8f57c7. 忽略文件:.gitignore(避免提交无用文件)
大一同学常犯的错:把编译后的.exe、日志文件、临时文件提交到仓库,导致仓库臃肿。
第一步:新建.gitignore文件
在仓库根目录新建文件,命名为.gitignore(注意前面有个点)。
第二步:编写忽略规则(通俗示例)
plaintext
# 忽略所有C语言编译后的可执行文件 *.exe *.out # 忽略日志文件 *.log # 忽略指定文件夹(比如存放测试数据的data文件夹) data/ # 忽略指定文件(比如配置文件config.h) config.h # 例外:虽然忽略*.log,但保留test.log !test.log第三步:生效规则(已提交的文件需额外操作)
- 如果文件还没提交:直接保存
.gitignore,git add .即可; - 如果文件已经提交过:先从仓库删除,再忽略
bash
运行
git rm --cached main.exe # 从仓库删除,保留本地文件 git add .gitignore git commit -m "docs: 添加.gitignore,忽略可执行文件"五、Git 分支:并行开发的核心(25 分钟)
1. 分支是什么?(用 “游戏存档” 类比)
- 主分支(
main/master):正式版本的存档,永远保持可运行; - 功能分支(如
dev-login):新开一个存档,专门开发登录功能,不影响主存档; - 开发完功能后,把功能分支合并回主分支,就像 “把新功能整合到正式存档”。
2. 分支核心命令(手把手教)
bash
运行
# 1. 查看分支 git branch # 查看本地分支(*号表示当前分支) git branch -r # 查看远程分支 git branch -a # 查看所有分支(本地+远程) # 2. 创建分支 git branch dev-tree # 创建dev-tree分支(仅创建,不切换) # 3. 切换分支 git checkout dev-tree # 切换到dev-tree分支 # 4. 创建+切换(最常用) git checkout -b dev-tree # 等价于上面两步 # 5. 删除分支(已合并到主分支) git branch -d dev-tree # 6. 强制删除(未合并,确认不要了再删) git branch -D dev-tree3. 分支合并:把功能整合到主分支(核心流程)
以 “把dev-tree分支合并到main分支” 为例:
bash
运行
# 第一步:切换到主分支(要合并到哪个分支,就切到哪个) git checkout main # 第二步:确保主分支是最新的(后续远程协作会讲) git pull origin main # 第三步:执行合并 git merge dev-tree两种合并方式(通俗讲)
- Fast-forward(快进):如果主分支没新修改,直接把主分支指针移到功能分支的最新提交(无冲突);
- No-fast-forward(推荐):创建新提交,保留分支历史(能看出来 “这个功能是从 dev-tree 合并来的”):bash运行
git merge --no-ff -m "merge: 合并二叉树功能到main" dev-tree4. 冲突解决:多人协作必遇问题(别怕!)
冲突产生场景
两个分支修改了同一个文件的同一行代码,Git 不知道保留哪个,就会标红冲突。
冲突标识(打开文件能看到)
c
运行
<<<<<<< HEAD // 当前分支(main)的代码 printf("二叉树前序遍历\n"); ======= // 待合并分支(dev-tree)的代码 printf("Binary Tree PreOrder\n"); >>>>>>> dev-tree // 分支名解决步骤(三步搞定)
- 手动修改文件:保留需要的代码,删除冲突标识(
<<<<<<</=======/>>>>>>>);比如保留中文版本:printf("二叉树前序遍历\n"); - 暂存修改后的文件:
git add 冲突文件名; - 完成合并提交:
git commit -m "fix: 解决二叉树遍历文案冲突"。
六、Git 远程协作
1. 远程仓库基础操作
第一步:关联远程仓库(本地新建仓库需做)
bash
运行
# 关联远程仓库(origin是远程仓库的别名,默认叫origin) git remote add origin https://gitee.com/你的账号/实验室项目.git # 查看关联的远程仓库 git remote -v第二步:推送本地代码到远程(第一次推送)
bash
运行
# -u:关联本地分支和远程分支(后续推送只需git push) git push -u origin main第三步:后续推送(本地有新提交后)
bash
运行
git push origin main # 推main分支 git push origin dev-tree # 推功能分支第四步:拉取远程最新代码(同学改了远程仓库,你要同步)
bash
运行
# 拉取并合并(等价于git fetch + git merge,新手用这个) git pull origin main # 仅拉取不合并(进阶,先看修改再合并) git fetch origin main git merge origin/main2. 多人协作标准流程(实验室必遵守)
避免多人直接改主分支,规范流程:
- 克隆远程仓库到本地:
git clone 仓库地址; - 新建功能分支:
git checkout -b 你的功能分支(如dev-zhangsan-tree); - 本地开发、提交:
git add .→git commit -m "xxx"; - 拉取主分支最新代码(避免冲突):
git pull origin main; - 推送自己的功能分支到远程:
git push -u origin 你的功能分支; - 提合并请求(PR/MR):在 Gitee/GitHub 上点 “合并请求”,让负责人审核;
- 审核通过后,负责人把你的分支合并到主分支;
- 本地删除功能分支:
git checkout main→git pull origin main→git branch -d 你的功能分支。
3. SSH 免密推送(进阶,解决每次输密码)
大一同学如果觉得每次推送输账号密码麻烦,可以配置 SSH:
- 生成 SSH 密钥:
ssh-keygen -t rsa -C "你的邮箱"(一路回车,默认路径); - 复制公钥:
- Windows:打开
C:\Users\你的用户名\.ssh\id_rsa.pub,复制里面的内容; - Linux/Mac:
cat ~/.ssh/id_rsa.pub,复制输出内容;
- 粘贴到 Gitee/GitHub 的 “SSH 公钥” 设置里;
- 测试:
ssh -T [email protected](Gitee)/ssh -T [email protected](GitHub),显示欢迎信息就是配好了; - 切换仓库地址为 SSH:
git remote set-url origin [email protected]:你的账号/实验室项目.git。
七、Git 进阶技巧(10 分钟,补充)
1. 暂存工作区:git stash(临时存代码)
场景:正在开发功能,突然要改 bug,不想提交未完成的代码:
bash
运行
# 暂存当前工作区(给暂存起个名字,方便识别) git stash save "未完成的二叉树后序遍历" # 查看暂存列表 git stash list # 恢复暂存(并删除暂存记录) git stash pop # 恢复指定暂存 git stash apply stash@{0} # 删除暂存记录 git stash drop stash@{0}2. 标签:标记重要版本(如发布版)
bash
运行
# 创建轻量标签(仅标记) git tag v1.0.0 # 创建带注释的标签(推荐) git tag -a v1.0.0 -m "第一个版本:实现二叉树基本遍历" # 推送标签到远程 git push origin v1.0.0 # 查看所有标签 git tag3. 变基:git rebase(整理提交历史)
场景:提交记录太乱,想合并成整洁的记录(替代 merge,避免分支分叉):
bash
运行
# 把dev-tree分支的提交,变基到main分支最新版本 git checkout dev-tree git rebase main # 解决变基冲突(和merge冲突解决一样),解决后输: git add . git rebase --continue # 变基完成后,合并到main分支 git checkout main git merge dev-tree八、Git 常见坑与避坑指南(5 分钟,必讲)
- 不要直接改 main 分支:永远在功能分支开发,合并前先审核;
- 提交信息不要乱写:用 “类型:描述” 的格式,方便后续追溯;
- 删除.git 文件夹 = 删版本记录:千万不要删!
- 回退远程已推送的版本:不要用
git reset --hard,改用git revert(创建新提交撤销旧提交); - 冲突只改自己懂的代码:不要乱删同学的代码,不确定就问;
- 定期拉取远程代码:避免本地代码太旧,合并时产生大量冲突。
总结:Git 核心工作流程(一句话记牢)
克隆/初始化仓库 → 新建分支开发 → git add 暂存 → git commit 提交 → git pull 拉取最新 → git push 推送 → 提合并请求 → 合并到主分支