文章目录
-
- 前言
- [Git 提交规范速记](#Git 提交规范速记)
-
- [🔥 天天用](#🔥 天天用)
- [📝 经常用](#📝 经常用)
- [⚡ 偶尔用](#⚡ 偶尔用)
- [🔧 配置/安全用](#🔧 配置/安全用)
- 一、基础配置篇
-
- [1.1 用户信息配置](#1.1 用户信息配置)
- [1.2 常用配置优化](#1.2 常用配置优化)
- 二、仓库管理篇
-
- [2.1 创建与克隆仓库](#2.1 创建与克隆仓库)
- [2.2 远程仓库管理](#2.2 远程仓库管理)
- [三、Git 核心原理](#三、Git 核心原理)
-
- [3.1 三区模型](#3.1 三区模型)
- [3.2 Git 对象模型:为什么 Git 这么快?](#3.2 Git 对象模型:为什么 Git 这么快?)
- 四、日常开发工作流
-
- [4.1 文件状态管理](#4.1 文件状态管理)
- [4.2 提交代码](#4.2 提交代码)
- [4.3 分支管理](#4.3 分支管理)
- 五、代码合并与同步
-
- [5.1 合并操作](#5.1 合并操作)
- [5.2 变基操作](#5.2 变基操作)
- [5.3 代码同步](#5.3 代码同步)
- [六、Git 冲突解决实战案例](#六、Git 冲突解决实战案例)
-
- [案例一:merge 冲突(新人必看)](#案例一:merge 冲突(新人必看))
- [案例二:rebase 冲突(进阶)](#案例二:rebase 冲突(进阶))
- [七、reset 完全解析:Git 最难知识点](#七、reset 完全解析:Git 最难知识点)
-
- [reset 三种模式对照表](#reset 三种模式对照表)
- [图解 reset 影响范围](#图解 reset 影响范围)
- 实战示例
- [八、stash 实战:打工人的必备技能](#八、stash 实战:打工人的必备技能)
-
- [核心场景:开发到一半被叫去修线上 Bug](#核心场景:开发到一半被叫去修线上 Bug)
- [stash 进阶技巧](#stash 进阶技巧)
- [九、cherry-pick 实战:精准移植提交](#九、cherry-pick 实战:精准移植提交)
-
- 核心场景:只上线某个修复,不带其他功能
- [cherry-pick 进阶用法](#cherry-pick 进阶用法)
- 十、危险命令警告(必读)
-
- [🔴🔴🔴🔴🔴 极高危险](#🔴🔴🔴🔴🔴 极高危险)
-
- [1. `git reset --hard`](#1.
git reset --hard) - [2. `git clean -fdx`](#2.
git clean -fdx) - [3. `git push --force`(无保护版本)](#3.
git push --force(无保护版本))
- [1. `git reset --hard`](#1.
- [🔴🔴🔴 高度危险](#🔴🔴🔴 高度危险)
-
- [4. `git reset --hard` + `git push --force` 组合](#4.
git reset --hard+git push --force组合) - [5. 对公共分支执行 `git rebase`](#5. 对公共分支执行
git rebase)
- [4. `git reset --hard` + `git push --force` 组合](#4.
- [十一、Git 时光机:reflog 救命指南](#十一、Git 时光机:reflog 救命指南)
-
- [为什么 reflog 比 log 更重要?](#为什么 reflog 比 log 更重要?)
- 核心原理
- 实战场景一:救回误删的分支
- [实战场景二:撤销错误的 reset --hard](#实战场景二:撤销错误的 reset --hard)
- [实战场景三:恢复搞砸的 rebase](#实战场景三:恢复搞砸的 rebase)
- 黄金法则
- 十二、历史记录与回退
-
- [12.1 查看历史](#12.1 查看历史)
- [12.2 代码回退](#12.2 代码回退)
- 十三、储藏与清理
-
- [13.1 储藏操作](#13.1 储藏操作)
- [13.2 清理工作区](#13.2 清理工作区)
- 十四、标签管理
- 十五、高级技巧
-
- [15.1 樱桃摘取(Cherry-pick)](#15.1 樱桃摘取(Cherry-pick))
- [15.2 二分查找(Bisect)](#15.2 二分查找(Bisect))
- [15.3 子模块管理](#15.3 子模块管理)
- [15.4 历史清理:从 filter-branch 到 filter-repo](#15.4 历史清理:从 filter-branch 到 filter-repo)
- [十六、企业级 PR 工作流](#十六、企业级 PR 工作流)
-
- [PR 最佳实践](#PR 最佳实践)
- [十七、Android 开发专属配置](#十七、Android 开发专属配置)
-
- [推荐 .gitignore 文件](#推荐 .gitignore 文件)
- 常见问题处理
- 十八、团队协作规范
-
- [推荐分支模型(简化版 Git Flow)](#推荐分支模型(简化版 Git Flow))
- [提交信息规范(Conventional Commits)](#提交信息规范(Conventional Commits))
- [十九、Git 面试高频题](#十九、Git 面试高频题)
-
- [1. merge 和 rebase 的区别?](#1. merge 和 rebase 的区别?)
- [2. git fetch 和 git pull 的区别?](#2. git fetch 和 git pull 的区别?)
- [3. revert 和 reset 的区别?](#3. revert 和 reset 的区别?)
- [4. reset、revert、restore、checkout 的区别(高频!)](#4. reset、revert、restore、checkout 的区别(高频!))
- [5. Git Flow 分支策略是什么?](#5. Git Flow 分支策略是什么?)
- [6. 如何恢复误删的提交或分支?](#6. 如何恢复误删的提交或分支?)
- [7. Git 对象模型是什么?(进阶)](#7. Git 对象模型是什么?(进阶))
- 二十、快速参考卡片
-
- [🆘 救命命令 TOP 5](#🆘 救命命令 TOP 5)
- [📋 日常高频命令速查](#📋 日常高频命令速查)
- [🔄 reset 模式速查](#🔄 reset 模式速查)
- 结语
- 相关推荐
前言
Git 作为现代软件开发中不可或缺的版本控制工具,掌握其命令行操作是每个开发者的必修课。虽然图形化工具层出不穷,但命令行依然是最高效、最灵活的 Git 操作方式。
本文将带你从基础命令出发,深入 Git 的底层原理,掌握危险操作的避坑技巧,了解真实开发场景的最佳实践,并覆盖面试高频考点。

Git 提交规范速记
🔥 天天用
| 图标 | type | 说明 | 示例 |
|---|---|---|---|
| ✨ | feat |
新功能 | feat(login): add fingerprint auth |
| 🐛 | fix |
修Bug/安全漏洞 | fix(security): patch XSS vulnerability |
📝 经常用
| 图标 | type | 说明 | 示例 |
|---|---|---|---|
| 📝 | docs |
文档修改 | docs(readme): add setup guide |
| 🎨 | style |
代码格式 | style: format code with spotless |
| ♻️ | refactor |
重构 | refactor(user): extract validator |
⚡ 偶尔用
| 图标 | type | 说明 | 示例 |
|---|---|---|---|
| ⚡ | perf |
性能优化 | perf(list): add RecyclerView cache |
| ✅ | test |
测试 | test(payment): add unit tests |
🔧 配置/安全用
| 图标 | type | 说明 | 示例 |
|---|---|---|---|
| 📦 | build |
构建/安全升级 | build(deps): upgrade okhttp for CVE |
| 👷 | ci |
CI/CD/安全扫描 | ci: add security scan to pipeline |
| 🔧 | chore |
杂项/合规配置 | chore: update privacy policy |
| ⏪ | revert |
回退 | revert: revert feat(payment) abc123 |
💡 记忆口诀:feat/fix 天天用,docs/style/refactor 经常用,perf/test 偶尔用,build/ci/chore 配置用
🛡️ 安全合规:修漏洞用 fix,加防护用 feat,升级依赖用 build,合规配置用 chore
一、基础配置篇
1.1 用户信息配置
bash
# 设置全局用户名和邮箱
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
# 为特定项目设置不同的用户名和邮箱(在项目目录下执行)
git config user.name "Project Specific Name"
git config user.email "project@example.com"
# 查看配置信息
git config --list
git config user.name
1.2 常用配置优化
bash
# 设置命令别名
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --all"
# 设置默认编辑器
git config --global core.editor "code --wait"
# 设置换行符处理(Windows)
git config --global core.autocrlf true
# 开启颜色显示
git config --global color.ui true
二、仓库管理篇
2.1 创建与克隆仓库
bash
# 初始化新仓库
git init
git init my-project # 在指定目录初始化
# 克隆远程仓库
git clone https://github.com/user/repo.git
git clone https://github.com/user/repo.git my-directory # 克隆到指定目录
git clone -b branch-name https://github.com/user/repo.git # 克隆特定分支
2.2 远程仓库管理
bash
# 查看远程仓库
git remote -v
# 添加远程仓库
git remote add origin https://github.com/user/repo.git
git remote add upstream https://github.com/original/repo.git
# 修改远程仓库地址
git remote set-url origin https://new-url.com/repo.git
# 删除远程仓库
git remote remove origin
# 查看远程仓库详细信息
git remote show origin
三、Git 核心原理
3.1 三区模型
很多开发者会背命令,但不知道命令到底影响哪里。理解 Git 的三区模型,是真正掌握 Git 的第一步。
text
工作区(Working Tree)
│
│ git add
▼
暂存区(Index / Stage)
│
│ git commit
▼
本地仓库(Local Repository)
│
│ git push
▼
远程仓库(Remote Repository)
| 区域 | 说明 | 对应命令 |
|---|---|---|
| Working Tree | 正在修改的代码,文件系统上的实际文件 | git restore、git checkout -- |
| Stage (Index) | 准备提交的代码快照 | git add、git reset HEAD |
| Local Repo | 本地提交历史,.git 目录中的对象数据库 |
git commit、git reset --soft |
| Remote Repo | GitHub/GitLab 等远程仓库 | git push、git fetch |
3.2 Git 对象模型:为什么 Git 这么快?
Git 本质不是保存文件的差异,而是保存快照(Snapshot)。Git 内部有四种核心对象:
text
┌────────────────────────────────────────┐
│ Git 对象模型 │
├────────────────────────────────────────┤
│ │
│ Blob → 文件内容 │
│ Tree → 目录结构 │
│ Commit → 一次提交快照 │
│ Tag → 版本标记 │
│ │
└────────────────────────────────────────┘
用命令直观感受:
bash
# 查看最近一次提交的内部对象
git cat-file -p HEAD
# 输出示例:
# tree a1b2c3d4e5f6... ← 指向一个 Tree 对象
# parent 7890abcdef... ← 指向上一个 Commit
# author Scc <tom@example.com> 1718123456 +0800
# committer Scc <tom@example.com> 1718123456 +0800
#
# feat: add login feature
# 查看这个 Tree 对象
git cat-file -p a1b2c3d4e5f6
# 输出示例:
# 100644 blob 1a2b3c4d... User.java
# 100644 blob 5e6f7g8h... LoginActivity.java
# 040000 tree 9i0j1k2l... utils/
# 查看具体的 Blob(文件内容)
git cat-file -p 1a2b3c4d
关键理解:
text
Blob:只存文件内容,不存文件名
Tree:存目录结构和文件名,指向 Blob 或其他 Tree
Commit:指向一个 Tree,包含作者、时间、提交信息等元数据
这三个对象组合起来,就构成了 Git 的版本快照系统。
这就是为什么 checkout、reset、rebase 几乎都是秒级完成------它们只是在操作指向这些对象的指针,而不是复制文件。
这是区分"会用 Git"和"懂 Git"的关键。
四、日常开发工作流
4.1 文件状态管理
bash
# 查看工作区状态
git status
git status -s # 简短格式
# 将文件添加到暂存区
git add file.txt
git add . # 添加所有文件
git add -p # 交互式添加,可以选择部分修改
git add -u # 只添加已跟踪文件的修改
# 从暂存区移除文件
git reset HEAD file.txt
git restore --staged file.txt # Git 2.23+ 推荐用法
# 撤销工作区修改
git checkout -- file.txt
git restore file.txt # Git 2.23+ 推荐用法
4.2 提交代码
bash
# 基本提交
git commit -m "feat: add new login feature"
# 提交所有已跟踪文件的修改(跳过 git add)
git commit -a -m "fix: resolve login bug"
# 修改最后一次提交
git commit --amend # 修改提交信息
git commit --amend --no-edit # 追加文件但不改变提交信息
# 提交规范示例(推荐使用 Conventional Commits)
git commit -m "feat: 添加用户登录功能
- 实现JWT认证
- 添加登录接口
- 前端登录页面
Closes #123"
4.3 分支管理
bash
# 查看分支
git branch # 本地分支
git branch -r # 远程分支
git branch -a # 所有分支
git branch -v # 查看分支最后一次提交
# 创建分支
git branch feature-login
git branch feature-login <commit-hash> # 基于指定提交创建
# 切换分支
git checkout feature-login
git switch feature-login # Git 2.23+ 推荐用法
# 创建并切换分支
git checkout -b feature-register
git switch -c feature-register # Git 2.23+ 推荐
# 删除分支
git branch -d feature-login # 安全删除(已合并的分支)
git branch -D feature-login # 强制删除
# 重命名分支
git branch -m old-name new-name
五、代码合并与同步
5.1 合并操作
bash
# 普通合并
git merge feature-branch
# 合并但不自动提交(方便检查)
git merge --no-commit feature-branch
git merge --no-ff feature-branch # 禁用快进合并,保留分支痕迹
# 压缩合并(将多个提交合并为一个)
git merge --squash feature-branch
# 中止合并
git merge --abort
5.2 变基操作
bash
# 基本变基
git rebase main
# 交互式变基(合并提交、修改提交信息等)
git rebase -i HEAD~3 # 处理最近3个提交
git rebase -i <commit-hash>
# 在交互式变基中可用的命令
# pick: 使用该提交
# reword: 使用但修改提交信息
# squash: 合并到上一个提交
# fixup: 合并但丢弃提交信息
# drop: 删除该提交
# 解决冲突后继续变基
git rebase --continue
# 跳过当前提交
git rebase --skip
# 中止变基
git rebase --abort
5.3 代码同步
bash
# 拉取远程代码
git pull # 等于 git fetch + git merge
git pull --rebase # 等于 git fetch + git rebase(推荐,历史更清晰)
# 推送代码
git push origin main
git push -u origin feature-branch # 设置上游分支
git push --force-with-lease # 安全的强制推送
# 只获取不合并
git fetch origin
git fetch --all # 获取所有远程仓库
git fetch --prune # 获取并清理已删除的远程分支
六、Git 冲突解决实战案例
案例一:merge 冲突(新人必看)
场景: 两个人修改了同一文件的同一行。
main 分支:
java
public class User {
private String name = "Tom";
}
feature 分支:
java
public class User {
private String name = "Jerry";
}
执行合并:
bash
git merge feature
冲突标记解读:
java
public class User {
<<<<<<< HEAD
private String name = "Tom";
=======
private String name = "Jerry";
>>>>>>> feature
}
text
<<<<<<< HEAD
当前分支的代码(你的修改)
=======
待合并分支的代码(别人的修改)
>>>>>>> feature
解决方案(根据业务需求选择):
java
// 方案一:保留两者(通常需要手动处理)
private String name = "Tom Jerry";
// 方案二:采用新值
private String name = "Jerry";
// 方案三:保留原值
private String name = "Tom";
完成合并:
bash
git add User.java
git commit -m "merge: resolve name conflict"
案例二:rebase 冲突(进阶)
场景: 你的 feature 分支需要更新到最新的 main。
bash
git checkout feature
git rebase main
冲突时:
bash
# 解决冲突后
git add .
git rebase --continue
# 如果某个提交不需要了
git rebase --skip
# 完全放弃 rebase
git rebase --abort
⚠️ 重要提示: rebase 过程中每次冲突解决后,都是对"单个提交"的修改,这与 merge 一次性解决所有冲突完全不同。
七、reset 完全解析:Git 最难知识点
git reset 是 Git 中最强大也最容易出错的命令。理解它的关键在于:同一个命令可以影响三个不同区域。
reset 三种模式对照表
| 命令 | 工作区 (Working Tree) | 暂存区 (Stage) | 提交历史 (Commit) | 使用场景 |
|---|---|---|---|---|
reset --soft |
✅ 保留 | ✅ 保留 | ⬅️ 回退 | 重新组织提交 |
reset --mixed (默认) |
✅ 保留 | ❌ 清空 | ⬅️ 回退 | 撤销 add 和 commit |
reset --hard |
❌ 删除 | ❌ 删除 | ⬅️ 回退 | 完全放弃修改 |
图解 reset 影响范围
text
HEAD (指针)
↓
│
▼
Commit ◄── reset --soft 停在这里
│
│ ◄── reset --mixed 停在这里
▼
Stage
│
│ ◄── reset --hard 停在这里
▼
Working Tree
实战示例
bash
# 场景:刚刚提交了三个 commit,但想把它们合并成一个
# 1. 先 soft reset 回到三个 commit 之前
git reset --soft HEAD~3
# 2. 此时:
# - 工作区的修改全部保留
# - 暂存区保留了三个 commit 的所有修改
# - 提交历史回退了三个 commit
# 3. 重新提交为一个 commit
git commit -m "feat: complete user module (squashed)"
# 场景:撤销 git add 操作
git reset HEAD file.txt
# 或 Git 2.23+
git restore --staged file.txt
⚠️ 警告:
reset --hard会永久删除未提交的工作区修改。执行前务必确认或先用git stash备份。
八、stash 实战:打工人的必备技能
核心场景:开发到一半被叫去修线上 Bug
这是每个开发者都会遇到的情况:
text
上午 10:30
你正在开发支付功能,完成了约 60%
代码还没到可以提交的程度
突然:
老板:「线上 Crash 了!紧急修复!」
你:「可是我这边代码还没写完...」
老板:「现在就要!」
正确操作流程:
bash
# 1. 保存当前工作进度
git stash push -m "WIP: payment module 60%"
# 查看 stash 列表确认
git stash list
# stash@{0}: On feature/payment: WIP: payment module 60%
# 2. 切换到修复分支
git checkout main
git checkout -b hotfix/crash-fix
# 3. 修复 Bug、提交、推送
git add .
git commit -m "fix: resolve null pointer crash in login"
git push -u origin hotfix/crash-fix
# 4. 切回开发分支
git checkout feature/payment
# 5. 恢复之前的开发进度
git stash pop
恢复后你会看到:
text
所有未提交的修改完美恢复
就像从未离开过一样
stash 进阶技巧
bash
# 只 stash 部分文件
git stash push -m "only utils" src/utils/Helper.java
# 从 stash 创建新分支(很实用)
git stash branch feature/stashed-work stash@{0}
# 查看 stash 的具体内容
git stash show -p stash@{0}
# 应用但不删除 stash
git stash apply stash@{0}
💡 核心价值: stash 不是"高级功能",而是每个打工人必备的日常生存技能。它能让你在多个紧急任务之间自由切换,而不会丢失任何工作进度。
九、cherry-pick 实战:精准移植提交
核心场景:只上线某个修复,不带其他功能
这是大厂高频使用场景:
text
你的分支结构:
main (线上 v2.0)
│
├── commit: 支付功能 A ← 还在测试,不能上线
├── commit: 支付功能 B ← 还在测试,不能上线
└── commit: 修复支付金额计算错误 ← 需要紧急上线!
如果用 git merge:
bash
# ❌ 错误做法
git checkout main
git merge feature/payment
# 结果:把未测试的功能 A、B 也带进线上了!
正确做法 ------ 使用 cherry-pick:
bash
# ✅ 只挑取修复提交
git checkout main
git cherry-pick abc123 # 只取修复金额计算的 commit
# 推送上线
git push origin main
cherry-pick 进阶用法
bash
# 挑取多个不连续的提交
git cherry-pick abc123 def456
# 挑取连续的提交范围(不包含 start-commit)
git cherry-pick start-commit..end-commit
# 挑取连续的提交范围(包含 start-commit)
git cherry-pick start-commit^..end-commit
# 只应用修改但不自动提交(方便检查)
git cherry-pick --no-commit abc123
# 解决冲突后继续
git cherry-pick --continue
git cherry-pick --abort # 放弃
💡 核心价值:
cherry-pick让你能像外科手术一样精准地移植提交,是处理紧急修复和跨分支代码同步的利器。
十、危险命令警告(必读)
以下命令可能导致代码永久丢失,使用前务必理解其影响。
🔴🔴🔴🔴🔴 极高危险
1. git reset --hard
bash
git reset --hard HEAD~1
影响范围:
text
❌ 删除最近一次提交
❌ 清空暂存区所有内容
❌ 删除工作区所有未提交修改
救命方案(立即执行):
bash
# 不要慌,立即查看引用日志
git reflog
# 找到 reset 前的 HEAD 位置,例如 HEAD@{1}
git reset --hard HEAD@{1}
⚠️ 黄金原则:执行
reset --hard前,先用git stash备份当前工作区!
2. git clean -fdx
bash
git clean -fdx
影响范围:
text
❌ 删除所有未跟踪文件
❌ 删除所有未跟踪目录
❌ 删除 .gitignore 中被忽略的文件(如 local.properties、签名文件)
安全做法:
bash
# 永远先预览!
git clean -n # 预览将要删除的文件
git clean -nd # 同时预览目录
git clean -ndx # 预览包括被 gitignore 忽略的文件
# 确认无误后,逐步执行
git clean -fd # 删除文件和目录
3. git push --force(无保护版本)
bash
# ❌ 危险写法,绝对避免
git push --force origin main
# ✅ 安全写法,应该使用
git push --force-with-lease origin main
两者的关键区别:
text
git push --force:
直接覆盖远程分支,不管别人有没有推送新代码
可能把同事的提交直接干掉
git push --force-with-lease:
只在远程分支和你本地记录一致时才允许推送
如果有人在你之后推送了代码,命令会拒绝执行
相当于加了"安全检查"的强制推送
🔴🔴🔴 高度危险
4. git reset --hard + git push --force 组合
bash
# 组合拳,杀伤力翻倍
git reset --hard HEAD~5
git push --force origin main
5. 对公共分支执行 git rebase
bash
# ❌ 大忌!永远不要这样做
git checkout main
git rebase develop
git push --force
十一、Git 时光机:reflog 救命指南
为什么 reflog 比 log 更重要?
git log 只能看到当前分支的提交历史,而 git reflog 记录了所有 HEAD 的移动记录,包括:
- 被删除的分支
- 被 reset 掉的提交
- 错误的 rebase 操作
- cherry-pick 记录
核心原理
text
Git 不会立即删除任何对象
只要能在 reflog 中找到,就能恢复
默认保留 90 天(可配置 gc.reflogExpire)
实战场景一:救回误删的分支
bash
# 不小心删除了包含重要功能的 feature-important 分支
git branch -D feature-important
# 查找该分支的最后提交
git reflog --all | grep feature-important
# 输出示例:
# a1b2c3d HEAD@{5}: checkout: moving from feature-important to main
# 恢复分支
git checkout -b feature-important a1b2c3d
实战场景二:撤销错误的 reset --hard
bash
# 发现 reset 错了,多回了 10 个提交
git reset --hard HEAD~10
# 立即查看 reflog
git reflog
# 输出示例:
# e5f6g7h HEAD@{0}: reset: moving to HEAD~10
# i8j9k0l HEAD@{1}: commit: 完成支付模块开发 ← 想回到这里
# 时光倒流
git reset --hard HEAD@{1}
# 或使用具体 hash
git reset --hard i8j9k0l
实战场景三:恢复搞砸的 rebase
bash
# rebase 过程中把事情搞复杂了,想回到 rebase 之前
git reflog
# 找到 rebase 启动前的 HEAD
# m1n2o3p HEAD@{5}: rebase (start): checkout main
# 回到过去
git reset --hard HEAD@{5}
黄金法则
text
只要你能在 reflog 中找到那个提交的 hash
你的代码就永远没有真正丢失
reflog 是 Git 给你的人生后悔药
十二、历史记录与回退
12.1 查看历史
bash
# 基本日志查看
git log
git log --oneline # 简洁格式
git log --graph --all --decorate # 图形化显示分支结构
git log -p # 显示详细差异
git log --stat # 显示文件修改统计
# 高级日志搜索
git log --author="John" # 按作者搜索
git log --grep="login" # 按提交信息搜索
git log -S "function_name" # 按代码内容搜索(强大!)
git log --since="2024-01-01" --until="2024-01-31"
# 查看某文件的历史
git log --follow -p file.txt # 跟踪文件重命名历史
# 查看引用日志(真正的时光机)
git reflog
12.2 代码回退
bash
# 撤销提交(保留修改)
git reset --soft HEAD~1 # 撤销提交,修改回到暂存区
git reset --mixed HEAD~1 # 撤销提交和暂存,修改在工作区(默认行为)
git reset --hard HEAD~1 # 完全撤销,丢弃所有修改(⚠️ 危险)
# 撤销到指定提交
git reset --hard <commit-hash>
# 创建新提交来撤销之前的修改(团队推荐方式)
git revert HEAD
git revert <commit-hash>
git revert -m 1 <merge-commit> # 撤销合并提交
# 恢复误删的文件
git checkout <commit-hash> -- file.txt
git restore --source=<commit-hash> file.txt
十三、储藏与清理
13.1 储藏操作
bash
# 储藏当前修改
git stash
git stash save "WIP: 正在进行用户模块开发"
# 查看储藏列表
git stash list
# 恢复储藏
git stash pop # 恢复并删除储藏
git stash apply # 恢复但不删除
git stash apply stash@{2} # 恢复指定的储藏
# 删除储藏
git stash drop stash@{0}
git stash clear # 删除所有储藏
# 储藏部分文件
git stash push -m "partial stash" file1.txt file2.txt
# 从储藏创建分支(很实用的功能)
git stash branch new-branch stash@{0}
13.2 清理工作区
bash
# ⚠️ 清理未跟踪文件(注意安全)
git clean -n # 第一步:预览将要删除的文件
git clean -f # 第二步:删除未跟踪文件
git clean -fd # 同时删除未跟踪的目录
# 忽略文件配置
# 创建 .gitignore 文件
echo "node_modules/" >> .gitignore
echo "*.log" >> .gitignore
十四、标签管理
bash
# 创建标签
git tag v1.0.0 # 轻量标签
git tag -a v1.0.0 -m "正式版1.0.0 发布" # 附注标签(推荐)
# 查看标签
git tag
git tag -l "v1.*"
git show v1.0.0
# 推送标签
git push origin v1.0.0 # 推送单个标签
git push origin --tags # 推送所有标签
# 删除标签
git tag -d v1.0.0 # 删除本地
git push origin --delete v1.0.0 # 删除远程
# 基于标签创建分支
git checkout -b hotfix-from-v1 v1.0.0
十五、高级技巧
15.1 樱桃摘取(Cherry-pick)
bash
# 应用特定提交到当前分支
git cherry-pick <commit-hash>
git cherry-pick <commit1> <commit2> # 多个提交
git cherry-pick <start-commit>..<end-commit> # 连续提交范围
# 解决冲突后继续
git cherry-pick --continue
git cherry-pick --abort
15.2 二分查找(Bisect)
bash
# 开始二分查找 bug
git bisect start
git bisect bad # 标记当前版本为有问题
git bisect good <commit-hash> # 标记一个确认正常的版本
# Git会自动切换版本供你测试
git bisect good # 如果当前版本测试正常
git bisect bad # 如果当前版本测试有问题
# 找到引入 bug 的提交后,结束查找
git bisect reset
15.3 子模块管理
bash
# 添加子模块
git submodule add https://github.com/user/lib.git libs/lib
# 克隆含子模块的项目
git clone --recursive https://github.com/user/project.git
# 更新子模块
git submodule update --init --recursive
git submodule update --remote
# 删除子模块
git submodule deinit libs/lib
git rm libs/lib
15.4 历史清理:从 filter-branch 到 filter-repo
当你需要从 Git 历史中彻底删除某个文件(如误提交的密钥文件):
bash
# ❌ 旧方案(官方已不推荐)
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch secret.key" \
--prune-empty --tag-name-filter cat -- --all
# ✅ 新方案(官方推荐,速度更快更安全)
# 首先安装 git-filter-repo
# pip install git-filter-repo
# 从历史中删除文件
git filter-repo --path secret.key --invert-paths
# 强制推送到远程(需提前通知团队!)
git push origin --force --all
💡 为什么用
filter-repo?
filter-branch是历史遗留方案,速度慢且容易出错filter-repo是官方推荐方案,速度更快、更安全- 2026 年的文章应该使用现代工具
十六、企业级 PR 工作流
现代企业开发早已不是 git push 就完事,而是完整的 Pull Request 流程:
text
┌─────────────────────────────────────────────────────────┐
│ 企业级 Pull Request 工作流 │
├─────────────────────────────────────────────────────────┤
│ │
│ Developer │
│ │ │
│ │ git checkout -b feature/login │
│ │ git add . && git commit │
│ │ git push -u origin feature/login │
│ ▼ │
│ Pull Request 创建 │
│ │ │
│ ├── 填写 PR 描述 │
│ ├── 关联 Issue │
│ └── 指定 Reviewer │
│ ▼ │
│ Code Review │
│ │ │
│ ├── Reviewer 审查代码 │
│ ├── 提出修改意见 │
│ └── Developer 修改后 force-push │
│ ▼ │
│ CI/CD 检查通过 │
│ │ │
│ ├── 单元测试 │
│ ├── 代码风格检查 │
│ └── 构建检查 │
│ ▼ │
│ Merge to develop / main │
│ │ │
│ └── Squash merge / Rebase merge │
│ │
└─────────────────────────────────────────────────────────┘
PR 最佳实践
bash
# 1. 创建功能分支
git checkout -b feature/user-login develop
# 2. 开发并保持 commit 粒度合理
git commit -m "feat: add login UI"
git commit -m "feat: add login API integration"
git commit -m "test: add login unit tests"
# 3. 推送前先同步 develop 最新代码
git fetch origin
git rebase origin/develop
# 4. 推送并创建 PR
git push -u origin feature/user-login
# 5. Code Review 后如需修改
git add .
git commit -m "fix: address review comments"
# 使用 force-with-lease 更新 PR
git push --force-with-lease
十七、Android 开发专属配置
推荐 .gitignore 文件
gitignore
# Gradle 构建产物
.gradle/
build/
*/build/
# IDE 配置文件
.idea/
*.iml
*.iws
# 本地配置(含敏感信息,绝对不能提交)
local.properties
# 应用签名文件(绝对不能提交到仓库)
*.jks
*.keystore
*.p12
keystore.properties
# 编译产物
*.apk
*.aab
*.ap_
# 测试相关
captures/
*.hprof
# 系统文件
.DS_Store
Thumbs.db
# 依赖目录
node_modules/
# 混淆映射文件(用于崩溃分析,应单独安全备份)
mapping/
常见问题处理
问题一:不小心提交了 local.properties
bash
# 从 Git 中移除但保留本地文件
git rm --cached local.properties
echo "local.properties" >> .gitignore
git add .gitignore
git commit -m "chore: remove local.properties from tracking"
问题二:不小心提交了签名文件(安全事件)
bash
# 这是严重的安全事故,需要立即处理
# 使用现代工具 filter-repo
git filter-repo --path your_keystore.jks --invert-paths
git push origin --force --all
# 立即更换被泄露的签名文件!
十八、团队协作规范
推荐分支模型(简化版 Git Flow)
text
main (线上稳定版本)
│
├── develop (日常开发主线)
│ │
│ ├── feature/login (功能开发)
│ ├── feature/payment
│ │
│ └── release/2.1.0 (发布准备分支)
│
└── hotfix/crash-fix (紧急修复)
| 分支 | 用途 | 命名规范 | 从哪创建 | 合并到哪 |
|---|---|---|---|---|
| main | 线上稳定版本 | main | - | - |
| develop | 日常开发主线 | develop | main | - |
| feature | 功能开发 | feature/功能描述 | develop | develop |
| release | 发布准备 | release/版本号 | develop | main + develop |
| hotfix | 紧急修复 | hotfix/问题描述 | main | main + develop |
提交信息规范(Conventional Commits)
bash
# 推荐的提交信息格式
<type>(<scope>): <subject>
# 类型(type):
feat: 新功能
fix: 修复 bug
docs: 文档修改
style: 代码格式调整(不影响功能)
refactor: 重构(既不是新功能也不是修复)
test: 测试相关
chore: 构建过程或辅助工具变动
# 示例:
git commit -m "feat(user): add JWT authentication"
git commit -m "fix(payment): resolve amount calculation error"
git commit -m "docs(api): update endpoint documentation"
git commit -m "refactor(login): extract validation logic"
十九、Git 面试高频题
1. merge 和 rebase 的区别?
merge(合并):
text
A---B---C (main)
\
D---E (feature)
合并后:
A---B---C-------F (main)
\ /
D-------E
- 保留完整的分支历史
- 会产生一个合并提交
- 适合公共分支
rebase(变基):
text
变基前:
A---B---C (main)
\
D---E (feature)
变基后:
A---B---C---D'---E' (feature)
- 线性历史,更清晰整洁
- 重写了提交 SHA
- 适合个人分支
标准回答:
text
个人开发分支使用 rebase,保持历史整洁。
公共分支(如 main/develop)使用 merge,保留完整记录。
永远不要 rebase 已推送到远程的公共分支。
2. git fetch 和 git pull 的区别?
text
git pull = git fetch + git merge
git fetch: 只下载远程更新到本地,不影响工作区代码
git pull: 下载并自动合并到当前分支
推荐的工作方式:
bash
# 先看看远程有什么更新
git fetch origin
git log origin/main --oneline
# 确认无误后再手动合并
git merge origin/main
3. revert 和 reset 的区别?
| 维度 | reset | revert |
|---|---|---|
| 原理 | 移动 HEAD 指针 | 创建新的反向提交 |
| 历史 | 修改历史 | 保留完整历史 |
| 远程分支 | 需要 force push | 正常 push |
| 团队安全 | ❌ 危险 | ✅ 安全 |
| 使用场景 | 本地修改 | 公共分支 |
标准回答:
text
reset 是"撤销",从历史中移除提交。
revert 是"抵消",保留原提交但用新提交反转其更改。
在团队协作中,远程分支推荐使用 revert,避免改写历史导致协作混乱。
4. reset、revert、restore、checkout 的区别(高频!)
这道题是近年来面试官的宠儿,很多人会混淆:
| 命令 | 作用 | 影响范围 | 推荐度 |
|---|---|---|---|
checkout |
切换分支 / 恢复文件 | 工作区 | ⚠️ 功能过载,新版本分拆 |
restore |
恢复文件 | 工作区 / 暂存区 | ✅ Git 2.23+ 推荐 |
reset |
回退历史 | Commit / 暂存区 / 工作区 | ⚠️ 危险,谨慎使用 |
revert |
创建反向提交 | Commit | ✅ 团队推荐 |
记忆技巧:
text
restore → 恢复文件(restore = 还原)
reset → 重置历史(reset = 重置)
revert → 反转提交(revert = 恢复原状)
checkout 功能被拆分为 switch(切分支)和 restore(恢复文件)
5. Git Flow 分支策略是什么?
text
main ← 线上正式版本,只接受合并
└── develop ← 日常开发主线
├── feature/login ← 功能开发
├── feature/payment
├── release/1.2.0 ← 发布准备
└── hotfix/crash-fix ← 紧急修复
完整工作流程:
text
1. 日常开发在 develop 分支
2. 新功能从 develop 切出 feature 分支
3. feature 完成后合并回 develop
4. 准备发布时从 develop 切出 release 分支
5. release 测试通过后合并到 main 并打 tag
6. main 出现紧急问题,从 main 切出 hotfix 分支
7. hotfix 修复后同时合并到 main 和 develop
6. 如何恢复误删的提交或分支?
text
1. 使用 git reflog 找到被删提交或分支的 hash
2. git checkout -b recovery-branch <commit-hash> 恢复分支
3. 或 git cherry-pick <commit-hash> 挑取特定提交
4. 关键原理:Git 的垃圾回收机制有延迟,reflog 会保留操作记录
7. Git 对象模型是什么?(进阶)
text
Git 底层有四种对象:
- Blob:存储文件内容
- Tree:存储目录结构
- Commit:指向一个 Tree,包含元数据
- Tag:指向一个 Commit 的标记
Git 的快照本质就是这些对象的组合,
这就是为什么 checkout/reset/rebase 几乎瞬间完成------
它们只是在移动指针,而不是复制文件。
二十、快速参考卡片
🆘 救命命令 TOP 5
bash
# 1. 时光机 - 查看所有 HEAD 移动记录
git reflog
# 2. 安全预览 - 执行危险操作前查看影响
git stash # 备份工作区
git clean -n # 预览将要删除的文件
# 3. 安全强制推送 - 带安全检查的推送
git push --force-with-lease
# 4. 紧急保存 - 快速保存当前所有工作
git stash
# 5. 文件追溯 - 查看文件的修改者和时间
git blame filename
📋 日常高频命令速查
bash
# 创建并切换到新分支
git checkout -b feature/xxx
# 暂存所有修改
git add .
# 提交(推荐格式)
git commit -m "feat(module): description"
# 同步远程最新代码(使用 rebase)
git pull --rebase
# 推送到远程并设置上游
git push -u origin feature/xxx
# 查看简洁的提交历史
git log --oneline --graph --all
# 查看某个文件的所有修改历史
git log --follow -p filename
🔄 reset 模式速查
| 命令 | 工作区 | 暂存区 | Commit | 安全度 |
|---|---|---|---|---|
reset --soft |
保留 | 保留 | 回退 | 🟢 安全 |
reset --mixed |
保留 | 清空 | 回退 | 🟡 注意 |
reset --hard |
删除 | 删除 | 回退 | 🔴 危险 |
结语

掌握 Git 不仅是记住命令,更关键的是建立完整的认知体系:
- 理解三区模型 --- 知道每条命令影响了哪个区域
- 理解对象模型 --- 知道 Blob/Tree/Commit 的关系,理解 Git 为什么快
- 熟悉危险操作 --- 知道哪些命令可能造成不可逆的损失
- 会用 reflog --- 这是 Git 给你的最后保障,是人生的后悔药
- 遵守团队规范 --- 分支策略、提交规范、PR 流程是协作的基础
- 掌握实战场景 --- stash 切换任务、cherry-pick 精准移植、PR 工作流
建议从日常基础命令开始,逐步尝试高级功能。每当使用危险命令时,先用预览功能确认影响范围。
记住:
text
会用 Git ≠ 懂 Git ≠ 驾驭 Git
三区模型 → 会用 Git
对象模型 → 懂 Git
实战经验 + reflog → 驾驭 Git
💡 小贴士:
- 配置好常用别名可以大幅提升效率
- 将危险的裸命令包装成带安全选项的别名是个好习惯
- 永远在执行危险操作前先
git stash备份