全栈手账 订阅 RSS
Git

Git 常用操作与使用场景手册

按"日常开发会遇到的真实场景"组织命令,而非简单罗列参数。每个操作都附带典型使用场景,便于遇到问题时快速定位。

读了 30 分钟 更新于 7 月 17 日

一、初始化与配置

1. 安装后首次配置

场景:新机器装好 Git 后,设置全局用户名和邮箱,确保提交记录正确归属。

bash
git config --global user.name "你的名字"git config --global user.email "you@example.com"# 查看所有配置git config --list# 设置默认分支名为 maingit config --global init.defaultBranch main# 让 Git 记住账号密码,避免每次输入git config --global credential.helper store

2. 项目级配置

场景:公司项目用企业邮箱,个人项目用私人邮箱,需要按仓库单独设置。

bash
# 进入项目目录后执行(去掉 --global)git config user.name "工作名"git config user.email "work@company.com"

3. 配置别名提升效率

场景:常用命令太长,想用简写。

bash
git config --global alias.st statusgit config --global alias.co checkoutgit config --global alias.br branchgit config --global alias.ci commitgit config --global alias.lg "log --graph --oneline --all"# 之后可用 git lg 查看漂亮的提交树

二、仓库初始化

1. 把本地目录变成 Git 仓库

场景:本地已有一个项目文件夹,想开始用 Git 管理。

bash
cd your-projectgit initgit add .git commit -m "init: 初始化项目"

2. 克隆远程仓库

场景:加入新团队,需要把远程代码拉到本地。

bash
# HTTPS 方式(简单,适合新人)git clone https://github.com/user/repo.git# SSH 方式(免密,推荐长期使用)git clone git@github.com:user/repo.git# 克隆到指定目录git clone git@github.com:user/repo.git my-folder# 只克隆最近一次提交(大仓库加速)git clone --depth 1 git@github.com:user/repo.git

3. 关联本地仓库到远程

场景:本地已有 Git 仓库,想推到 GitHub/GitLab 新建的空仓库。

bash
git remote add origin git@github.com:user/repo.gitgit branch -M maingit push -u origin main

三、日常开发四件套

场景:每天写代码最常用的循环——改文件 → 查看状态 → 暂存 → 提交。

1. 查看状态

bash
git status              # 查看哪些文件改了git status -s           # 简短模式git diff                # 查看未暂存的具体改动git diff --staged       # 查看已暂存但未提交的改动git diff HEAD           # 查看所有未提交的改动

2. 暂存文件

bash
git add index.html              # 暂存单个文件git add src/                    # 暂存整个目录git add .                       # 暂存所有改动(含新增)git add -u                      # 只暂存已跟踪文件的修改(不含新文件)git add -p                      # 交互式选择部分改动暂存(同一文件可拆分提交)

关键场景:git add -p 适合把一个大改动拆成多个语义清晰的提交,比如同时修了 bug 和加了功能,应该分两次提交。

3. 提交

bash
git commit -m "feat: 新增用户登录功能"git commit -m "标题" -m "详细描述"   # 标题 + 正文git commit --amend                  # 修改最近一次提交(未 push 时用)git commit --amend --no-edit        # 把新改动并入上次提交,不改 message

4. 推送

bash
git push                           # 推到默认远程的默认分支git push origin main               # 明确指定git push -u origin feature/login   # 首次推送新分支并建立跟踪git push --force-with-lease         # 安全的强推(见下方说明)

警告:不要对公共分支(main/develop)使用 git push --force,会覆盖他人提交。用 --force-with-lease 更安全,它会在远程有新提交时拒绝推送。


四、提交信息规范

场景:团队协作时,规范的 commit message 让历史可读、可自动生成 changelog。

推荐使用 Conventional Commits:

前缀 含义 示例
feat 新功能 feat: 新增微信支付
fix Bug 修复 fix: 修复登录超时问题
docs 文档变更 docs: 更新 README
style 代码格式(不影响逻辑) style: 统一缩进
refactor 重构(非新功能非修 bug) refactor: 抽离用户服务
perf 性能优化 perf: 列表接口加索引
test 测试相关 test: 补充订单单测
chore 构建/工具/依赖 chore: 升级 Vue 到 3.4
build 构建系统或外部依赖 build: 修改 webpack 配置
ci CI 配置 ci: 添加 GitHub Actions

格式:

code
<type>(<scope>): <subject><body><footer>

示例:

文本
feat(order): 新增订单导出功能- 支持 Excel 与 CSV 两种格式- 后端走异步任务,避免超时- 关联需求 #1234

五、分支管理

1. 查看/创建/切换分支

bash
git branch                     # 查看本地分支git branch -a                  # 查看所有分支(含远程)git branch -vv                 # 查看分支跟踪关系git branch feature/login       # 创建分支但不切换git switch feature/login       # 切换分支(新命令,推荐)git checkout feature/login     # 切换分支(老命令)git switch -c feature/login    # 创建并切换git checkout -b feature/login  # 创建并切换(老写法)

2. 基于远程分支创建本地分支

场景:同事在远程建了 feature/pay,你想本地拉下来接着开发。

bash
git fetch origingit switch feature/pay         # 自动跟踪同名远程分支

3. 重命名分支

bash
git branch -m new-name         # 重命名当前分支git branch -m old-name new-name # 重命名指定分支# 已推送的分支重命名后,需要删除远程旧分支再推新分支git push origin :old-namegit push -u origin new-name

4. 删除分支

bash
git branch -d feature/login        # 安全删除(未合并会提醒)git branch -D feature/login        # 强制删除git push origin --delete feature/login  # 删除远程分支

5. 分支命名建议

前缀 场景 示例
feature/ 新功能 feature/user-export
fix/ Bug 修复 fix/login-timeout
hotfix/ 紧急线上修复 hotfix/payment-crash
refactor/ 重构 refactor/order-service
chore/ 杂项工程任务 chore/upgrade-vue
release/ 发布准备 release/v2.3.0

六、合并与变基

1. merge(保留分支历史)

场景:把 feature 分支合到 main,想保留"曾经有这个分支"的痕迹。

bash
git switch maingit merge feature/login

2. rebase(线性历史)

场景:feature 分支开发期间 main 又有新提交,想让我的提交"接"到最新 main 之后,历史更干净。

bash
git switch feature/logingit rebase main# 如有冲突:解决后 git add,再 git rebase --continue

3. merge vs rebase 怎么选

维度 merge rebase
历史 保留分支拓扑 线性
冲突 一次解决 可能多次解决
安全性 不改写历史,公共分支安全 改写历史,公共分支危险
推荐场景 合并 feature 到 main 同步 main 最新代码到 feature

铁律:永远不要对已推送的公共分支执行 rebase。

4. squash merge(压缩合并)

场景:feature 分支有 20 个零碎提交,合并到 main 时只想留 1 条干净的记录。

bash
git switch maingit merge --squash feature/logingit commit -m "feat: 新增登录功能"

5. cherry-pick(摘樱桃)

场景:某个 bug 修复提交在 feature 分支,但 main 也急需这个修复,不想合并整个分支。

bash
git switch maingit cherry-pick <commit-hash>

6. 取消刚做的合并

bash
git merge --abort              # 合并冲突时放弃合并git reset --hard HEAD~1        # 合并完成后撤销

七、撤销与回退

1. 撤销工作区改动

场景:刚改的代码不想要了,想恢复到上次提交的样子。

bash
git restore index.html         # 新命令,推荐git checkout -- index.html     # 老写法

2. 撤销已暂存的改动

场景:git add 错了,想从暂存区拿出来。

bash
git restore --staged index.htmlgit reset HEAD index.html       # 老写法

3. 修改最近一次提交

场景:刚 commit 完发现 message 写错或有 typo 没改。

bash
# 只改 messagegit commit --amend -m "新的 message"# 把新改动并入上次提交git add .git commit --amend --no-edit

警告:已 push 的提交尽量别 amend,会让其他人冲突。

4. 回退到历史提交

场景:发现最近 3 次提交都有问题,想整体回到 3 次之前。

bash
git reset --soft HEAD~3     # 保留改动在暂存区git reset --mixed HEAD~3    # 保留改动在工作区(默认)git reset --hard HEAD~3     # 完全丢弃改动(危险)
模式 工作区 暂存区 提交历史
--soft 保留 保留 回退
--mixed(默认) 保留 清空 回退
--hard 清空 清空 回退

5. revert(安全回退公共分支)

场景:已经推到远程的提交有问题,不能用 reset,需要"反向提交"撤销。

bash
git revert <commit-hash>          # 撤销单次提交git revert HEAD                   # 撤销最近一次git revert HEAD~2..HEAD           # 撤销最近 3 次提交

区别:reset 是"删除历史",revert 是"新增一次反向提交",公共分支只能用 revert。

6. 紧急处理:误删分支恢复

场景:误删了 feature 分支,想找回来。

bash
git reflog                    # 查看所有 HEAD 移动记录git switch -c feature/recovered <reflog-hash>

git reflog 是 Git 的"后悔药",几乎所有误操作都能从这里找回。


八、远程仓库操作

1. 查看与添加远程

bash
git remote -v                          # 查看远程地址git remote add origin git@...           # 添加远程git remote set-url origin git@...       # 修改远程地址git remote remove origin                # 删除远程

2. 多远程协作

场景:fork 了开源项目,既想同步上游更新,又想推到自己 fork。

bash
git remote add origin git@github.com:你/repo.git      # 自己的 forkgit remote add upstream git@github.com:原作者/repo.git # 上游# 同步上游更新git fetch upstreamgit switch maingit merge upstream/maingit push origin main

3. fetch vs pull

bash
git fetch origin          # 拉取远程更新但不合并(安全)git pull                  # = fetch + merge(可能产生冲突)git pull --rebase         # = fetch + rebase(更干净)

推荐:git pull --rebase 避免无意义的 merge commit。


九、暂存与切换(stash)

1. 临时保存当前改动

场景:正在 feature 分支写代码,老板说 main 有紧急 bug 要先修,但当前代码还不想提交。

bash
git stash                  # 保存当前改动到栈git stash push -m "登录功能写一半"   # 带说明git switch main# ...修 bug、提交、推送 ...git switch feature/logingit stash pop              # 取出最近的 stash 并删除git stash list             # 查看所有 stashgit stash apply stash@{1}  # 取出指定 stash 但不删除git stash drop stash@{0}   # 删除指定 stash

2. 暂存部分文件

bash
git stash push -m "仅暂存配置" -- config.yml

3. 暂存时包含未跟踪文件

bash
git stash -u

十、查看历史

1. 提交日志

bash
git log                                # 完整日志git log --oneline                      # 每行一条git log --oneline --graph --all        # 图形化所有分支git log --author="张三"                 # 按作者过滤git log --since="2 weeks ago"          # 按时间过滤git log -p index.html                  # 查看某文件的修改历史git log -S "loginUser"                 # 查看包含某字符串的提交

2. 查看某次提交的详情

bash
git show <commit-hash>git show HEAD                  # 最近一次git show HEAD~2                # 倒数第三次

3. 查看某一行代码是谁写的

场景:线上出 bug,想知道这行代码谁加的。

bash
git blame index.htmlgit blame -L 50,80 index.html   # 只看 50-80 行

4. 搜索提交

bash
git log --grep="登录"            # 按 message 搜索git log -- source/              # 只看某目录的提交

十一、标签与版本发布

场景:发布 v1.0.0 时,想打个标签方便以后 checkout。

bash
# 轻量标签git tag v1.0.0# 附注标签(推荐,带说明)git tag -a v1.0.0 -m "正式发布版本 1.0.0"# 推送标签到远程git push origin v1.0.0git push origin --tags          # 推送所有标签# 查看标签git taggit show v1.0.0# 删除标签git tag -d v1.0.0                       # 删本地git push origin --delete v1.0.0         # 删远程# checkout 到某个版本git checkout v1.0.0

版本号建议(语义化版本):v<主版本>.<次版本>.<修订号>,如 v2.3.1。


十二、冲突解决

1. 典型冲突场景

合并或 rebase 时,Git 无法自动合并,会提示:

code
CONFLICT (content): Merge conflict in index.html

2. 解决步骤

bash
git status                      # 看哪些文件冲突# 打开文件,手动解决冲突标记# <<<<<<< HEAD# 我的代码# =======# 对方代码# >>>>>>> feature/logingit add index.html              # 解决后标记为已解决git commit                      # merge 时完成合并提交# 或 rebase 时:git rebase --continue

3. 放弃解决

bash
git merge --abort       # 取消 mergegit rebase --abort      # 取消 rebase

4. 减少冲突的策略

  • 频繁同步 main:git pull --rebase origin main
  • 拆分大 feature 为多个小 PR
  • 团队约定文件责任人,减少多人同改
  • 大改动用特性开关(feature flag)隔离

十三、典型工作流场景

场景 1:从零开发一个新功能

bash
# 1. 同步最新主分支git switch maingit pull --rebase origin main# 2. 创建功能分支git switch -c feature/user-export# 3. 开发过程中频繁小提交git add .git commit -m "feat: 导出按钮 UI"# 4. 中途同步 main 更新git fetch origingit rebase origin/main# 5. 推送到远程git push -u origin feature/user-export# 6. 在 GitLab/GitHub 提 Merge Request / Pull Request# 7. Code Review 通过后合并到 main,删除功能分支

场景 2:修复线上紧急 Bug

bash
# 1. 从 main 拉出 hotfix 分支git switch maingit pullgit switch -c hotfix/payment-crash# 2. 修复并测试git commit -m "fix: 修复支付回调崩溃"# 3. 合并到 main 并打标签git switch maingit merge --no-ff hotfix/payment-crashgit tag -a v1.2.1 -m "修复支付崩溃"# 4. 推送git push origin main --tags# 5. 如果有 develop 分支,也要同步git switch developgit merge hotfix/payment-crash# 6. 清理git branch -d hotfix/payment-crashgit push origin --delete hotfix/payment-crash

场景 3:多人协作同分支

bash
# 拉取同事的提交git pull --rebase origin feature/login# 如有冲突:解决 → git add → git rebase --continue# 推送自己的提交git push origin feature/login# 如果同事在你 pull 后又 push 了,push 会失败git pull --rebase origin feature/logingit push origin feature/login

场景 4:回滚已上线的版本

bash
# 方案 A:用 revert 反向提交(推荐,安全)git switch maingit revert <有问题的 commit hash>git push origin main# 方案 B:回退到指定版本(需强推,慎用)git reset --hard v1.0.0git push --force-with-lease origin main

场景 5:把误提交到 main 的代码移到 feature 分支

bash
# 假设误提交了 2 次git switch -c feature/oops         # 先把这些提交带到新分支git switch maingit reset --hard HEAD~2            # main 回退 2 次git switch feature/oops            # 继续在 feature 上开发

场景 6:只想合并某个文件

bash
# 把 feature 分支的 utils.js 合到 main,不要其他改动git switch maingit checkout feature/xxx -- utils.jsgit commit -m "chore: 同步 utils.js"

十四、子模块与大文件

1. 子模块 submodule

场景:项目依赖另一个独立仓库(如公共组件库)。

bash
# 添加子模块git submodule add git@github.com:team/common-ui.git src/common-ui# 克隆含子模块的项目git clone --recurse-submodules git@github.com:user/repo.git# 已克隆项目后初始化子模块git submodule update --init --recursive# 更新子模块到最新git submodule update --remote

2. 大文件用 LFS

场景:仓库里有视频、模型等大文件,普通 Git 会很慢。

bash
git lfs installgit lfs track "*.psd"git lfs track "*.mp4"git add .gitattributes

十五、二分查找定位 Bug

场景:某个功能本周突然坏了,不知道是哪次提交引入的。

bash
git bisect startgit bisect bad                    # 标记当前是坏的git bisect good v1.0.0            # 标记 v1.0.0 是好的# Git 自动 checkout 中间提交,你测试后:git bisect good   # 或 git bisect bad# 重复几次,Git 会定位到具体哪次提交引入的 buggit bisect reset                  # 结束

十六、常用命令速查表

场景 命令
查看状态 git status
查看改动 git diff
暂存全部 git add .
暂存部分 git add -p
提交 git commit -m "msg"
修改上次提交 git commit --amend
推送 git push
拉取并 rebase git pull --rebase
新建并切换分支 git switch -c name
合并分支 git merge name
变基 git rebase main
撤销工作区改动 git restore file
取消暂存 git restore --staged file
回退提交(安全) git revert <hash>
回退历史(慎用) git reset --hard HEAD~3
暂存工作 git stash
恢复暂存 git stash pop
查看历史 git log --oneline --graph --all
查看作者 git blame file
后悔药 git reflog
找回误删分支 git switch -c name <reflog-hash>
打标签 git tag -a v1.0 -m "msg"
摘单次提交 git cherry-pick <hash>
二分查 bug git bisect start

十七、常见问题 FAQ

Q1:push 被拒绝,提示 "non-fast-forward"

远程有你本地没有的提交。先 git pull --rebase origin main,解决冲突后再 push。

Q2:commit message 写错了,已 push

bash
git commit --amend -m "正确的 message"git push --force-with-lease origin feature/xxx

仅限自己独占的分支,公共分支不要这样改。

Q3:误执行了 git reset --hard,代码没了

bash
git reflog              # 找到误操作前的 hashgit reset --hard <hash>

Q4:想把某次提交拆成两次

bash
git rebase -i HEAD~3    # 交互式 rebase# 把要拆的提交标记为 edit# Git 停在该提交后:git reset HEAD~git add -p              # 分批暂存git commit -m "第一部分"git add .git commit -m "第二部分"git rebase --continue

Q5:clone 太慢怎么办

bash
# 浅克隆git clone --depth 1 <url># 只克隆最近 N 次提交git clone --depth 10 <url># 只克隆指定分支git clone --branch main --single-branch <url>

Q6:如何让 Git 忽略某些文件

在仓库根目录创建 .gitignore:

code
node_modules/*.log.envdist/.vscode/*.local

已被跟踪的文件加入 .gitignore 后,还需 git rm --cached <file> 取消跟踪。

Q7:如何查看某个文件的历史版本

bash
git log --oneline -- path/to/filegit show <commit-hash>:path/to/file    # 查看历史版本内容

Q8:merge 之后想撤销

bash
git reset --hard ORIG_HEAD    # 回到 merge 之前

十八、推荐工作流模型

1. GitHub Flow(简单,适合小团队)

code
main(永远可部署) └── feature/xxx → PR → review → merge

规则:main 永远可部署,所有改动通过 PR 合并。

2. Git Flow(规范,适合版本发布)

文本
main        ← 只放发布版本develop     ← 日常集成分支feature/*   ← 功能分支,合到 developrelease/*   ← 发布准备分支hotfix/*    ← 紧急修复,合到 main 和 develop

3. Trunk-Based(主干开发,适合高频发布)

所有人直接往 main 提交(或短命 feature 分支),配合特性开关与持续集成。大厂主流模式。


总结

Git 是开发者最趁手的工具,也是最容易踩坑的地方。掌握核心原则:

  1. 小步提交:每次 commit 只做一件事,方便回溯与 review。
  2. 分支隔离:永远不要在 main 上直接开发。
  3. 公共分支不用 reset/amend:用 revert 安全回退。
  4. 勤同步:每天开始工作前 git pull --rebase。
  5. reflog 是后悔药:误操作第一时间看 reflog。
  6. 提交信息要可读:用规范前缀,团队历史才可追溯。

Git 不在于背多少命令,而在于理解每个操作改写了什么:工作区、暂存区、本地仓库,还是远程仓库。理清这四层,所有命令都有迹可循。


附:推荐资源

前端、后端、部署、客服都是我一个人。写这里的东西都是真踩过的坑,不是抄来的教程。