CC 咖啡猫的工作空间 Coding Space

Git 与代码协作

原始素材:2-开发环境与工具/2.03-git-version-control.md

这篇解决什么问题

Git 是现代软件开发最重要的基础工具之一。它解决三类问题:

  • 版本管理:知道每次改了什么,并能回到历史版本。
  • 并行开发:不同功能可以在不同分支上推进。
  • 团队协作:多人通过远程仓库共享、审查和合并代码。

这篇文档不要求死背命令,而是先建立几个核心模型:工作区、暂存区、仓库、分支、远程仓库和冲突处理。

Git 和 GitHub 的区别

对比 Git GitHub
是什么 版本控制工具 Git 仓库托管平台
运行在哪里 本地电脑 云端网站
是否必须联网 不需要 需要
作用 记录和管理代码历史 共享代码、PR、Issue、Code Review
类比 本地日记本 云端协作空间

Git 是工具,GitHub 是服务。类似的平台还有 GitLab、Gitee、Bitbucket。

Git 解决的问题

没有 Git 时,版本管理常常变成这样:

项目_v1.zip
项目_v2_修改版.zip
项目_v3_最终版.zip
项目_v3_最终版_真的最终版.zip

Git 的做法是把每次「有意义的改动」保存成一次提交。提交之间形成历史链路,你可以查看、比较、回退和协作。

三个区域:工作区、暂存区、仓库

Git 最核心的模型是三个区域。

区域 英文 说明
工作区 Working Directory 你正在编辑的普通文件夹
暂存区 Staging Area / Index 准备进入下一次提交的改动
仓库 Repository .git 中保存的永久历史

日常提交流程:

修改文件
  -> git add
  -> 暂存区
  -> git commit
  -> 仓库历史

为什么要有 addcommit 两步?

因为你经常不想把所有改动都放进同一次提交。例如:

  • login.js:登录功能,想提交。
  • style.css:登录页样式,想提交。
  • debug.log:临时日志,不想提交。
  • experiment.js:实验代码,还没完成,不想提交。

有暂存区后,你可以只提交真正属于同一件事的改动:

git add login.js style.css
git commit -m "feat: 完成登录页面"

初始化和基础配置

在当前目录初始化 Git 仓库:

git init

第一次使用 Git 时配置身份:

git config --global user.name "你的名字"
git config --global user.email "你的邮箱"

查看配置:

git config --list

日常三步工作流

1. 查看状态

git status

它会告诉你:

  • 当前在哪个分支。
  • 哪些文件修改了但未暂存。
  • 哪些文件已暂存,等待提交。
  • 是否有未跟踪文件。

2. 添加到暂存区

git add login.js
git add login.js style.css
git add .

git add . 很方便,但也容易把临时文件加进去。更稳的习惯是先 git status,再精确添加。

3. 提交

git commit -m "feat: 添加用户登录功能"

提交信息要写给未来的自己和队友看,不要只写 updatefix改了点东西

Commit Message 建议

常见前缀:

前缀 含义
feat: 新功能
fix: 修复 Bug
docs: 文档
style: 格式调整,不影响功能
refactor: 重构
test: 测试
chore: 工具、构建、依赖

示例:

git commit -m "feat: 添加用户登录功能"
git commit -m "fix: 修复 iOS Safari 首页白屏"
git commit -m "docs: 更新部署说明"
git commit -m "refactor: 拆分 UserService"

查看历史和差异

git log
git log --oneline
git diff
git diff --staged

常用场景:

命令 用途
git log --oneline 简洁查看提交历史
git diff 查看工作区未暂存改动
git diff --staged 查看暂存区即将提交的改动
git show <commit> 查看某次提交详情

分支:平行开发线

分支可以理解为一条独立开发线。主分支保持稳定,新功能在功能分支上开发,完成后再合并。

创建并切换分支:

git checkout -b feature-login

查看分支:

git branch

切换分支:

git checkout main
git checkout feature-login

合并分支:

git checkout main
git merge feature-login

删除已合并分支:

git branch -d feature-login

什么时候该开分支?

场景 建议 理由
开发新功能 开分支 完成前不影响主线
修复线上 Bug hotfix/xxx 可快速合并上线
多人并行开发 各自分支 减少互相干扰
改一个错别字 可直接改 风险低

常见分支命名:

分支 用途
main / master 稳定主线
develop / dev 日常集成
feature/user-login 功能开发
fix/login-error 普通修复
hotfix/payment-timeout 紧急修复

远程仓库

远程仓库是团队共享的云端仓库。常用别名是 origin

关联远程仓库:

git remote add origin git@github.com:user/repo.git
git remote -v

第一次推送:

git push -u origin main

之后推送:

git push

拉取远程更新:

git pull

克隆已有项目:

git clone git@github.com:team/project.git

方向记忆:

git push  本地 -> 远程
git pull  远程 -> 本地
git clone 远程 -> 本地完整复制

git pull 实际上约等于:

git fetch + git merge

更谨慎的团队会先 git fetch 看看远程变化,再决定怎么合并。

Pull Request / Merge Request

团队协作通常不会直接把代码推到 main,而是:

创建功能分支
  -> 提交代码
  -> push 到远程
  -> 创建 PR / MR
  -> Code Review
  -> CI 通过
  -> 合并到主分支

PR 的价值:

  • 让队友审查代码。
  • 触发自动测试和构建。
  • 留下讨论和决策记录。
  • 避免直接污染主分支。

冲突处理

冲突通常发生在多人修改同一文件同一位置时。

冲突标记长这样:

function login() {
  const url = '/api/login';

<<<<<<< HEAD
  const timeout = 3000; // 当前分支
=======
  const timeout = 5000; // 合并进来的分支
>>>>>>> feature/update-timeout

  return fetch(url, { timeout });
}

含义:

标记 含义
<<<<<<< HEAD======= 当前分支内容
=======>>>>>>> xxx 合并进来的内容

解决流程:

  1. 打开冲突文件。
  2. 判断保留哪一段,或手动合并两边逻辑。
  3. 删除 <<<<<<<=======>>>>>>> 标记。
  4. 运行测试或至少确认代码能编译。
  5. git add 标记已解决。
  6. git commit 完成合并。
git add login.js
git commit

减少冲突的习惯:

  • 每天开始工作前先拉最新代码。
  • 小步提交,不要攒一周再提交。
  • 功能分支尽量短生命周期。
  • 改公共文件前先和队友沟通。
  • PR 尽量小,便于 review。

stash:临时保存现场

当你改到一半,突然要切分支修 Bug,可以用 stash 暂存未提交改动:

git stash
git checkout hotfix/payment

恢复:

git stash pop

查看 stash:

git stash list

stash 适合临时切换任务,不适合长期保存重要工作。重要改动还是应该提交到分支。

reset、revert 和 checkout 的区别

这些命令容易危险,使用前要确认目标。

命令 作用 风险
git reset 移动当前分支指针,可改写本地历史 对已共享提交要谨慎
git revert 新增一个反向提交,撤销某次改动 安全,适合公共分支
git checkout <file> 恢复文件到某个版本 会丢弃工作区改动

撤销最近一次提交但保留改动:

git reset HEAD~1

撤销已推送到远程的提交,优先用:

git revert <commit>

团队项目标准流程

加入一个团队项目时,可以按这个流程:

# 1. 克隆项目
git clone git@github.com:team/project.git
cd project

# 2. 同步主分支
git checkout main
git pull origin main

# 3. 创建功能分支
git checkout -b feature/user-profile

# 4. 开发后提交
git add src/UserProfile.vue
git commit -m "feat: 添加用户资料页"

# 5. 推送功能分支
git push origin feature/user-profile

# 6. 到 GitHub / GitLab 创建 PR / MR
# 7. 根据 review 修改,继续 commit + push
# 8. 合并后回到 main 并同步
git checkout main
git pull origin main
git branch -d feature/user-profile

.gitignore

不应该提交的文件包括:

  • node_modules/
  • .env.env.local
  • *.log
  • .DS_Store
  • dist/build/
  • IDE 临时文件
  • 密钥、证书、数据库备份

示例:

node_modules/

.env
.env.local

dist/
build/

.DS_Store
Thumbs.db

*.log

如果某个文件已经被 Git 跟踪,后来再加入 .gitignore 不会自动停止跟踪。需要:

git rm --cached <file>

常用命令速查

命令 用途
git status 查看工作区和暂存区状态
git add <file> 添加文件到暂存区
git add . 添加当前目录所有改动
git commit -m "..." 提交暂存区内容
git log --oneline 查看简洁历史
git diff 查看未暂存差异
git diff --staged 查看已暂存差异
git branch 查看分支
git checkout -b <branch> 创建并切换分支
git checkout <branch> 切换分支
git merge <branch> 合并分支
git push 推送到远程
git pull 拉取并合并远程更新
git clone <url> 克隆远程仓库
git remote -v 查看远程仓库
git stash 临时保存未提交改动
git stash pop 恢复最近一次 stash
git branch -d <branch> 删除已合并分支

名词速查表

名词 英文 解释
仓库 Repository 保存项目历史的数据库,位于 .git
提交 Commit 一次完整版本记录。
分支 Branch 独立开发线。
合并 Merge 把一个分支改动整合到另一个分支。
冲突 Conflict 同一位置被不同分支修改,需人工决定。
暂存 Stage / Index 准备进入下一次提交的改动集合。
远程 Remote 云端仓库副本。
克隆 Clone 把远程仓库复制到本地。
推送 Push 上传本地提交到远程。
拉取 Pull 下载并合并远程更新。
HEAD HEAD 当前所在提交或分支指针。
origin origin 默认远程仓库别名。
stash Stash 临时保存未提交改动。
PR / MR Pull Request / Merge Request 请求合并分支并进行代码审查。

小结

  • Git 是版本控制工具,GitHub 是托管平台。
  • 工作区、暂存区、仓库是 Git 的核心模型。
  • addcommit 分开,是为了让提交更精确。
  • 分支让功能开发和主线稳定互不干扰。
  • 远程仓库让团队通过 push、pull、PR 协作。
  • 冲突不可怕,关键是理解冲突标记并手动选择正确结果。
  • .gitignore 用来避免把依赖、密钥、构建产物和临时文件提交进仓库。