Git 命令速查
按「我正在做什么」分组的 Git 命令表。会丢代码或改历史的操作单独标了风险,选之前先看一眼。
显示 67 / 67 条命令
常见任务直接抄
日常最常出现的十个愿望,对应的命令就这一条。参数细节可以往下翻命令表。
| 想做的事 | 命令 | 复制 |
|---|---|---|
| 想撤销最后一次提交但保留改动 | git reset --soft HEAD~1 | |
| 想改上一次提交的说明或补漏文件 | git add 漏掉的文件 && git commit --amend --no-edit | |
| 想丢掉某个文件的未提交改动 | git restore 文件路径 | |
| 暂存区放错了文件想撤回 | git restore --staged 文件路径 | |
| 改动做到一半要切分支救火 | git stash push -u -m "说明" | |
| 想看清工作区将删掉哪些未跟踪文件 | git clean -nd | |
| 提交推错了分支想搬走 | git switch 正确分支 && git cherry-pick 哈希 | |
| 误删分支或 reset --hard 后悔了 | git reflog 找到哈希后 git switch -c 新分支 哈希 | |
| 想看这个文件某一行是谁改的 | git blame -L 起始行,结束行 文件 | |
| 想找出哪次提交引入了 bug | git bisect start HEAD 已知正常的版本 |
分类说明
| 分类 | 条数 | 包含什么 |
|---|---|---|
| 仓库与状态 | 7 | 初始化、克隆、查看改动和提交历史 |
| 暂存与提交 | 4 | 把改动组合成提交,以及修补和撤销提交 |
| 分支与合入 | 7 | 建分支、切换、合并、变基和拣选提交 |
| 远程协作 | 5 | 拉取、推送、跟踪分支和 PR 相关操作 |
| 撤销与回退 | 5 | 撤销改动、回退提交、找回丢失的提交 |
| 暂存现场 | 6 | 临时把未提交的改动挪开再拿回来 |
| 查看与追溯 | 6 | 查历史、查是谁改的、查文件每一行的来历 |
| 比较与补丁 | 6 | 比较不同提交、分支和工作区,导出补丁 |
| 标签与发布 | 5 | 打版本标签、签名和推送标签 |
| 配置与维护 | 8 | 身份、别名、换行符、忽略规则和仓库清理 |
| 进阶操作 | 8 | 子模块、工作树、二分查找、打包和稀疏检出 |
命令清单
| 命令 | 作用 | 常用参数 | 示例 | 复制 |
|---|---|---|---|---|
| git init | 把当前目录变成 Git 仓库 | -b 指定初始分支名,--bare 建裸仓库(当远程用),--template 指定模板目录 | git init -b main | |
| git clone | 克隆远程仓库到本地 | --depth=1 只取最新一次提交,--branch 指定分支,--recurse-submodules 连子模块一起,--filter=blob:none 部分克隆 | git clone --depth=1 --branch main git@github.com:org/repo.git | |
| git status | 查看工作区与暂存区的改动状态 | -s 精简输出,-b 同时显示分支信息,--ignored 连被忽略的文件一起列,--porcelain 机器可读格式 | git status -sb | |
| git add | 把改动放进暂存区 | -A 全量(含删除),-u 只处理已跟踪文件的改动,-p 交互式分块挑,-n 只演练不执行 | git add -p | |
| git rm | 删除文件并同时记入暂存区 | --cached 只从版本控制里移除、保留本地文件,-r 递归目录,-f 强制删有改动的文件 | git rm -r --cached ./dist | |
| git mv | 移动或重命名文件并记入暂存区 | -f 目标已存在时强制覆盖,-k 出错也继续处理后面的文件 | git mv old/name.ts src/name.ts | |
| git restore | 把文件恢复到某个版本的状态(新版撤销命令) 注意:git restore 不带 --staged 会直接覆盖工作区的未提交改动,而且不进回收站。想留着就先用 git stash 或先提交。 | --staged 撤销暂存,--source 指定来源版本,-p 分块挑,-W 连工作区一起恢复 | git restore --source=HEAD~2 -- src/app.ts | |
| git commit | 把暂存区的内容提交成一个版本 | -m 直接给信息,-a 自动包含已跟踪文件的改动,--amend 修补上一次提交,-p 分块提交,--no-verify 跳过钩子 | git commit -m "fix: 修正分页越界" | |
| git commit --amend | 改写最近一次提交(补文件或改信息) 注意:amend 会生成新的提交哈希。已经推到共享分支的提交不要 amend,否则别人拉下来会分叉,只能靠强推收拾。 | --no-edit 保留原提交信息,-m 换新信息,--date 改提交时间 | git commit --amend --no-edit | |
| git reset | 移动分支指针,用来撤销提交 注意:reset --hard 会丢掉未提交的改动,Git 里没有回收站,只能靠 reflog 找回已提交过的内容,没提交过的恢复不了。 | --soft 保留改动在暂存区,--mixed 保留在工作区(默认),--hard 连改动一起丢,HEAD~n 回退 n 个提交 | git reset --soft HEAD~1 | |
| git revert | 用一个新提交抵消指定提交,历史不改写 | -n 只改暂存区不自动提交,-m 指定合并提交的主线父节点,--no-edit 用默认信息 | git revert --no-edit a1b2c3d | |
| git branch | 列出、创建或删除分支 | -a 含远程分支,-v 显示各分支最新提交,-d 删除已合并分支,-D 强制删除,-m 重命名,--merged 只看已合并的 | git branch -vv | |
| git switch | 切换分支(新版命令,语义比 checkout 清楚) | -c 创建并切换,- 回到上一个分支,--detach 切到游离状态,--track 跟踪远程分支 | git switch -c feature/login | |
| git checkout | 切换分支或恢复文件(老版命令,兼职两件事) | -b 创建并切换,-- 后面跟文件表示恢复文件,-p 分块恢复,--detach 游离头指针 | git checkout -b hotfix --track origin/hotfix | |
| git merge | 把另一个分支的提交合进当前分支 注意:合并冲突时别直接 -X theirs 一把梭,那等于无声丢掉自己的改动。先看清楚冲突内容再决定。 | --no-ff 强制生成合并提交,--squash 压成一个改动但不提交,--abort 放弃这次合并,-X ours/theirs 处理冲突 | git merge --no-ff feature/login | |
| git rebase | 把当前分支的提交挪到另一个分支之后,历史更直 注意:rebase 会改写提交哈希。只在自己独占的分支上做,推过的共享分支 rebase 会让同事的历史和你对不上。 | -i 交互式(可压缩、改序、改信息),--onto 换基底,--continue/--abort 处理冲突,--autosquash 自动应用 fixup | git rebase -i origin/main | |
| git cherry-pick | 把指定的某几个提交摘到当前分支 | -n 只改工作区不提交,-x 在信息里标注来源提交,--continue/--abort 处理冲突,可接多个哈希 | git cherry-pick -x a1b2c3d | |
| git switch --orphan | 创建一个没有历史的全新分支 | 配合 git rm -rf . 清空工作区后即可作为干净起点 | git switch --orphan docs-clean | |
| git remote | 管理远程仓库地址 | -v 查看地址,add 添加,remove 删除,rename 改名,set-url 改地址,prune 清理已删除的远程分支引用 | git remote set-url origin git@github.com:org/repo.git | |
| git fetch | 从远程取回更新但不合并到当前分支 | --all 所有远程,--prune 同时清理已删除的分支,--tags 连标签一起取,-j 并行取多个远程 | git fetch --all --prune --tags | |
| git pull | 取回远程更新并合并到当前分支 注意:默认的 pull 会产生一次合并提交,本地有未推提交时历史会变乱。日常建议配成 rebase 或坚持用 --ff-only。 | --rebase 用变基代替合并,--ff-only 只允许快进(最安全),-p 顺带清理远程已删分支 | git pull --ff-only | |
| git push | 把本地提交推送到远程 注意:push --force 会覆盖远程历史,别人的提交可能直接消失。必须强推时用 --force-with-lease,它会在远程被别人更新过时拒绝执行。 | -u 建立跟踪关系,--force-with-lease 安全强推,--tags 推标签,--delete 删远程分支,--dry-run 只演练 | git push -u origin HEAD | |
| git push --delete | 删除远程分支或标签 | 删分支:git push origin --delete 名字;删标签:git push origin --delete tag 标签名 | git push origin --delete feature/old-branch | |
| git restore --staged | 把文件从暂存区撤回工作区 | -- 后面跟路径,. 表示全部;等价于老版本的 git reset HEAD 文件 | git restore --staged . | |
| git clean | 删除工作区里没被跟踪的文件 注意:clean -fdx 会删掉所有未跟踪文件,包括 .env、本地数据库、编译产物,而且不可恢复。先跑 clean -nd 看清楚再删。 | -n 只列出将删除什么(务必先跑),-f 强制删,-d 含目录,-x 连 .gitignore 忽略的文件一起删,-i 交互式选 | git clean -nd | |
| git reflog | 查看 HEAD 的移动记录,找回误删的提交 | --date=iso 显示时间,show 看某个记录,-n 限制条数,expire 清理记录 | git reflog -n 30 | |
| git checkout 哈希 -- 文件 | 把某个文件恢复到历史上某个提交的版本 | 哈希可以用 HEAD~2、reflog 里的条目或短哈希,-- 后面跟文件路径 | git checkout a1b2c3d -- src/config.ts | |
| git reset --hard | 把分支指针、暂存区和工作区一起退到指定提交 注意:一条命令同时丢暂存和工作区改动,是 Git 里最容易造成不可逆损失的操作。执行前先 git stash 或确认这些改动真的不要了。 | 配 origin/main 可把本地强行对齐远程,HEAD~1 退一个提交 | git reset --hard origin/main | |
| git stash | 把未提交的改动挪到一边,工作区变干净 | -u 连未跟踪文件一起存,-a 连被忽略的文件一起存,-m 加说明,-k 保留暂存区状态,push 显式推入 | git stash push -u -m "wip: 分页逻辑" | |
| git stash list | 列出所有暂存现场 | 每条前面是 stash@{n},n 越小越新,配 show 可看具体内容 | git stash list | |
| git stash pop | 取回最近一次暂存并从列表里删掉 | stash@{n} 指定取哪一条,--index 连暂存区状态一起恢复 | git stash pop stash@{1} | |
| git stash apply | 取回暂存但保留记录,适合多次复用 | stash@{n} 指定条目,--index 恢复暂存区状态 | git stash apply | |
| git stash drop | 删除指定的一条暂存记录 注意:stash 的内容不在任何分支上,drop 之后只能靠 git fsck --lost-found 或翻 .git 里的悬空对象找回,很难。 | stash@{n} 指定条目,clear 清空全部暂存 | git stash drop stash@{0} | |
| git stash branch | 基于某条暂存记录新建分支并应用它 | 参数是新建的分支名,可再接 stash@{n} 指定条目 | git stash branch fix/pagination stash@{0} | |
| git log | 查看提交历史 | --oneline 单行,--graph 画分支图,--all 含所有分支,-n 限制条数,--author 按人筛,--since/--until 按时间筛,-S 搜改动内容 | git log --oneline --graph --all -n 30 | |
| git log --stat | 查看提交历史并列出每次改了哪些文件 | -p 连具体改动 diff 一起显示,--name-only 只列文件名,--follow 跟着重命名追历史 | git log --oneline --stat -n 5 | |
| git show | 查看某个提交或对象的详细内容 | 哈希 看指定提交,--stat 只看文件统计,标签名 看标签指向的提交,HEAD:路径 看某文件某版本 | git show --stat HEAD | |
| git blame | 逐行显示文件每一行是哪个提交改的 | -L 限定行范围,-w 忽略空白改动,-C 追踪跨文件搬移,--ignore-rev 跳过某些提交 | git blame -L 40,60 -w src/app.ts | |
| git shortlog | 按作者汇总提交数量 | -sn 只显示人名和数量,-n 按数量排序,-e 显示邮箱,--since 限定时间 | git shortlog -sne --since="3 months ago" | |
| git describe | 用最近的标签加距离描述当前提交 | --tags 用任意标签(不只带注释的),--always 没有标签时退回短哈希,--dirty 工作区有改动时加后缀 | git describe --tags --always --dirty | |
| git diff | 比较工作区和暂存区的差异 | --staged 比较暂存区与 HEAD,--stat 只给统计,--name-only 只列文件名,--word-diff 按词比较,-w 忽略空白 | git diff --stat | |
| git diff 分支之间 | 比较两个分支或两个提交的差异 | a..b 从 a 到 b 的差异,a...b 只看 b 相对共同祖先的新增(PR 常用),接文件路径可限定范围 | git diff main...HEAD -- src/ | |
| git difftool | 用图形化工具逐文件比较 | --dir-diff 目录整体比较,-y 不逐个询问,--tool 指定工具 | git difftool --dir-diff main | |
| git format-patch | 把提交导出成可邮寄的补丁文件 | -n 导出最近 n 个,-o 指定输出目录,--stdout 输出到标准输出,-1 只导一个 | git format-patch -1 --stdout > fix.patch | |
| git apply | 把补丁文件应用到工作区 | --check 先检查能否干净应用,--3way 三方合并,-R 反向应用(撤销补丁),--stat 只看统计 | git apply --check fix.patch | |
| git am | 应用 format-patch 导出的补丁并保留提交信息 | -3 三方合并,--abort 放弃,--continue 冲突解决后继续,--skip 跳过当前补丁 | git am -3 *.patch | |
| git tag | 列出、创建或删除标签 | -l 按模式筛选,-d 删除本地标签,-a 创建带注释标签,-m 附说明,-n 显示标签说明 | git tag -l "v1.2.*" | |
| git tag -a | 创建带注释的标签,发布版本用这种 | -a 标签名,-m 说明文字,可接提交哈希给历史提交打标签 | git tag -a v1.4.0 -m "发布 1.4.0" | |
| git tag -s | 创建带 GPG 签名的标签 | -s 签名,-u 指定密钥,-m 说明;用 git tag -v 校验签名 | git tag -s v1.4.0 -m "发布 1.4.0" | |
| git push --tags | 把本地标签推送到远程 | git push origin 标签名 只推一个,git push origin --delete 标签名 删远程标签,--follow-tags 随提交推送相关标签 | git push origin v1.4.0 | |
| git describe --tags | 生成形如 v1.3.0-12-gabc1234 的版本号 | --always 兜底用哈希,--dirty 有未提交改动时加标记,--long 强制带完整信息 | git describe --tags --always | |
| git config | 读取或设置 Git 配置 | --global 用户级,--local 仓库级,--list 列出,--get 读单项,--unset 删配置 | git config --global user.name "你的名字" | |
| git config --global alias | 给常用命令配别名 | alias.短名 命令,配 ! 开头可以跑 shell 命令 | git config --global alias.lg "log --oneline --graph --all" | |
| git config core.autocrlf | 处理 Windows 与 Unix 的换行符差异 | true Windows 上自动转换,input 只在提交时转成 LF,false 不转换;更推荐用 .gitattributes 统一管理 | git config --global core.autocrlf input | |
| git config pull.rebase | 让 pull 默认用变基而不是合并 | true 默认 rebase,false 默认 merge,only 只允许快进否则报错 | git config --global pull.rebase true | |
| git gc | 整理仓库、压缩对象、回收无用数据 注意:--prune=now 会立刻删除悬空对象,reflog 里能救回提交的窗口就此关闭。想留后路就先不加这个参数。 | --aggressive 更彻底但更慢,--prune=now 立刻清掉过期对象(慎用),--auto 只在需要时执行 | git gc --prune=now | |
| git fsck | 检查仓库完整性并列出悬空对象 | --lost-found 把悬空对象写到 .git/lost-found,--unreachable 列出不可达对象 | git fsck --lost-found | |
| git count-objects | 统计仓库对象数量和占用空间 | -v 显示人类可读大小,-H 直接显示 MB/GB | git count-objects -vH | |
| git archive | 把某个版本导出成压缩包(不含 .git) | --format 指定格式(zip/tar.gz),-o 输出文件,--prefix 加目录前缀 | git archive --format=zip --prefix=app/ -o app.zip HEAD | |
| git bisect | 二分查找是哪次提交引入了问题 | start 开始,good/bad 标记,run 跑脚本自动判定,reset 结束并复位,skip 跳过无法验证的提交 | git bisect start HEAD v1.2.0 | |
| git worktree | 同一个仓库挂出多个工作目录,可并行开分支 | add 新建工作树,list 列出,remove 删除,prune 清理失效记录 | git worktree add ../hotfix hotfix | |
| git submodule | 管理嵌套的仓库 | add 添加,update --init --recursive 拉取内容,status 查看状态,foreach 批量执行,deinit 取消 | git submodule update --init --recursive | |
| git sparse-checkout | 只检出大仓库里需要的目录 | init 开启,set 指定目录(cone 模式),add 追加,disable 关闭 | git sparse-checkout set --cone apps/web libs/shared | |
| git bundle | 把仓库或部分历史打包成单文件便于离线传输 | create 创建,verify 校验,clone 从包克隆,接 rev-list 参数可限定范围 | git bundle create repo.bundle --all | |
| git notes | 给提交追加不改变哈希的备注 | add 添加,append 追加,show 查看,list 列出所有带备注的提交 | git notes add -m "已通过安全评审" HEAD | |
| git replace | 临时用另一个对象替换现有对象,不改历史 | 对象哈希 替换 被替换哈希,-d 删除替换,-l 列出替换,--graft 嫁接历史 | git replace --graft HEAD~5 | |
| git filter-repo | 重写历史,用来删掉误提交的大文件或密钥 注意:filter-repo 会改写全部提交哈希,所有协作者都必须重新克隆。执行前一定先完整备份一份仓库,且要通知所有相关人。 | --path 只保留路径,--invert-paths 反向排除,--replace-text 替换敏感文本,--strip-blobs-bigger-than 删大文件 | git filter-repo --strip-blobs-bigger-than 10M |
三种撤销到底用哪个
只改了文件还没 add,用 git restore 文件路径 把工作区恢复到 HEAD 的样子;已经 add 进暂存区,用 git restore --staged 文件路径 退回工作区;已经 commit 了,才轮到 git reset。这三步是递进的,从哪一步开始出错就从哪一步往回撤,能少走很多弯路。
reset 的三种模式区别在「改动往哪去」:--soft 把改动留在暂存区(想重新组织提交时用),--mixed 留在工作区(这是默认值,想重新挑文件时用),--hard 直接丢掉。已经推到远程的提交不要用 reset 改,改用 git revert 生成一个反向提交,历史不动,别人也不会分叉。
rebase 和 merge 怎么选
简单说:合别人的分支用 merge,整理自己的分支用 rebase。merge 保留真实的合并点,历史如实反映「什么时候合的」;rebase 把提交重新摆放,得到一条直线,看着舒服但改写了哈希。判断标准只有一条——这些提交有没有被别人拉走过。没有就可以放心 rebase,有就只能 merge。
配套的一条纪律是:主分支(main、master、release)永远只快进合并,别 rebase。合并前用 git pull --ff-only 而不是默认的 pull,它会在无法快进时直接报错,而不是悄悄生成一个合并提交,这能避免绝大部分「本地历史怎么多出一堆交叉线」的困惑。
12 条会丢东西的命令
表里标了「注意」的 12 条都属于删了就找不回来的类型。git reset --hard 和 git clean -fdx 丢掉的是从未提交过的内容,Git 里没有任何地方存着它们,reflog 也救不了。git stash drop 丢掉的暂存现场同样尴尬,它不属于任何分支,只能靠 git fsck --lost-found 去翻悬空对象,成功率不高。
会改写历史的(rebase、commit --amend、filter-repo)本身不丢内容,但会让别人的本地仓库和远程对不上,协作者必须重新克隆或做一次麻烦的复位。强推时坚持用 --force-with-lease 而不是 --force,前者会在远程被别人更新过时拒绝执行,这一个参数能挡掉最典型的那种事故。
这份表的适用边界
Git 2.23 之后官方把 checkout 的两种用途拆成了 git switch(切分支)和 git restore(恢复文件),表里两套命令都保留了,老版本系统上还能用。git filter-repo 是官方推荐替代 filter-branch 的独立工具,多数发行版的仓库里没有,需要单独装(pip install git-filter-repo 或 brew install git-filter-repo),表里列出的 filter-branch 用法在新项目里已经不建议再用。