Git¶
主要内容
这篇是根据飞书 Git 与版本控制、Git 与 Git 进阶、Github与Gitlab、工程规范 等文档整理的 Git 个人学习笔记。
主要参考:
前置知识:无,但最好能熟悉基本终端操作,例如 cd、ls、mkdir、touch、cat。
预计完成用时:0.5d 到 1d。第一遍能完成基础命令和冲突练习即可,进阶命令可以在真实项目里逐步补齐。
学习目标
基本目标
- 理解 Git、GitHub/GitLab 与版本控制的基本作用。
- 建立使用 Git 管理代码和协作开发的基本意识。
- 掌握常见 Git 基础操作:克隆、提交、推送、拉取、分支切换、查看状态、查看历史。
- 知道代码托管平台在协作、开源参与中的基本用途。
进阶目标
- 能使用 Git 完成日常开发中的基础版本管理和协作操作。
- 能参与 Issue、PR/MR 等协作流程。
- 能处理冲突、回滚错误、临时保存修改、整理本地历史。
- 对开源社区、协作规范与开源伦理有基本认识。
为什么要学 Git¶
最开始我很容易把 Git 理解成“云端备份工具”。但文档强调了两个关键词:版本控制 和 协作。
真正在实际的工程项目中代码几乎没有一次写完的。一个项目会经历需求变化、bug 修复、多人并行开发、线上回滚、版本发布、实验性尝试等情况。如果没有版本控制,就会退回到压缩包、文件名后缀、聊天软件传附件这种混乱的方式:
Git 解决的是:
- 我能知道项目在某个时间点是什么样子。
- 我能比较两次提交之间到底改了什么。
- 我能把一次修改命名、归档、回溯。
- 我能开一条分支做实验,不影响主线。
- 多个人可以同时开发,再把结果合并。
- 出错后可以回退,或者用新提交抵消错误。
GitHub/GitLab 解决的是另一层问题:
- 把 Git 仓库放到一个大家都能访问和协作的平台上,并提供 Issue、PR/MR、权限管理、代码评审、CI/CD、开源社区等能力。
所以,会 Git 命令只是第一步;会协作开发,还要会提交清晰的 commit、开分支、提 PR/MR、处理 review、遵守分支策略、保护主分支。
版本控制¶
VCS 是什么¶
VCS 是 Version Control System,即版本控制系统。它负责记录、管理、回溯文件的修改历史。
按历史形态看,可以分为:
| 类型 | 说明 | 例子 | 个人理解 |
|---|---|---|---|
| VCS 人工 | 手动复制文件、改文件名、打压缩包 | final_v2.zip |
小作业还能忍,团队项目不可维护 |
| LVCS 本地版本控制 | 版本历史主要保存在本机 | RCS | 解决个人历史,但协作能力弱 |
| CVCS 集中式版本控制 | 中央服务器保存主要历史 | SVN | 大家围绕中央服务器工作 |
| DVCS 分布式版本控制 | 每个人本地都有完整仓库历史 | Git、Mercurial | 离线可用,分支和协作更灵活 |
Git 是 DVCS。它不要求每次操作都联网,因为本地就有完整仓库。只有 pull、push、fetch、clone 等与远程交互的命令才需要网络。
分支模型和 Workflow¶
分支模型不是 Git 自带的强制规则,而是团队约定的协作方式。
常见分支可以分为两类:
| 分支类别 | 分支 | 作用 |
|---|---|---|
| 常驻分支 | main / master / production |
产品分支,可发布版本,应该稳定 |
| 常驻分支 | develop / development |
开发主线,从产品分支创建,聚合日常开发 |
| 活动分支 | feature/* |
从开发分支创建,开发某个特性 |
| 活动分支 | hotfix/* |
从产品分支创建,紧急修复线上 bug |
| 活动分支 | release/* |
从开发分支创建,进入正式发布前的整理和修复 |
如果是个人小项目,main + feature/* 足够。
如果是多人项目,至少应该避免所有人直接往 main 上提交。
Git 介绍¶
什么是 Git¶
Git 原作者是 Linus Torvalds, Linux 内核的作者。
Git 是分布式版本控制系统,有几个关键点:
- 分布式:不联网也能提交、查看历史、切分支。
- 版本控制:记录、管理、回溯文件修改历史。
- 基于内容寻址:Git 更像是在保存内容快照和对象,而不是简单保存“文件名”。
- 本地仓库完整:每个 clone 下来的仓库都带有完整历史。
Git 的四个区域¶
| 命令 | 作用 | 对应流向 |
|---|---|---|
git status |
查看当前状态 | 工作区/暂存区 |
git add |
把修改加入暂存区 | 工作区 -> 暂存区 |
git commit |
生成本地提交 | 暂存区 -> 本地仓库 |
git push |
上传提交 | 本地仓库 -> 远程仓库 |
git fetch |
拉取远程对象但不自动合并 | 远程仓库 -> 本地仓库 |
git pull |
拉取并合并/变基 | 远程仓库 -> 本地仓库/工作区 |
git diff |
比较差异 | 工作区、暂存区、提交之间 |
不确定时先
git status,再决定下一步。
安装与准备
安装可参考 Atlassian 的 Install Git 文档。安装后先确认版本:
然后配置身份。这个身份会写进 commit 里:
查看配置:
如果只想对某一个仓库设置身份,就在该仓库目录下去掉 --global:
创建本地版本库¶
git init¶
git init 会让当前文件夹变成 Git 仓库,本质是创建 .git 隐藏目录。
也可以创建新目录并初始化:
初始化之后,文件还不会自动进入版本控制。要经过 add 和 commit。
.git 目录¶
.git 是仓库的核心目录,里面保存对象、引用、配置、索引等内容。不要手动乱改 .git,除非很清楚自己在做什么。
.gitignore¶
.gitignore 放在版本库根目录下,规定哪些文件不要进入 Git 版本库。
常见应该忽略的内容:
.gitignore的意义在于保持工程卫生,使依赖目录、构建产物、日志、私密配置等不污染仓库。
基本语法¶
| 规则 | 含义 | 例子 |
|---|---|---|
# 开头 |
注释 | # logs |
* |
通配多个字符 | *.log |
** |
通配中间目录 | a/**/b 可匹配 a/b、a/x/b、a/x/y/b |
/ 开头 |
只匹配仓库根目录 | /dist 只忽略根目录 dist |
无 / 开头 |
可匹配任意目录 | dist 可忽略任意层级 dist |
! |
取消忽略 | !README.md |
检查某个文件为什么被忽略:
常用模板可以参考 GitHub 的 github/gitignore 仓库。
暂存区、修改与提交¶
git add¶
git add: 把修改加入暂存区。
暂存区像一次 commit 的草稿篮子:可以只提交一部分文件,而不把工作区所有修改都提交。
git commit¶
不带 -m 会打开默认编辑器,要求手动写提交信息。
带 -m 适合较短提交。复杂提交建议写多行:
然后在编辑器里写:
feat(auth): add login form
Add controlled inputs for email and password.
Validate required fields before submitting.
Closes #12
git diff¶
比较工作区和暂存区。
比较暂存区和 HEAD。
比较两个分支。
比较两次提交。
提交前一般可以按照这个顺序看一下:
Commit Message¶
Angular/Conventional Commits 风格。
一个完整格式大概是:
常见字段:
| 字段 | 说明 | 例子 |
|---|---|---|
type |
更改类型 | feat、fix、docs |
scope |
影响范围,可选 | auth、storage、api |
summary |
简短描述 | add login form |
body |
详细描述,可选 | 说明为什么改、怎么改 |
footer |
issue、破坏性变更等 | Fixes #12 |
常见 type:
| 类型 | 含义 |
|---|---|
feat |
新功能 |
fix |
修复 bug |
docs |
文档修改 |
style |
格式修改,不影响逻辑 |
refactor |
重构,不是新增功能也不是修 bug |
perf |
性能优化 |
test |
测试相关 |
ci |
CI/CD 配置相关 |
chore |
工具、依赖、构建等杂项 |
重大更改可以写:
或:
英文 summary 常见要求:一般现在时、首字母小写、句末无句号。
文件状态¶
分为三类:
| 状态 | 含义 |
|---|---|
| Untracked | 未跟踪,新建的本地文件,还没进入版本库 |
| Tracked | 已追踪,已经在版本库里 |
| Ignored | 被忽略,本地存在,但 .gitignore 规定不纳入版本控制 |
git status 会说明当前文件处于哪种状态。很多 Git 初学问题,其实是没分清:工作区改了、暂存区改了、还是已经 commit 了。
查看历史¶
常用变体:
git log --oneline
git log --graph
git log --oneline --graph
git log --oneline --graph --all
git log --stat
git log -p
| 命令 | 用途 |
|---|---|
git log --oneline |
每个提交显示一行,适合快速看历史 |
git log --graph |
显示分支结构 |
git log --stat |
显示文件删改统计 |
git log -p |
显示具体修改内容 |
我常用:
它能让我看到分支结构、HEAD、tag 和远程分支位置。
分支¶
分支是什么¶
分支不是完整复制一份项目,而是指向某次提交的指针。因为 Git 的对象模型,创建分支非常轻量。
创建分支¶
基于当前 HEAD 创建。
基于某次提交创建。
创建并切换分支。
新写法:
查看分支¶
| 命令 | 说明 |
|---|---|
git branch |
查看本地分支 |
git branch -a |
查看本地和远程分支 |
git branch -v |
显示分支及其最新提交 |
git show-branch |
更详细地显示分支关系 |
切换分支¶
新写法:
git checkout - 或 git switch - 可以回到上一个分支。
删除分支¶
如果分支未合并,-d 会拒绝删除。强制删除是:
强制删除前要确认这个分支确实不要了。
checkout 的另一个用法¶
飞书原文提到:
它会把某个文件从暂存区/HEAD 还原到工作区,用来撤销本地修改。新版本 Git 更推荐用:
如果是把暂存区撤回来:
合并¶
merge¶
merge 会把其他分支合入当前分支:
也可以把多个分支合进当前分支:
合并结果会进入工作区和暂存区。如果有冲突,需要人工解决。
多人协作时,一般不直接在命令行把别人分支合进主分支,而是通过 GitHub/GitLab 的 PR/MR 完成,这样可以留下讨论、评审和 CI 检查记录。
squash merge¶
squash merge 会把目标分支多出的多个提交压缩成一个新提交,再合入当前分支。
适合:功能分支上有很多“试一下”“修一下”的临时提交,但最终希望主线历史简洁。
代价:原来的细粒度提交历史不会原样保留在主线。
rebase¶
rebase 是变基,会把当前分支的提交接到目标分支后面:
本地功能分支上,rebase 可以让历史更线性。但它会改写提交历史,所以协作时不要随便 rebase 已经公开、别人也基于它开发的分支。
命令行直接 rebase 会导致提交历史改变,同步时可能冲突,合作时不推荐随意使用。
GitHub PR 里的 rebase merge 和命令行 rebase 的历史方向理解上容易混淆。实际使用时只要记住:会改写历史的操作,不要轻易用在公共分支。
冲突¶
Git 无法自动判断两个修改谁应该保留。
典型流程:
查看状态:
冲突文件里通常会出现:
解决方式:
- 打开冲突文件。
- 判断应该保留哪部分,或手动合并两边逻辑。
- 删除冲突标记。
- 运行测试或至少运行项目。
git add解决后的文件。- 完成 merge commit。
我的经验:解决冲突不要只看文本,要看业务语义。有时两边代码都要保留,但需要重新组织顺序。
修改提交历史¶
飞书原文提醒得很重要:Git 的提交历史可以修改,但如果项目已经公开且有他人协作,就不应该随意修改公共历史。
revert¶
revert 不会删除旧提交,而是生成一个新提交,用来撤销目标提交的更改。
适合:公共分支、线上分支、已经 push 出去的提交。
commit --amend¶
修改最新提交的提交信息:
或直接指定新 message:
它本质上会创建一个新提交替换旧提交,所以也是修改历史。不建议对已经协作共享的提交随便 amend。
有时也可以用 amend 把漏掉的文件补进上一个提交:
reset¶
reset 会移动 HEAD/分支指针。常见模式:
| 模式 | HEAD | 暂存区 | 工作区 | 用途 |
|---|---|---|---|---|
--soft |
回退 | 不改 | 不改 | 撤销提交但保留暂存 |
--mixed |
回退 | 回退 | 不改 | 撤销提交和暂存,保留文件修改,默认模式 |
--hard |
回退 | 回退 | 回退 | 完全回到目标提交,危险 |
例子:
--hard 会丢弃工作区修改,使用前要非常确定。
reflog¶
如果 reset 错了,可以尝试:
reflog 记录 HEAD 的移动历史,可以帮我找回刚刚所在的提交。但它不是永久保险,时间太久或清理后可能丢失。
git stash¶
stash 是隐藏区,可以理解为一个栈。它适合临时保存未完成修改,让工作区变干净。
典型场景:
- 正在一个分支工作,突然需要切到另一个分支处理紧急问题。
- 做了一些实验性修改,不想 commit,但也不想丢。
- 切分支时 Git 提示本地修改会被覆盖。
常用命令:
| 命令 | 说明 |
|---|---|
git stash |
保存当前修改到 stash 栈 |
git stash list |
查看所有 stash |
git stash apply stash@{0} |
恢复某个 stash,但不删除记录 |
git stash drop stash@{0} |
删除某个 stash |
git stash pop |
恢复栈顶 stash,并删除它 |
补充:如果想顺手写说明,可以用:
stash 不是长期保存方案。长期有价值的工作应该 commit 到分支。
tag 与语义化版本¶
tag 常用来标记版本发布点。
创建标签¶
轻量标签:
给某个提交打标签:
附注标签:
查看标签:
推送标签:
语义化版本¶
格式:
例子:
含义:
| 字段 | 含义 |
|---|---|
| 修订号 patch | 兼容修改,修正不正确的行为 |
| 次版本号 minor | 添加新功能,但保持兼容 |
| 主版本号 major | 不兼容的 API 修改 |
| 0.y.z | 表示仍在开发阶段,不保证稳定 |
| 预发布版本 | alpha、beta、rc.1 等 |
进阶命令¶
飞书原文把这部分列为可选,但它们在真实项目里很常见。
fetch / pull / push¶
只拉取远程信息,不自动合并。
拉取并合并,通常相当于 fetch + merge,也可能配置为 fetch + rebase。
把本地分支推到远程。
cherry-pick¶
把某个提交单独摘到当前分支。适合只想拿某个 bugfix,而不是合并整个分支。
show¶
查看某次提交的详细内容。
也可以看 tag:
interactive rebase¶
可以整理最近几个本地提交,例如 squash、reword、drop。只建议用于尚未公开的本地分支。
force push¶
如果 rebase 或 amend 后需要推送改写后的历史,可能要 force push。比 --force 更稳的是 --force-with-lease,它会检查远程是否有别人新提交,降低覆盖别人工作的风险。
但原则是:公共分支尽量不要 force push。
Git Hooks¶
Git Hooks 是在 Git 特定事件前后自动执行脚本的机制。例如:
- commit 前检查格式。
- commit 前检查敏感信息。
- push 前运行测试。
- merge 后清理或生成文件。
常见 hook:
| Hook | 触发时机 | 常见用途 |
|---|---|---|
pre-commit |
commit 前 | 格式化、lint、密钥扫描 |
commit-msg |
commit message 写完后 | 检查 commit 格式 |
pre-push |
push 前 | 运行测试 |
飞书 Hooks 文档还把 Git Hooks 和 AI Agent Hooks 类比:本质都是在某个事件发生时触发自动化动作。区别是 Git Hooks 更偏固定脚本,Agent Hooks 可能让模型或工具参与判断。
远程版本库¶
Git 是分布式 VCS,但多人协作通常需要一个远程的“权威”版本库。远程仓库也是普通 Git 仓库,只是放在 GitHub/GitLab/Gitee 或团队服务器上。
clone¶
指定目录:
clone 会自动建立 remote 关联,通常叫 origin。
查看远程:
添加远程:
修改远程地址:
pull 与 push¶
常见:
第一次推送新分支时:
-u 会建立 upstream,之后可以直接:
SSH 与远程连接¶
远程仓库可以用 HTTPS,也可以用 SSH。SSH 的关键是公钥和私钥。
飞书原文建议使用 ed25519:相较 RSA,key 更短,安全性也更好。
生成 SSH key:
生成后通常会在用户目录下出现 .ssh 文件夹:
| 文件 | 能不能公开 | 说明 |
|---|---|---|
私钥,无 .pub 后缀 |
不能 | 只能自己保存,不能上传网络,不能发给别人 |
公钥,.pub 结尾 |
可以 | 上传到 GitHub/GitLab Settings |
测试 GitHub:
测试 GitLab 时把域名换成对应 GitLab 域名。
一个冷知识:可以通过下面的地址看到某个 GitHub 用户公开添加的 SSH 公钥:
GitLab 也有类似能力。
GitHub / GitLab / Gitee¶
为什么需要代码托管平台¶
如果团队还在用压缩包分享代码,每个人的一次更新都要手动同步,合并也只能靠人肉复制。代码托管平台相当于一个统一的协作中心:大家把更新推上去,再通过一套流程形成最新版本。
GitHub/GitLab/Gitee 不是 Git 本身,而是围绕 Git 提供协作能力的平台。
GitHub¶
GitHub 是最知名的代码托管和开源社区平台。它提供:
- 仓库托管。
- Issue 讨论和任务管理。
- Pull Request。
- GitHub Actions。
- Release。
- Star、Fork、Watch 等开源社区机制。
一般情况下访问 GitHub 可能受网络环境影响。飞书原文也提到,如果暂时无法解决访问问题,可以先用 Gitee 学习基本流程。
GitLab¶
GitLab 可以理解为企业或组织内部常用的 Git 托管平台。学校、实验室、公司都可以部署自己的 GitLab。
飞书原文提到:
- gitlab.com
- X-Lab GitLab:
https://xlab.zju.edu.cn/git
GitLab 中 Pull Request 通常叫 Merge Request,即 MR。
Git Workflow¶
为什么需要 Workflow ?
设想多人都在
main分支上提交:
- 冲突频繁
main可能长期不可用- 不知道哪个提交可以发布
- 难以管理 release
- review 和测试没有统一入口
Git Workflow 就是一套使用 Git 的流程规范。
Feature Branch Workflow¶
适合实验室和多数 Web 项目入门协作。
基本流程:
- 从稳定分支拉取最新代码。
- 创建功能分支。
- 在功能分支开发和提交。
- 推送功能分支到远程。
- 提 PR/MR。
- 经过 review 和 CI 后合并。
- 删除已合并的功能分支。
命令示例:
git switch main
git pull origin main
git switch -c feat/comment-api
# edit files
git status
git diff
git add .
git commit -m "feat(comment): add create comment api"
git push -u origin feat/comment-api
GitFlow Workflow¶
GitFlow 更适合发布节奏明确、版本管理更复杂的项目。
常见分支:
我的理解:
main保持可发布。develop聚合开发成果。feature/*做新功能。release/*做发布前收尾。hotfix/*从生产分支拉出,快速修线上问题。
GitFlow 比 Feature Branch 更重。小项目不要为了“看起来专业”而强行上复杂流程。
Forking Workflow¶
适合开源项目或没有直接写权限的仓库。
基本流程:
- Fork 原仓库到自己的账号。
- Clone 自己的 fork。
- 添加原仓库为 upstream。
- 在自己的分支开发。
- Push 到自己的 fork。
- 向原仓库提 PR。
git remote -v
git remote add upstream <original-repo-url>
git fetch upstream
git switch main
git merge upstream/main
飞书原文提到内部一般更常用 Feature Branch Workflow,但了解 Forking Workflow 有助于参与开源。
PR / MR¶
Pull Request 或 Merge Request 不是“我写完了,帮我合一下”的通知,而是一个可讨论、可审核、可追踪的变更单元。
一份好的 PR/MR 通常包含:
- 改了什么。
- 为什么改。
- 如何验证。
- 有无截图或日志。
- 是否影响接口、数据库、配置、部署。
- 关联的 Issue。
PR/MR 的价值:
- 避免所有人直接改主分支。
- 让代码评审有固定入口。
- 让 CI 自动检查有触发点。
- 让未来回溯知道当时为什么这样改。
工程规范相关¶
飞书 工程规范.md 把 Git 学习延伸到协作规范:目录结构、命名、commit、PR、整洁代码。
为什么需要工程规范
- 提高代码和项目可读性
- 提高可维护性
- 提高协作效率
- 帮助 AI 工具理解项目结构
项目目录规范¶
可以观察开源项目里的目录名:
| 目录 | 常见含义 |
|---|---|
common |
通用逻辑、工具、类型 |
dao |
数据访问层 |
service |
业务逻辑层 |
controller |
请求入口或接口控制层 |
components |
前端组件 |
hooks |
React Hooks 或复用逻辑 |
tests |
测试 |
scripts |
自动化脚本 |
目录规范的目的不是套模板,而是让人能快速定位代码职责。
命名¶
命名要表达语义,并和语言/团队风格一致。
- 小驼峰:
userName、getUserInfo。 - 大驼峰:
UserProfile、CreateOrderRequest。 - snake_case:
user_name、get_user_info。 - kebab-case:
user-profile、create-order。 - 常量:
MAX_RETRY_COUNT。
代码整洁原则¶
飞书原文提到 Clean Code、Clean Architecture、SOLID、DRY、KISS。
我的简化理解:
| 原则 | 笔记 |
|---|---|
| SRP 单一职责 | 一个模块最好只有一个变化理由 |
| OCP 开闭原则 | 尽量通过新增代码扩展行为,而不是频繁修改旧代码 |
| LSP 里氏替换 | 子类型应能替换父类型,不破坏约定 |
| ISP 接口隔离 | 不要让调用方依赖用不到的接口 |
| DIP 依赖反转 | 高层策略不应依赖底层细节,细节应依赖抽象 |
| DRY | 避免重复,把同一逻辑集中维护 |
| KISS | 能简单就简单,避免不必要复杂度 |
这些原则和 Git 的关系是:Git 记录变化,但工程规范决定变化是否容易被理解、review 和维护。
Git 与 AI/Vibe Coding¶
飞书 Vibe Coding 文档里有一句很重要的话:Git 是 Vibe Coding 的“后悔药”。
用 AI 写代码时,改动速度会非常快,如果没有 Git,很容易从“自动化加速”变成“自动化制造混乱”。
我的实践方式:
git switch -c experiment/vibe-demo
# 让 AI 完成一个小阶段
git status
git diff
git add .
git commit -m "feat: add first todo prototype"
原则:
- AI 每完成一个明确阶段,就 commit。
- 尝试新奇方案时开实验分支。
- 方向错了直接回到稳定分支,不要在坏代码上继续堆修复。
- 提交前一定看 diff,不要无脑接受所有改动。
日常 Git 流程
- 新项目
mkdir my-project
cd my-project
git init
git config user.name "Your Name"
git config user.email "your_email@example.com"
printf "node_modules/\ndist/\n.env\n" > .gitignore
git add .
git commit -m "chore: initial commit"
- 参与已有项目
- 提交前
- 提 PR/MR 前
git switch main
git pull origin main
git switch feat/my-task
git merge main
# or: git rebase main, only if this is my private branch
git push -u origin feat/my-task
- 出问题时
先看状态和历史,再决定 restore、revert、reset 还是重新开分支。
Practice
本部分练习可以在 X-Lab GitLab 或 GitLab/GitHub/Gitee 上完成。
远程版本库管理:
- gitlab.com
https://xlab.zju.edu.cn/git- github.com
本地版本管理练习¶
- 新建一个 Git 仓库。
- 在
main分支上进行一版更新。 - 新建一个有辨识度的 branch,例如
feat/conflict-demo。 - 分别在
main分支与 branch 分支上提交一版更新,保证这两个更新会产生冲突。 - Merge 自建 branch 到
main分支,处理 conflict。 - 在
main分支中提交一版更新。 - 将 branch 同步到
main分支的最新更新上。
GitHub/GitLab 练习¶
- 根据 GitHub 官方 hello-world 教程创建一个代码仓库。
- 在平台上创建一个 Issue。
- 从
main创建一个功能分支。 - 推送分支并提 PR/MR。
- 在 PR/MR 描述里写清楚改动和验证方式。
- 合并后删除远程功能分支。
可视化练习¶
- Learn Git Branching
- 搜索 Git 分支可视化教程,辅助理解 merge、rebase、reset、cherry-pick。
常见坑¶
- 把私密配置提交了
.env、数据库密码、token、私钥都不应该提交。已经提交到公开仓库时,删除文件再 commit 不等于从历史中消失,需要进一步清理历史并轮换密钥。
- 在主分支直接开发
个人项目偶尔可以,但团队项目最好用功能分支和 PR/MR。
- 不看 diff 就 commit
尤其使用 AI 工具时,一定要看 diff。AI 可能顺手改了不该改的文件。
- 乱用 reset --hard
reset --hard 会改工作区。没有备份或没有确认前不要用。
- 对公共分支 rebase/force push
这可能覆盖或打乱别人的工作。除非团队流程明确要求,否则不要这样做。
- commit 太大
一个 commit 改了十件事,review 和回滚都会痛苦。更好的方式是按语义拆分提交。
一些名词¶
- HEAD
HEAD 表示当前工作位置,通常指向当前分支的最新提交。理解 HEAD 有助于理解 reset、checkout、rebase。
- Index
Index 就是暂存区。它决定下一次 commit 里会包含哪些内容。
- Origin
origin 是默认远程仓库名,不是固定必须叫这个,只是 clone 后常见默认名。
- Upstream
本地分支关联的远程分支叫 upstream。有 upstream 后,可以直接 git pull、git push。
- Fast-forward
如果当前分支没有额外提交,合并另一个分支时只需要移动指针,这叫 fast-forward。
- 冲突
冲突: Git 无法自动判断两个修改谁应该保留。解决冲突的过程本质是人工合并语义。
- PR
PR :把代码变更转化为可讨论、可审核、可追踪的协作单元。
思考题
-
大家可以看到,我们在文中将 Git 与 GitHub/GitLab 并列介绍。版本控制系统与代码托管平台分别解决什么问题?为什么会用 Git 不等于会协作开发?
版本控制系统解决的是代码历史管理问题。Git 可以记录每次修改、比较差异、创建分支、合并分支、回滚错误。它主要回答“代码如何随时间变化”。
代码托管平台解决的是多人围绕代码协作的问题。GitHub/GitLab 提供远程仓库、Issue、PR/MR、权限管理、CI/CD、代码评审、Release 和开源社区入口。它主要回答“多人如何围绕同一份代码工作”。
会 Git 只是会操作版本历史;协作开发还需要知道如何拆任务、命名分支、写 commit、提交 PR/MR、说明改动、接受 review、处理冲突、保护主分支、遵守开源协议。这些都不是单靠 Git 命令能自动完成的。
-
这一块内容要多多实践,推荐大家去试试相关的操作,去提个 Issue,提个 PR,都会让我们对此部分内容理解得更加深入。
我的实践路线是:先在自己的仓库完成
init -> add -> commit -> branch -> merge -> conflict,再到 GitHub/GitLab 上完成Issue -> branch -> push -> PR/MR -> review -> merge。前者练的是 Git 的版本模型,后者练的是平台协作流程。如果只在本地练 Git,很容易忽略权限、远程分支、PR 描述、CI 检查和 review;如果只会在网页上点按钮,又会在冲突、回滚、同步分支时手忙脚乱。所以这两部分要一起练。
-
什么是小驼峰命名?什么是 snake_case 命名?
小驼峰是第一个单词首字母小写,后续单词首字母大写,例如
userName、getUserInfo、createOrder。snake_case是用下划线连接小写单词,例如user_name、get_user_info、create_order。不同语言和团队有不同习惯。JavaScript/TypeScript 里变量和函数常用小驼峰,Python 里变量和函数常用
snake_case。关键不是某种命名绝对更好,而是项目内部保持一致。 -
Commit 时,
feat、fix等分别表示什么含义?它们是 commit message 中的提交类型,帮助别人快速理解这次提交的性质。
feat:新增功能。fix:修复 bug。docs:文档修改。style:格式修改,不影响代码逻辑。refactor:重构,不是新增功能也不是修 bug。perf:性能优化。test:测试相关。ci:CI/CD 配置相关。chore:依赖、构建、工具配置等杂项。
例如
feat(storage): add file upload api表示在storage这个范围内新增了文件上传接口。