整理时间:2026-10-19
适用场景:日常开发、团队协作(自建 GitLab)、分支管理、问题排查
说明:本记录按「从入门到熟练」的顺序组织,每条命令都给出用途 + 示例 + 注意事项,便于复习时快速定位。
目录
- 基础概念与模型
- 环境配置
- 仓库初始化与克隆
- 日常提交流程
- 查看状态与历史
- 分支管理 | 心智模型 · 使用场景 · 工作流 · 命令速览 · 分支模型 · 常见困惑
- 远程仓库操作
- 撤销与回退
- 合并与变基
- [贮藏 stash](#贮藏 stash)
- [标签 Tag](#标签 Tag)
- [忽略文件 gitignore](#忽略文件 gitignore)
- 问题排查工具
- 团队协作规范建议
- 常用命令速查表
一、基础概念与模型
理解 Git 的三区模型,是掌握所有命令的前提:
| 区域 | 英文 | 说明 |
|---|---|---|
| 工作区 | Working Directory | 你能直接看到、编辑的文件 |
| 暂存区 | Staging Area / Index | 用 git add 把改动放进来,等待提交 |
| 版本库 | Repository / HEAD | 用 git commit 把暂存区内容固化成一次记录 |
一个典型的数据流向:
工作区 --(git add)--> 暂存区 --(git commit)--> 版本库 --(git push)--> 远程仓库
<--(git checkout / restore)-- <--(git reset)-- <--(git pull/fetch)--
几个核心对象:
- commit :一次提交,含唯一 SHA-1 哈希(如
a1b2c3d)、作者、时间、说明、快照。 - branch:指向某个 commit 的可移动指针(本质只是一个 41 字节的文件)。
- HEAD :指向「当前所在分支」的指针。
HEAD~1表示上一个提交,HEAD^同理。 - origin:远程仓库的默认别名。
⚠️ 注意:Git 记录的是文件快照,不是 diff。所以回退到某个版本非常快,也不会丢失历史。
二、环境配置
2.1 身份配置(首次必做)
bash
git config --global user.name "zhaojingang"
git config --global user.email "zhaojingang@example.com"
2.2 常用配置
bash
# 默认编辑器(GitLab 提交、merge message 会用到)
git config --global core.editor "vim"
# 让中文文件名不显示为转义字符(如 \344\270\255)
git config --global core.quotepath false
# 换行符处理:Windows 下推荐,避免 CRLF/LF 混乱
git config --global core.autocrlf true
# 命令别名,提高效率
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.lg "log --oneline --graph --decorate --all"
# 拉取时对分支做 rebase 而非 merge(保持线性历史,视团队规范而定)
git config --global pull.rebase false
2.3 查看配置
bash
git config --list # 列出所有配置
git config --list --show-origin # 显示配置来源文件
git config user.name # 查看单项
💡 配置层级优先级:
--system<--global<--local(仓库内)。仓库内配置会覆盖全局。
三、仓库初始化与克隆
bash
# 在当前目录初始化一个新仓库(生成 .git 目录)
git init
# 初始化并指定默认分支名为 main
git init -b main
# 克隆远程仓库到本地
git clone http://10.1.3.143:9509/feiShu_hermes/xxx.git
# 克隆到指定目录
git clone <url> my-project
# 只克隆最近一次提交(加快大仓库速度)
git clone --depth 1 <url>
# 克隆指定分支
git clone -b dev <url>
💡 自建 GitLab 的地址形如
http://10.1.3.143:9509/<group>/<project>.git,首次 clone 会要求输入用户名密码或 Personal Access Token,可用git config --global credential.helper store记住凭据(注意明文存储的安全风险,建议用凭据管理器)。
四、日常提交流程
这是使用频率最高的一组命令:
bash
# 1. 查看当前改动状态
git status
git status -s # 精简输出(?? 未跟踪,M 修改,A 新增)
# 2. 把改动加入暂存区
git add file.txt # 指定文件
git add src/ # 指定目录
git add . # 当前目录所有改动(新增+修改,不含忽略文件)
git add -A # 全仓库所有改动(含删除)
git add -u # 只暂存已跟踪文件的修改与删除,不含新文件
# 3. 交互式选择要提交的片段(推荐用于拆分提交)
git add -p
# 4. 提交
git commit -m "feat: 新增发票信息提取接口"
git commit # 打开编辑器写多行说明
git commit -am "fix: 修正查重逻辑" # 跳过 add,但只对已跟踪文件生效
# 5. 修改最后一次提交(还没 push 时)
git commit --amend -m "新的提交说明"
git commit --amend --no-edit # 只改动内容,保留原说明
提交信息规范(Conventional Commits)
推荐格式:<type>(<scope>): <subject>
| type | 含义 |
|---|---|
feat |
新功能 |
fix |
修 bug |
docs |
文档变更 |
style |
格式调整(不影响逻辑) |
refactor |
重构 |
perf |
性能优化 |
test |
测试相关 |
chore |
构建/依赖/杂项 |
示例:fix(invoice): 修复同一发票重复入库的边界情况
五、查看状态与历史
bash
# 日志
git log # 完整日志
git log --oneline # 一行一条
git log --oneline --graph --all # 图形化展示所有分支
git log -p # 显示每次提交的具体 diff
git log --stat # 显示改动的文件统计
git log -3 # 只看最近 3 条
git log --author="zhaojingang" # 按作者过滤
git log --since="2026-10-01" --until="2026-10-19"
git log --grep="发票" # 按提交说明搜索
git log -S "TODO" # 搜索「内容变更」包含某字符串的提交(pickaxe)
# 查看某文件的修改历史
git log --follow -- path/to/file
# 查看某次提交的详情
git show a1b2c3d
git show HEAD
git show HEAD --stat
# 查看某行代码是谁改的(背锅神器)
git blame path/to/file
git blame -L 10,30 path/to/file # 只看 10-30 行
# 查看某个引用/文件当前内容
git cat-file -p HEAD
💡 排查「这行代码为什么变成这样」的高效组合:
git log -S "关键代码" --oneline找到引入的提交,再git show <hash>看完整改动。
六、分支管理
6.0 先建立心智模型:分支到底是什么?
这是理解一切分支操作的关键:
分支不是"文件夹的副本",它只是一个 41 字节的指针文件,里面存着一个 commit 的哈希值。
main → [C3] ← HEAD
↑
[C2]
↑
[C1]
# 创建一个新分支 = 新写一个小文件,指向同一个 commit
git switch -c feature/x
main → [C3]
↑
feature/x → [C3] ← HEAD # 两个指针指向同一个提交,没有任何文件被复制
由此推出几个反直觉但重要的结论:
| 结论 | 含义 |
|---|---|
| 创建分支极快、极省空间 | 只是写一个 41 字节文件,与仓库大小无关 |
| 切换分支会改变工作区文件 | Git 把工作区内容「替换」成目标提交的快照 |
| 提交时只有 HEAD 所在的分支在移动 | 这就是「你在哪个分支上提交,提交就长在哪」 |
| 切换前有未提交改动会失败或带过去 | 所以常配合 stash 或 commit |
再理解 HEAD:
HEAD是「你现在站在哪」的指针,通常指向一个分支:HEAD → main → C3- 也有「游离 HEAD(detached HEAD)」状态:
HEAD → C3,不指向任何分支名- 出现场景:
git checkout <hash>、git checkout v1.0.0(切到标签) - ⚠️ 危险点:此时提交的 commit 不在任何分支上,切走后容易"丢失"(用
git reflog+git switch -c可救回)
- 出现场景:
bash
# 看看 HEAD 究竟指向哪
cat .git/HEAD # 输出 ref: refs/heads/main
git symbolic-ref HEAD # main
git rev-parse HEAD # 当前提交哈希
6.1 为什么用分支:四个典型场景
这是最实用的部分------什么时候该开分支:
| 场景 | 为什么开分支 | 分支名建议 |
|---|---|---|
| 开发新功能 | 主干上要随时能发版,半成品功能不能污染主干 | feature/invoice-dedup |
| 修线上 bug | 需要基于「线上版本」快速修复并单独发版,而不是等主干的功能做完 | hotfix/fix-login-500 |
| 改别人的代码 / 做实验 | 不确定方案是否可行,失败了直接删掉分支,零成本 | experiment/new-parser |
| 多人并行改同一个模块 | 各自在分支上工作,互不阻塞,合并时统一处理冲突 | feature/xxx-zhang |
反面案例(不该开分支的情况):
- 只改一个错别字、改个注释 → 直接在主干提交,开分支反而增加流程成本
- 已经在别人的分支上协作 → 不要另开分支,直接在那个分支上继续提交
- 纯本地个人项目 → 分支可完全不用,一条
main走到黑也没问题
判断口诀:
只要这个改动**「有可能中途失败」或 「需要和其他改动隔离发布」**,就开分支。
反之,确定要立刻进主干的小改动,不必开。
6.2 分支上的实际工作流(最关键)
分支本身没意义,**「创建 → 开发 → 同步 → 合并 → 删除」**这个闭环才有意义。下面按场景拆开讲。
场景 A:在功能分支上开发 → 合并回主干
bash
# ① 从最新主干拉出分支
git switch main
git pull --rebase # 确保起点是最新的
git switch -c feature/invoice-dedup # 创建并切换
# ② 在此期间随便提交多少次
git add -p
git commit -m "feat(invoice): 新增发票哈希去重"
git commit -m "test(invoice): 补去重单测"
# ③ 开发过程中主干被别人更新了,把自己的分支同步上去(关键一步)
git fetch origin
git rebase origin/main # 把你的提交"接到"最新主干之后
# 或者:git merge origin/main # 会多一个合并提交,历史稍乱
# ④ 推送你的分支
git push -u origin feature/invoice-dedup
# → 在 GitLab 上创建 Merge Request,交给 review
# ⑤ MR 合并后,回到主干并清理分支
git switch main
git pull
git branch -d feature/invoice-dedup # 本地删除
git push origin --delete feature/invoice-dedup # 远程删除(GitLab 通常可自动删)
场景 B:线上出 bug,紧急修复
bash
# 从"线上发布的那个点"拉分支,而不是从 main 最新拉
git switch -c hotfix/fix-login-500 v1.0.0
git commit -am "fix(login): 修复空 token 导致 500"
git push -u origin hotfix/fix-login-500
# → MR 合并到 main,并打新标签 v1.0.1
# 修完别忘把修复「同步回主干」,否则下次发版又被还原
git switch main
git cherry-pick <hotfix上的提交hash>
场景 C:多分支之间来回切换(正在写 A,突然要改 B)
bash
# 你在 feature/A 上写了一半,代码跑不起来,不想提交
git stash -u # 先收起半成品
git switch main
git switch -c hotfix/B
# ... 处理 B 并提交 ...
git switch feature/A
git stash pop # 把半成品恢复回来
💡 只说「改一下别的分支」但不涉及未提交改动 时,直接
git switch即可。
场景 D:需要临时基于某个历史版本看一眼(不改代码)
bash
git switch --detach v1.0.0 # 明确进入 detached HEAD,只是看
# 看完回到分支:
git switch main
6.3 分支操作命令
bash
# 查看分支
git branch # 本地分支
git branch -a # 含远程分支
git branch -v # 显示每个分支的最新提交
git branch --merged # 已合并到当前分支的分支(可安全删除)
git branch --no-merged # 未合并的分支
# 创建 / 切换
git branch feature/invoice-dedup # 创建(不切换)
git checkout feature/invoice-dedup # 切换
git checkout -b feature/invoice-dedup # 创建并切换(旧写法)
git switch feature/invoice-dedup # 切换(新写法,推荐)
git switch -c feature/invoice-dedup # 创建并切换(新写法)
git switch -c hotfix/xxx origin/main # 基于远程分支创建
# 重命名 / 删除
git branch -m old-name new-name
git branch -d feature/done # 删除已合并分支
git branch -D feature/abandoned # 强制删除(未合并也删)
git push origin --delete feature/old # 删除远程分支
# 追踪远程分支
git branch -u origin/main # 把当前分支关联到 origin/main
git branch -vv # 查看追踪关系
git branch -a --merged # 哪些分支已经合进当前分支
分支命名建议 :feature/xxx、bugfix/xxx、hotfix/xxx、release/x.y.z,避免中文和空格。用 / 分隔可以让 GitLab 呈现层级树状结构。
6.4 常见分支模型(团队怎么约定分支)
「什么时候开分支」最终由团队的分支模型决定。实践中最常见的两种:
模型一:主干开发(Trunk Based)------ 推荐,适合持续交付
main ──●──●──●──●──●──●──► 主干始终可发布
\ / \ /
feature/A ●─● ●─● feature/B 分支寿命短(1~3 天),用完即删
- 规则 :任何人都从
main拉分支,改完尽快合回 - 优点:集成早、冲突少、发布频率高
- 适合:小团队、SaaS、快速迭代
模型二:Git Flow ------ 适合有明确版本发布节奏的产品
main ──────●──────────────●────────► 只放正式发布
/ \ / \
release ───/───●──────────/───●──────► 发布准备(改 bug、定版本号)
/ \ / \
develop ──●───●────●─────●───●───●────► 日常开发集成
\ / \ /
feature ●● ●● 功能分支
hotfix ──► 直接从 main 拉出紧急修复
涉及的分支:
| 分支 | 生命周期 | 用途 |
|---|---|---|
main / master |
永久 | 只存放已发布的稳定版本,每个提交都对应一个 tag |
develop |
永久 | 日常开发的集成分支,功能都合到这里 |
feature/* |
临时 | 从 develop 拉出,用完删 |
release/* |
临时 | 从 develop 拉出做发布准备 |
hotfix/* |
临时 | 从 main 拉出修线上 bug |
- 优点:职责清晰、版本可控
- 缺点:分支多、流程重、合并频繁,小团队容易累
- 适合:需要维护多个版本的传统软件、需要严格发布管控的产品
📌 给不熟悉分支的你的建议 :如果团队没强制规定,从「主干开发」开始 ------只需理解和掌握
feature/*一种分支就够了,等真正遇到多版本维护需求再引入 Git Flow。
6.5 新手最容易困惑的 6 个问题
Q1:本地分支和远程分支是同一个东西吗?
不是。远程分支(origin/main)是只读的本地快照,表示"上次 fetch 时远程的样子"。你不能直接在上面提交,只能通过 push 更新。
你的本地: main(可提交)
远程快照: origin/main(只读,fetch 时更新)
真正的远程: GitLab 服务器上的 main
Q2:为什么 git branch -a 里有一堆 remotes/origin/xxx 删不掉?
那些是"远程快照",本地删没用。分支在服务器上被删后,用 git fetch --prune 清理这些残留引用。
Q3:切分支时提示 Your local changes would be overwritten?
因为目标分支该文件的内容和你的未提交改动冲突。三个解法:
bash
git stash # 收起改动再切,之后 pop 回来(推荐)
git commit # 先提交再切
git restore <file> # 确定不要这些改动,丢弃
Q4:我在错误的分支上提交了怎么办?
bash
# 场景:本该在 feature/x 提交,结果提交到了 main
git log --oneline -1 # 记下这个提交的 hash
git switch feature/x # 切到正确的分支
git cherry-pick <hash> # 把提交"摘"过来
git switch main
git reset --hard HEAD~1 # 从 main 上抹掉(main 未 push 时安全)
Q5:分支合完了,本地和远程都该删吗?
应该。分支是用完即弃 的临时结构,长期堆积会让 git branch 输出失控。合并后按 6.2 场景 A 的第 ⑤ 步清理即可。
Q6:删分支会丢代码吗?
git branch -d 只会删掉那个指针文件 ,提交本身还在(被 main 或其他分支引用着)。只有 -D 强制删掉未合并 的分支,才会让那些提交变成"没人引用"------但此时用 git reflog 仍可找回。真正会永久丢失的只有「从未提交过」的工作区改动。
6.6 分支相关的可视化工具
bash
# 用图形看分支的"分叉与合并",理解分支最直观的方式
git log --oneline --graph --decorate --all
# 只看最近 10 条
git log --oneline --graph --all -10
# 设置别名,以后一条命令搞定(推荐)
git config --global alias.tree "log --oneline --graph --decorate --all"
# 之后直接:git tree
也可以执行 gitk --all(内置图形界面)或 git gui,或直接看 GitLab 的「Repository → Graph」页面,比命令行更直观。
七、远程仓库操作
bash
# 查看远程
git remote -v
git remote show origin
# 添加 / 修改远程
git remote add origin <url>
git remote set-url origin <new-url>
git remote rename origin upstream
# 拉取(fetch 只下载,不动工作区;pull = fetch + merge/rebase)
git fetch origin
git fetch --all --prune # 拉取所有远程并清理已删除的远程分支引用
# 拉取并合并到当前分支
git pull
git pull --rebase origin main # 拉取时用 rebase(历史更整洁)
# 推送
git push # 推当前分支
git push -u origin main # 首次推送并建立追踪关系
git push origin feature/invoice-dedup
git push --force-with-lease # 安全强推(如果远程被别人更新会失败,避免覆盖他人)
git push origin --tags # 推送所有标签
⚠️ 关于 force push :
git push -f会直接覆盖远程历史,可能造成他人提交丢失 。永远优先用--force-with-lease,并且只在个人分支上操作,绝不要对main/master强推。
推荐的安全拉取流程
bash
git fetch origin # 先下载,不改变本地
git log HEAD..origin/main --oneline # 看看远程多了什么
git rebase origin/main # 或 git merge origin/main
八、撤销与回退
这一节最容易出错,务必区分场景。
8.1 撤销工作区改动(还没 add)
bash
git restore file.txt # 丢弃工作区改动(新写法)
git checkout -- file.txt # 旧写法,效果相同
git restore . # 丢弃所有工作区改动
8.2 撤销暂存(已 add,还没 commit)
bash
git restore --staged file.txt # 从暂存区撤出,保留工作区改动
git reset HEAD file.txt # 旧写法
git reset # 撤出全部暂存内容
8.3 撤销提交(已 commit)
bash
# 方式一:reset ------ 直接把分支指针往回挪(会改写历史)
git reset --soft HEAD~1 # 撤销提交,改动保留在暂存区
git reset --mixed HEAD~1 # 撤销提交,改动保留在工作区(默认)
git reset --hard HEAD~1 # 撤销提交并丢弃所有改动 ⚠️危险
# 方式二:revert ------ 生成一次「反向提交」(不改写历史,安全)
git revert a1b2c3d # 适用于已 push 的公共提交
git revert HEAD
git revert -n a1b2c3d # 只应用改动不自动提交
选型口诀:
- 提交还没 push 、是本地私有的 → 用
reset - 提交已经 push 、别人可能已拉取 → 用
revert
8.4 引用日志与救命
bash
git reflog # 查看 HEAD 移动历史,找回"丢失"的提交
git reset --hard a1b2c3d # 配合 reflog 找到的 hash 恢复
💡
reflog是误操作后的最后一道保险。只要 commit 过,即使分支被删、reset 错方向,通常几十天内都能找回。
九、合并与变基
9.1 merge
bash
git switch main
git merge feature/invoice-dedup
# 禁用快进,强制生成一个合并提交(保留分支拓扑)
git merge --no-ff feature/invoice-dedup
# 只允许快进,否则失败
git merge --ff-only origin/main
# 中止一次冲突中的合并
git merge --abort
9.2 rebase
bash
git switch feature/x
git rebase main # 把 feature 的提交"挪"到 main 最新提交之后
git rebase --continue # 解决冲突后继续
git rebase --skip # 跳过当前提交
git rebase --abort # 放弃 rebase
# 交互式变基:整理/合并/重排提交(本地提交整理利器)
git rebase -i HEAD~3
# 编辑器里可用动作:pick / reword / edit / squash / fixup / drop
merge vs rebase 对比:
| merge | rebase | |
|---|---|---|
| 历史形态 | 保留分支结构,有合并节点 | 线性整洁 |
| 是否改写历史 | 否 | 是 |
| 适用场景 | 公共分支合并 | 个人分支同步主干 |
| 风险 | 历史较乱 | 不要在已 push 的公共分支上 rebase |
9.3 解决冲突的通用步骤
bash
# 1. 冲突时 git status 会标出 both modified 的文件
# 2. 手动编辑文件,保留所需内容,删除 <<<<<<< ======= >>>>>>> 标记
# 3. 标记为已解决
git add resolved-file.txt
# 4. 继续流程
git commit # merge 场景
git rebase --continue # rebase 场景
十、贮藏 stash
临时切换任务、又不想提交半成品时使用:
bash
git stash # 贮藏当前改动
git stash push -m "发票解析半成品" # 带说明
git stash -u # 连未跟踪的新文件一起贮藏
git stash list # 查看贮藏列表
git stash show -p stash@{0} # 查看某个贮藏的具体内容
git stash pop # 恢复并删除该贮藏(默认最近一个)
git stash apply stash@{1} # 恢复但保留贮藏记录
git stash drop stash@{0} # 删除指定贮藏
git stash clear # 清空所有贮藏 ⚠️
十一、标签 Tag
用于标记发布版本:
bash
git tag # 列出标签
git tag -l "v1.*" # 按模式过滤
git tag v1.0.0 # 轻量标签
git tag -a v1.0.0 -m "首个正式版" # 附注标签(推荐,含作者/时间/说明)
git tag -a v1.0.1 a1b2c3d -m "补丁" # 给历史提交补打标签
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 push不会 自动推送标签,必须显式--tags或指定标签名。
十二、忽略文件 .gitignore
放在仓库根目录(也可放子目录,作用范围不同):
gitignore
# 依赖
node_modules/
vendor/
# 构建产物
dist/
build/
*.pyc
__pycache__/
# 日志与临时文件
*.log
*.tmp
.DS_Store
# 环境与密钥(务必忽略!)
.env
*.pem
config/secrets.yml
# IDE
.idea/
.vscode/
常用配套命令:
bash
git check-ignore -v path/to/file # 排查某文件为什么被忽略
git rm -r --cached node_modules # 已误提交的文件停止跟踪(保留本地)
⚠️
.gitignore只对未跟踪文件生效 。已经提交过的文件必须先用git rm --cached移出索引,忽略规则才会生效。
十三、问题排查工具
bash
# 对比差异
git diff # 工作区 vs 暂存区
git diff --staged # 暂存区 vs 最后一次提交
git diff HEAD # 工作区 vs 最后一次提交
git diff main..feature # 两个分支差异
git diff a1b2c3d d4e5f6a # 两次提交差异
git diff --stat # 只显示统计
# 二分查找定位引入 bug 的提交(非常高效)
git bisect start
git bisect bad # 当前版本有问题
git bisect good a1b2c3d # 某个已知正常的版本
# Git 会不断 checkout 中间提交,你测试后继续标记 good/bad
git bisect good # 或 git bisect bad
git bisect reset # 结束后回到原分支
# 搜索
git grep "关键字" # 在已跟踪文件中搜索(比 grep 更快更准)
git grep -n "关键字" # 带行号
# 清理未被跟踪的文件(危险操作,先 dry-run)
git clean -n # 预览将被删除的文件
git clean -f # 删除未跟踪文件
git clean -fd # 连未跟踪目录一起删
git clean -fdx # 连 ignore 的文件也删(慎用)
十四、团队协作规范建议
结合实际项目(自建 GitLab)总结几条经验:
- 保护主干 :
main/master设为保护分支,禁止直接 push,只能通过 Merge Request 合入。 - 小步提交:一次提交只做一件事,方便回滚和 review。
- 及时同步 :每天开始工作前先
git fetch/git pull --rebase,减少冲突。 - 分支生命周期短:功能分支尽快合并,避免长期存在导致冲突加剧。
- 提交前自检 :
git status确认没有误加临时文件、密钥、大文件。 - 冲突时不要慌 :先
git status看状态,再处理;实在不行git merge --abort/git rebase --abort回到干净状态重新来。 - 永远不要 :对公共分支强推、提交
.env等敏感信息、git add .前不看 status。
典型的特性开发流程
bash
# 1. 同步主干
git switch main
git pull --rebase
# 2. 拉出功能分支
git switch -c feature/invoice-dedup
# 3. 开发、提交(多次)
git add -p
git commit -m "feat(invoice): 新增发票哈希去重"
# 4. 期间同步主干最新代码
git fetch origin
git rebase origin/main
# 5. 推送并创建 MR
git push -u origin feature/invoice-dedup
# 6. MR 合并后,清理本地分支
git switch main
git pull
git branch -d feature/invoice-dedup
十五、常用命令速查表
| 目的 | 命令 |
|---|---|
| 查看状态 | git status -s |
| 添加改动 | git add -p |
| 提交 | git commit -m "..." |
| 修改上次提交 | git commit --amend |
| 查看历史 | git log --oneline --graph --all |
| 看某行是谁改的 | git blame -L 10,30 file |
| 新建并切换分支 | git switch -c feature/x |
| 切换分支 | git switch main |
| 基于远程/标签创建分支 | git switch -c feature/x origin/main |
| 查看分支树 | git log --oneline --graph --decorate --all |
| 查看哪些分支已合并 | git branch --merged |
| 清理远程残留分支引用 | git fetch --prune |
| 跨分支搬运提交 | git cherry-pick <hash> |
| 删除分支 | git branch -d feature/x |
| 拉取 | git pull --rebase |
| 推送 | git push -u origin feature/x |
| 安全强推 | git push --force-with-lease |
| 丢弃工作区改动 | git restore file |
| 撤出暂存 | git restore --staged file |
| 撤销本地提交 | git reset --soft HEAD~1 |
| 撤销已推送提交 | git revert <hash> |
| 找回归失提交 | git reflog |
| 贮藏改动 | git stash -u |
| 恢复贮藏 | git stash pop |
| 打标签 | git tag -a v1.0.0 -m "..." |
| 推标签 | git push origin --tags |
| 对比差异 | git diff --staged |
| 定位引入 bug 的提交 | git bisect |
| 清理未跟踪文件 | git clean -nd |
附:易混淆点小结
| 容易混淆 | 区别 |
|---|---|
fetch vs pull |
fetch 只下载不动工作区;pull = fetch + 合并 |
reset vs revert |
reset 改写历史(本地用);revert 生成反向提交(公共用) |
reset --soft/--mixed/--hard |
改动分别保留在暂存区 / 工作区 / 被丢弃 |
git add . vs -A vs -u |
. 当前目录含新文件;-A 全仓库;-u 只含已跟踪文件 |
merge vs rebase |
merge 保留分支结构;rebase 得到线性历史但改写历史 |
checkout vs switch/restore |
新版本把职责拆分了,checkout 仍可用但语义模糊,推荐新命令 |
| 标签 vs 分支 | 标签是固定不动的版本标记;分支是会移动的指针 |
📌 学习建议:命令不用背,记住三区模型 + 知道自己当前在哪个区 ,剩下都是查文档的事。
官方文档:
git help <command>、git <command> --help,或 https://git-scm.com/docs