Git 速查表 — 按任务分类的命令
按你想做的事整理 Git 命令:撤销上一次提交、重命名分支、删除远程分支。优先给出新式 switch/restore 命令并附经典写法,危险操作有醒目标记。
最后核对:2026-10-18 依据Git 2.56 的 git-scm.com 官方参考文档和 GitHub CLI 手册核对。来源:Git reference (git-scm.com/docs), git restore, git switch, git reset, git config, GitHub CLI manual。
初始配置(每台电脑一次)
加上 --global 时,配置写入 ~/.gitconfig。从 Git 2.46 起,官方文档的写法是 git config set / get / list;传统写法依然可用。
git config set --global user.name "Ana Lee" git config set --global user.email "ana@example.com"
传统写法:git config --global user.name "Ana Lee"
会记录在你的每一次提交中。请使用 Git 托管平台上登记的邮箱,这样提交才能关联到你的账号。
git config set --global init.defaultBranch main
传统写法:git config --global init.defaultBranch main
不设置的话,git init 仍会把第一个分支命名为 master(并输出一条提示)。
git config set --global core.editor "code --wait"
传统写法:git config --global core.editor "code --wait"
任何会阻塞直到文件关闭的命令都可以:"nano"、"vim"、"subl -n -w"。
git config set --global core.autocrlf true # Windows git config set --global core.autocrlf input # macOS, Linux
传统写法:git config --global core.autocrlf true
提交时统一为 LF,在 Windows 上检出时转为 CRLF。团队协作时,用包含 "* text=auto" 的 .gitattributes 文件比每人单独设置更可靠。
git --version
git switch 和 git restore 需要 2.23+,git config 子命令需要 2.46+。
创建仓库
git init
git init -b main # name the first branch会创建 .git 目录。在第一次提交前加好 .gitignore,避免构建产物和密钥被提交进去。
git clone https://github.com/owner/repo.git git clone git@github.com:owner/repo.git my-folder
下载完整历史,并把远程仓库设为 "origin"。第二种写法使用 SSH,并指定自定义文件夹名。
git clone --depth 1 https://github.com/owner/repo.git
跳过历史记录,适合 CI 和大型仓库。之后可用 git fetch --unshallow 补全历史。
git remote add origin git@github.com:owner/repo.git git push -u origin main
先在托管平台上创建空仓库(或使用下文的 gh repo create)。-u 会把 origin/main 记为上游分支。
暂存与提交
git status
git status -s # short form列出已暂存、未暂存和未跟踪的文件,并提示下一步可用的命令。
git add file.txt
git add . # everything in this folder and belowgit add -A 还会暂存整个仓库中的文件删除。
git add -p file.txt
逐个处理每处改动("hunk"):y 暂存,n 跳过,s 拆分,e 编辑。
git commit -m "Add login form"
git commit -am "Fix typo" # stage tracked files and commit-a 会自动包含已跟踪文件的修改和删除,但不包括新文件。
git mv old.txt new.txt git rm file.txt
两者都会自动暂存改动。Git 根据内容识别重命名,所以直接 mv 再 git add 也可以。
git rm --cached .env echo ".env" >> .gitignore
从下一次提交起将其移出仓库。它仍保留在之前的提交中:如果其中有密钥,请更换密钥。
分支
git branch git branch -a # include remote branches git branch -vv # show upstream and ahead/behind
当前分支以 * 标记。
git switch -c feature/login
传统写法:git checkout -b feature/login
从当前提交开始;如需从别处创建,加上起点:git switch -c hotfix origin/main。
git switch main
git switch - # back to the previous branch传统写法:git checkout main
如果只存在 origin/feature,git switch feature 会自动创建对应的本地跟踪分支。
git branch -m new-name # current branch
git branch -m old-name new-name只重命名本地分支。要同时重命名远程分支,请看下一条。
git branch -m old-name new-name git push -u origin new-name git push origin --delete old-name
远程没有重命名操作:推送新名称,再删除旧名称。基于旧名称的未合并拉取请求可能会被关闭;使用 GitHub 网页上的重命名按钮则会自动把它们指向新分支。
git branch -d feature/login
git branch -D feature/login # even if unmerged如果分支有未合并到其上游或 HEAD 的提交,-d 会拒绝删除;-D 则强制删除。
恢复方法: 未合并的提交仍在 reflog 中:运行 git reflog 找到分支末端,然后 git branch feature/login <sha>。
git push origin --delete feature/login
传统写法:git push origin :feature/login
队友在运行 git fetch --prune 之前仍会看到它。
恢复方法: 本地还有这个分支的人(或你自己通过 git reflog)可以把它推送回去。
git branch -u origin/main
git push -u origin HEAD # push current branch and track it传统写法:git branch --set-upstream-to=origin/main
不带参数的 git pull 和 git push 使用的就是上游分支。
git switch --detach a1b2c3d
git switch -c rescue # keep work made there传统写法:git checkout a1b2c3d
分离状态下的提交不属于任何分支;切走之前先创建分支,否则只能通过 reflog 找回。
合并、变基与拣选
git switch main
git merge feature/login
git merge --no-ff feature/login # always create a merge commit能快进时会快进;--no-ff 会在历史中保留分支结构。
git merge --squash feature/login git commit -m "Add login"
暂存合并后的全部改动,但不记录合并;之后该分支不会被标记为已合并。
git status # list conflicted files # edit the files, remove <<<<<<< ======= >>>>>>> markers git add file.txt git commit # or: git rebase --continue
整体采用某一方:git restore --ours file.txt 或 --theirs。变基时 "ours" 指的是被变基到的目标分支,与合并时正好相反。
git merge --abort
回到合并开始前的状态。
恢复方法: 已经解决的冲突会丢失。如果合并开始时有未提交的改动,--abort 可能无法还原它们,所以合并前请先提交或 stash。
git switch feature/login git rebase main
把你的提交在 main 之上重放,得到线性历史。解决冲突后 git add,再 git rebase --continue;--abort 放弃变基。
恢复方法: 刚变基完:git reset --hard ORIG_HEAD。之后:在 git reflog 中找到原来的分支末端。
git rebase -i HEAD~3
会打开一个列表:把 pick 改成 squash/fixup 合并提交,改成 reword 修改提交信息,改成 drop 删除提交,或调整行的顺序。
恢复方法: git reflog 会显示变基前的提交;git reset --hard <sha> 可还原。
git commit --fixup=a1b2c3d git rebase -i --autosquash a1b2c3d~1
变基时,fixup 提交会自动并入 a1b2c3d。
恢复方法: 与交互式变基相同:git reflog。
git pull --rebase
git config set --global pull.rebase true # make it the default把你的本地提交变基到拉取到的内容之上。
git cherry-pick a1b2c3d
git cherry-pick -x a1b2c3d # note the source in the message创建一个包含相同改动的新提交。范围写法:git cherry-pick A..B(不含 A)。
远程仓库:fetch、pull、push
git remote -v git remote set-url origin git@github.com:owner/repo.git
set-url 可把克隆从 HTTPS 切换到 SSH(或指向改名后的仓库)。
git fetch
git fetch --prune # also drop deleted remote branches只更新 origin/*;你的分支保持不变。
git pull
相当于 git fetch 加 merge(如果设置了 pull.rebase,则是 rebase)。
git push
git push -u origin HEAD # first push of a new branch
git config set --global push.autoSetupRemote true开启 push.autoSetupRemote(Git 2.37+)后,在新分支上直接 git push 就会自动设置上游。
git push --force-with-lease
与 --force 不同,如果远程有你还没 fetch 的提交,它会拒绝推送。如有后台自动 fetch,再加上 --force-if-includes(Git 2.30+)更保险。
恢复方法: 被覆盖的远程提交仍保留在曾拥有它们的人的 reflog 中,GitHub 也会在一段时间内保留,可通过 SHA 访问。
git remote add upstream https://github.com/original/repo.git git fetch upstream git switch main git merge upstream/main
也可以用 GitHub CLI:gh repo sync。
撤销操作
根据错误所在位置选择:工作区、暂存区、本地提交,还是已推送的提交。凡是提交过的内容,通常都能用 git reflog 找回;被丢弃的未提交修改则无法找回。
git reset --soft HEAD~1
提交消失,改动仍处于暂存状态,可以重新提交。如果想让改动变为未暂存,改用 git reset HEAD~1(不带 --soft)。
恢复方法: git reset ORIG_HEAD 可以把提交找回来。如果已经推送,请改用 git revert。
git reset --hard HEAD~1
把分支回退一个提交,并将所有已跟踪文件重置为与之一致。
恢复方法: 该提交仍在 git reflog 中(不可达的记录默认 30 天后过期):git reset --hard HEAD@{1}。已跟踪文件中未提交的改动则永久丢失。
git revert a1b2c3d
git revert HEAD # the latest commit新增一个反向提交来抵消旧提交,不会改动其他人的历史。这是共享分支上安全的撤销方式。
git revert -m 1 <merge-sha>
-m 1 保留第一个父提交(通常是 main)。以后要重新合并该分支,需要先撤销这次 revert。
git commit --amend -m "Better message"
用新提交替换上次提交。推送前随意修改;推送后需要 --force-with-lease。
恢复方法: git reset --soft HEAD@{1} 可回到 amend 之前的提交。
git add forgotten.txt git commit --amend --no-edit
保留提交信息,添加文件。
恢复方法: git reset --soft HEAD@{1}。
git restore --staged file.txt
git restore --staged . # everything传统写法:git reset HEAD file.txt
改动仍留在工作区,只是撤销了暂存。
git restore file.txt
传统写法:git checkout -- file.txt
把文件恢复为暂存区的版本(如果没有暂存,则恢复为上次提交的版本)。
恢复方法: 无法通过 Git 恢复:这些修改从未提交。编辑器的本地历史可能还保留着。
git restore --staged --worktree .
git clean -fd # also delete untracked files传统写法:git reset --hard
git clean -fd
回到上次提交的状态。先运行 git clean -n 看看哪些文件会被删除。
恢复方法: 无法恢复:未提交的修改和未跟踪的文件都会被删除。可撤回的替代方案是 git stash -u。
git restore file.txt # deletion not committed git restore --source=a1b2c3d~1 file.txt # deleted in commit a1b2c3d
传统写法:git checkout a1b2c3d~1 -- file.txt
用 git log --diff-filter=D -- file.txt 找到删除它的提交。
git restore --source=main -- config.yml
传统写法:git checkout main -- config.yml
只覆盖工作区副本;加上 --staged --worktree 可同时暂存。只想查看的话:git show main:config.yml。
恢复方法: 该文件未提交的修改会被覆盖。
git reflog git branch rescued a1b2c3d
reflog 记录了 HEAD 去过的每个位置。找到出错前的 SHA,在上面创建一个分支即可。
git reset --hard ORIG_HEAD
merge、rebase 和 reset 会把 ORIG_HEAD 设为操作前所在的位置。下一次执行这类命令时它会被覆盖。
恢复方法: git reflog 中仍能找到这个合并提交。
git reflog # find "rebase (start)"; the entry below it is the old tip
git reset --hard HEAD@{5}刚变基完时,git reset --hard ORIG_HEAD 效果相同。
恢复方法: --hard 会丢弃未提交的改动;请先 stash。
git reset --hard HEAD@{1}HEAD@{1} 是 HEAD 上一次移动前的位置。只对已提交的内容有效。
git filter-repo --invert-paths --path secrets.env
git filter-repo 是独立工具(pip install git-filter-repo),git-filter-branch 文档推荐使用它。操作后所有克隆都必须重新克隆。无论如何都要更换密钥:从推送那一刻起它就已经公开了。
恢复方法: filter-repo 需要在全新的克隆上运行;确认无误之前保留旧克隆。
Stash 暂存
git stash
git stash push -m "half-done login"
git stash -u # include untracked files保存已跟踪文件的改动并清理工作区,方便你切换分支。
git stash pop # apply and drop git stash apply stash@{1} # apply, keep the stash
可能出现冲突;使用 pop 时,如果应用失败,stash 会被保留。
git stash list
git stash show -p stash@{0}最新的在前;stash@{0} 是最近一次。
git stash push -- src/login.ts
git stash push --staged # only what is staged (2.35+)指定路径的 stash 不会动其他文件。
git stash branch feature/login stash@{0}在 stash 时所在的提交上创建分支,应用并删除该 stash;可避免冲突。
git stash drop stash@{0}
git stash clearclear 会删除所有 stash。
恢复方法: 被删除的 stash 在垃圾回收前仍是不可达提交:git fsck --unreachable | grep commit,然后 git stash apply <sha>。
历史与差异
git log --oneline --graph --all
每个提交一行,并显示分支结构。在很旧的 Git 上需加 --decorate 才能看到分支名。
git log --follow -p -- path/file.txt
--follow 可跨越重命名继续追踪;-p 显示每次改动。
git log -S "functionName" --oneline git log -G "regex" --oneline
-S 查找出现次数发生变化的提交;-G 用正则表达式匹配任意改动的行。
git log --author="Ana" --since="2 weeks ago" --oneline
还有 --until、按提交信息筛选的 --grep="fix",以及 main..feature(在 feature 上但不在 main 上的提交)。
git show a1b2c3d git show a1b2c3d:path/file.txt
第二种写法会输出文件在该提交中的内容,不会影响你的工作副本。
git diff # unstaged git diff --staged # staged, i.e. what will be committed
--stat 按文件汇总;--word-diff 更适合文字内容。
git diff main...feature # changes on feature since it branched git diff main feature # the two tips directly
三个点表示与合并基础比较,也就是拉取请求中显示的内容。
git blame -L 10,20 path/file.txt
加 -w 忽略空白,加 -C 追踪从其他文件移动过来的行。
git bisect start git bisect bad # current commit is broken git bisect good v1.4.0 # this one worked # test, then mark each step good or bad git bisect reset
二分查找:大约 log2(n) 步。git bisect run ./test.sh 可以自动完成。
git grep -n "TODO"
在大型仓库中比 grep 更快,并会跳过被忽略的文件。加上提交即可搜索旧版本。
标签与发布
git tag -a v1.2.0 -m "Release 1.2.0"
git tag -a v1.1.1 a1b2c3d -m "Hotfix" # tag an older commit附注标签(-a)会保存作者、日期和说明,发布版本建议用它。只写 git tag v1.2.0 会创建轻量标签。
git tag -d v1.2.0 git push origin --delete v1.2.0
不要重复使用已删除的发布标签名:其他克隆仍保留着旧标签。
恢复方法: 被标记的提交不受影响;在其上重新创建标签即可。
子模块与工作树
git submodule add https://github.com/owner/lib.git vendor/lib git commit -m "Add lib submodule"
在 .gitmodules 中记录 URL,并锁定另一个仓库的某个确切提交。
git clone --recurse-submodules <url>
git submodule update --init --recursive # already cloned不运行这一步,子模块文件夹就是空的。
git submodule update --remote git commit -am "Bump submodules"
拉取每个子模块所跟踪的分支;然后在父仓库中提交新的锁定版本。
git worktree add ../repo-hotfix hotfix git worktree add -b review ../repo-review origin/main
共享同一仓库的第二个工作目录;无需 stash,也无需再克隆一份。
git worktree list
git worktree remove ../repo-hotfix
git worktree prune # forget folders deleted by hand如果工作树中有未提交的改动,remove 会拒绝执行(用 --force 强制)。
清理
git clean -n -d
运行 git clean -f 之前一定要先运行这条。
git clean -fd # untracked files and folders git clean -fdx # also ignored files (build output, .env!)
-x 还会删除被忽略的文件,包括 .env 等本地配置。
恢复方法: 无法恢复:这些文件从未进入 Git。
git branch --merged main git branch -d branch-a branch-b
先检查列表;-d 会拒绝删除未合并的分支,所以可以放心尝试。
git fetch --prune git config set --global fetch.prune true
删除那些在服务器上已被删除的分支对应的 origin/* 引用。
git maintenance start git gc
maintenance start 会安排后台的预取、commit-graph 和重新打包任务;gc 则立即打包对象并清理不可达对象。
配置与别名
git config list --show-origin
传统写法:git config --list --show-origin
显示系统、全局和仓库级别的配置值,以及每项所在的文件。
git config set --global alias.st "status -s" git config set --global alias.lg "log --oneline --graph --all"
传统写法:git config --global alias.st "status -s"
之后即可使用 git st 和 git lg。以 ! 开头可运行 shell 命令:alias.root "!pwd"。
git config set --global pull.rebase true git config set --global push.autoSetupRemote true git config set --global rerere.enabled true git config set --global merge.conflictStyle zdiff3 git config set --global diff.algorithm histogram
传统写法:git config --global pull.rebase true
pull 时变基;首次推送时自动设置上游(2.37+);记住冲突的解决方式;冲突中显示共同祖先(2.35+);更清晰的 diff。
git config set --global core.excludesFile ~/.gitignore_global
传统写法:git config --global core.excludesFile ~/.gitignore_global
用于系统和编辑器产生的杂项文件(.DS_Store、.idea/)。项目相关的规则应写在仓库的 .gitignore 中。
GitHub CLI(gh)基础
gh 是 GitHub 官方的命令行工具,需要在 Git 之外单独安装。
gh auth login
gh auth setup-git # let git use gh for HTTPS credentials会打开浏览器或使用令牌登录;支持 github.com 和 GitHub Enterprise。
gh repo create my-app --private --source=. --push
创建仓库,将其添加为 origin,并推送当前分支。
gh repo clone owner/repo
如果是 fork,还会把父仓库添加为 upstream 远程仓库。
gh pr create --fill gh pr create --draft --title "WIP: login" --body "…"
--fill 使用提交信息作为标题和正文。
gh pr checkout 123
拉取 PR 分支(包括来自 fork 的)并切换过去。
gh pr list gh pr view 123 --web gh pr merge 123 --squash --delete-branch
gh pr status 显示与你相关的 PR。
gh issue create --title "Bug: …" --body "…" gh issue list --assignee @me
gh issue view 42 --comments 可在终端中阅读讨论。
gh run list gh run watch
gh run view --log-failed 只输出失败的步骤。
需要一个初始 .gitignore?用.gitignore 生成器。想在 Git 之外比较文件的两个版本?文本差异对比工具可以并排显示差异。
这是一份静态参考:搜索在浏览器中进行,你输入的内容不会发送到任何地方。 浏览全部免费工具.
发现问题,或者觉得哪里可以更好?每条消息我们都会阅读,并尽快修复。
这份 Git 速查表按任务而不是按命令整理,因为没有人会去搜“git reset --soft”,大家搜的是“撤销上次提交”。找到你要做的事,复制命令,再看一句话说明它会改变什么。搜索会优先匹配任务,所以输入“删除远程分支”或“重命名分支”就能直接跳到对应条目。
会改写历史或丢弃工作的命令都有标记,并附有可恢复内容的说明:几乎所有曾经提交过的内容都能用 git reflog 找回,而用 restore、reset --hard 或 clean 丢弃的未提交修改则彻底没了。如果 Git 现在有更清晰的命令(2.23 起的 git switch 和 git restore,2.46 起的 git config set 和 list),会优先列出新命令并在旁边附上经典写法,无论你的团队是去年还是 2010 年学的 Git 都能用。内容已对照 git-scm.com 上 Git 2.56 的参考文档核实。
使用方法
- 在搜索框中输入你想做的事,如“撤销上次提交”“取消暂存”或“合并多个提交”,或点击常用任务之一。
- 运行任何命令前先看标记:琥珀色表示命令会改写历史,红色表示可能丢弃工作。恢复说明会告诉你如何还原。
- 点击“复制命令”。复制内容会去掉 # 注释,可以干净地粘贴到终端;记得把 a1b2c3d 或 feature/login 等占位内容换成你自己的。
- 用每个任务旁的 # 链接分享某个具体答案,或把整张速查表打印为双栏 PDF。
常见问题
Git 如何撤销上一次提交?
如果还没推送,git reset --soft HEAD~1 会删除该提交并把改动保留在暂存区,git reset HEAD~1 则把改动保留为未暂存状态。git reset --hard HEAD~1 会连提交带改动一起删除。如果该提交已推送到共享分支,请改用 git revert HEAD,它会新增一个撤销该提交的提交,不会改写任何人的历史。
git reset、git restore 和 git revert 有什么区别?
git restore 修改的是文件:丢弃工作区中的修改或取消暂存,从不移动分支。git reset 把当前分支移动到另一个提交(加上 --hard 还会覆盖你的文件),所以会改写历史。git revert 新建一个提交,内容与之前某个提交相反;历史只增不减,因此在别人也在用的分支上,它是安全的选择。
如何在本地和远程重命名 Git 分支?
git branch -m new-name 重命名当前所在的分支(重命名其他分支用 git branch -m old new)。远程仓库没有重命名操作,所以要用 git push -u origin new-name 推送新名称,再用 git push origin --delete old-name 删除旧分支。在 GitHub 上,通过网页界面重命名分支还会自动更新已打开拉取请求的目标分支。
应该用 git switch 还是 git checkout?
都可以。git checkout 身兼两项互不相关的工作:切换分支和恢复文件,所以 Git 2.23 把它拆分成了 git switch 和 git restore。新命令更清晰,也更不容易误用(git checkout -- file 会悄无声息地丢弃修改),所以本速查表优先列出新命令。git checkout 并未被弃用,这里的每条命令都附有经典写法。
git reset --hard 之后还能恢复提交吗?
通常可以。运行 git reflog,找到 reset 之前的那一行,然后运行 git reset --hard HEAD@{n},或在那个 SHA 上新建一个分支。默认情况下,一旦没有其他引用指向某个提交,它仍可通过 reflog 访问 30 天。无法恢复的是未提交的工作:从未提交或 stash 过的修改会被永久覆盖。
git push --force-with-lease 有什么作用?
只有当远程分支仍指向你上次 fetch 时看到的位置,它才会覆盖远程分支。如果在此期间有人推送过,推送会被拒绝,而不是像单纯的 --force 那样悄悄删掉别人的提交。在已推送的分支上做了 rebase 或 amend 之后,请使用它。
该用哪个撤销命令?看改动在哪里
• 修改了文件,想放弃修改:git restore file。无法恢复,因为从未提交过。
• 误暂存了内容:git restore --staged file。不会丢失任何东西;修改仍保留在文件中。
• 已提交但未推送:用 git reset --soft HEAD~1 重新提交,或用 git commit --amend 直接修正。
• 已提交并推送到共享分支:git revert <sha>。不要 reset 别人已经拉取过的分支。
• 丢失了提交、分支或糟糕 rebase 的结果:先 git reflog,再 git branch rescued <sha>。
背后的原则:只要提交还只属于你自己,改写它们就没问题;一旦共享出去,就成了所有人的麻烦。
merge 还是 rebase?
两者都能把一个分支的改动带到另一个分支。merge 会用一个有两个父提交的合并提交,记录两段历史的汇合;不会改写任何东西,所以在共享分支上始终是安全的。rebase 则把你的提交在另一个分支之上重放,形成一条直线式的历史,就像你从最新提交开始工作一样,但它会生成新的提交 ID,所有已经拿到旧提交的人都必须处理差异。
一种常见的团队约定:把自己的功能分支 rebase 到 main 上以保持同步(git pull --rebase 或 git rebase main),完成后通过拉取请求把分支 merge 进 main。squash 合并会让每个功能在 main 上只留一个提交;普通合并则保留所有提交和分支形态。每个仓库选定一种方式,并在托管平台的设置中固定下来,让历史保持一致。
值得修改默认值的 Git 设置
• pull.rebase true:git pull 时使用 rebase,而不是每次同步都生成合并提交。
• push.autoSetupRemote true(Git 2.37+):新分支第一次 git push 时自动设置上游,无需 -u。
• merge.conflictStyle zdiff3(Git 2.35+):冲突标记中包含共同祖先,大多数冲突一看就明白。
• rerere.enabled true:Git 会记住你如何解决某个冲突,在 rebase 中再次遇到相同冲突时自动重用。
• fetch.prune true:服务器上已删除的远程分支,在下次 fetch 时会从本地消失。
• init.defaultBranch main:新仓库默认从 main 分支开始。
相关免费工具
- .gitignore 生成器 — 把语言、框架、编辑器和操作系统的 .gitignore 模板合并成一个干净的文件。
- 文本对比(Diff) — 比较文本、代码或 JSON 文件的两个版本,准确看出哪些行、词和字符发生了变化。
- Markdown 速查表 — 每个 Markdown 元素都附源码和渲染预览,涵盖扩展语法(表格、任务列表、脚注、数学公式、Mermaid、提示框),另有 9 个平台的兼容性对照表和实时练习区。
- 正则表达式速查表 — 每个正则表达式语法元素都附可运行的示例,标明在 JavaScript、PCRE/PHP、Python、Go、Java 和 .NET 中的支持情况,并提供一键在正则测试工具中试用的链接。