git init在当前目录初始化一个空的 git 仓库。
⚠ 常见坑: 已经是 git 仓库的目录里再 init 会嵌套出新的 .git,工具会混乱。先 git status 确认。
git init
git init my-project
Git 命令速查:可搜可分类,每条带说明、常见坑、真实例子。
git init在当前目录初始化一个空的 git 仓库。
⚠ 常见坑: 已经是 git 仓库的目录里再 init 会嵌套出新的 .git,工具会混乱。先 git status 确认。
git init
git init my-project
git clone <url>把远端仓库连同完整历史克隆到本地新目录。
⚠ 常见坑: 巨型仓库可加 --depth=1 浅克隆;浅克隆不能 push --amend,要先 git fetch --unshallow。
git clone https://github.com/user/repo.git
git clone --depth=1 https://github.com/user/repo.git
git status显示工作区已改、已暂存和未跟踪的文件。
git status
git status -s
git add <file>把文件(或用 . 全部)加入下一次提交的暂存区。
⚠ 常见坑: `git add .` 在子目录里只暂存子树;要全仓库(含删除)用 git add -A。
git add src/index.ts
git add .
git add -A
git add -p
git commit -m "msg"把已暂存的改动以指定信息提交一次。
⚠ 常见坑: 忘记 add 会报“no changes”;-am 只暂存已跟踪文件,新文件不会被带进去。
git commit -m "fix: handle null user"
git commit -am "wip"
git commit --amend用新的提交替换最后一次提交(可改信息或内容)。
⚠ 常见坑: 改已 push 的提交会改写历史,协作者必须强制 pull,否则冲突。
git commit --amend
git commit --amend --no-edit
git commit --amend -m "better message"
git push把当前分支的本地提交推送到对应远端分支。
git push
git push origin main
git push -u origin <branch>把新本地分支推上远端并设置为跟踪分支(之后 git push 默认推这里)。
⚠ 常见坑: 不加 -u 的话,之后 git push 还要重新指定 remote 和分支名。
git push -u origin feature/login
git pull从跟踪的远端分支拉取更新并合并到当前分支。
⚠ 常见坑: 默认 pull = fetch + merge,会产生“merge of remote-tracking branch”这种空合并提交。多数团队偏好 pull --rebase。
git pull
git pull --rebase
git fetch从远端拉新提交和引用到本地,但不会合并进任何分支。
git fetch
git fetch origin
git fetch --all --prune
git clone --depth=1 <url>只克隆最新一个提交(无历史)。CI 构建里能省大量带宽和时间。
⚠ 常见坑: 浅克隆不能 push、rebase,需先 git fetch --unshallow。
git clone --depth=1 https://github.com/torvalds/linux.git
git mv <src> <dst>重命名或移动文件,并一次性暂存改动。
git mv old-name.ts new-name.ts
git log -n 5只显示最近 5 个提交(任意数字皆可)。
git log -n 5
git log -3 --oneline
git tag <name>在当前提交创建轻量 tag。用 -a 创建带消息和打 tag 人的注释 tag。
⚠ 常见坑: 发布版本推荐用注释 tag(git tag -a v1.0 -m "..."),轻量 tag 不存元信息。
git tag v1.0.0
git tag -a v1.0.0 -m "first stable release"
git tag -d <name>删除本地 tag。要同时删远端 tag:git push --delete origin <name>。
git tag -d v1.0.0
git push --delete origin v1.0.0
git rm <file>从工作区删除文件并暂存这次删除。
⚠ 常见坑: 只想取消跟踪不要真删本地文件,用 git rm --cached(比如刚加进 .gitignore 的文件)。
git rm secret.env
git rm --cached config.local.json
git commit提交已暂存的改动,并打开配置好的编辑器来写提交信息。
⚠ 常见坑: 编辑器里留空信息会中止本次提交,写点内容再保存才会真正提交。
git commit
git commit -v
git add -p逐块交互式暂存改动,挑文件里的哪些片段进这次提交。
⚠ 常见坑: 太大无法再拆的块会整块出现,按 e 手动编辑,或更早按 s 拆开。
git add -p
git add -p src/index.ts
git restore --source=<ref> <file>把文件还原成它在某个提交、分支或 tag 时的样子。
git restore --source=HEAD~2 src/index.ts
git restore --source=main config.json
git rm -r --cached <dir>停止跟踪整个目录但不删本地文件。改完 .gitignore 后常用。
git rm -r --cached node_modules
git rm -r --cached dist && git commit -m "chore: ignore dist"
git commit --allow-empty创建一个没有任何改动的提交。常用于触发 CI 或标记里程碑。
git commit --allow-empty -m "ci: trigger rebuild"
git tag -l <pattern>列出 tag,可用通配符过滤。
git tag -l
git tag -l "v1.*"
git tag -l --sort=-version:refname
git show <tag>显示一个注释 tag,包括它的信息、打 tag 人和它指向的提交。
git show v1.0.0
git describe基于最近的 tag 给当前提交生成可读名字(如 v1.0-14-g2414721)。
⚠ 常见坑: 没有可达的注释 tag 会报 "no names found",加 --tags 把轻量 tag 也算进来。
git describe
git describe --tags
git describe --tags --dirty
git archive把某个提交的文件树导出成 tar 或 zip,不含 .git 目录。
git archive --format=zip --output=release.zip HEAD
git archive main | tar -x -C /tmp/snapshot
git branch列出本地分支;带 * 的是当前分支。
git branch
git branch -a
git branch -vv
git branch <name>基于当前 HEAD 创建新分支,但不切换过去。
git branch feature/login
git branch -d <name>安全删除本地分支(有未合并提交会拒绝)。
⚠ 常见坑: 强删未合并分支用 -D(大写),删了只能靠 reflog 找回。
git branch -d feature/done
git branch -D feature/wip
git branch -m <new>重命名当前分支。
git branch -m main
git branch -m old-name new-name
git checkout <branch>切换到已有分支(老命令;新命令是 git switch)。
⚠ 常见坑: `git checkout <file>` 和 `git checkout <branch>` 是两个完全不同的操作却同名,容易误操作。改用 git switch / git restore。
git checkout main
git checkout -
git checkout -b <new>基于当前 HEAD 创建新分支并切过去(一步完成)。
git checkout -b feature/login
git checkout -b hotfix origin/main
git switch <branch>切换到已有分支。git checkout <分支> 的现代替代。
git switch main
git switch -
git switch -c <new>创建并切换到新分支。git checkout -b 的现代替代。
git switch -c feature/login
git switch -c hotfix origin/main
git merge <branch>把指定分支合并到当前分支。
⚠ 常见坑: 默认 merge 可 fast-forward 时也会快进。要强制不快进用 --no-ff,要拒绝非 FF 用 --ff-only。
git merge feature/login
git merge --no-ff feature/login
git merge --ff-only origin/main
git merge --abort中止进行中的 merge,回到 merge 之前的状态。
git merge --abort
git rebase <branch>把当前分支的提交搬到 <branch> 顶部重放。历史线性,但所有 commit ID 会变。
⚠ 常见坑: 已 push 到共享分支的提交不要 rebase,协作者每次 pull 都冲突。
git rebase main
git rebase origin/main
git rebase --abort中止进行中的 rebase,回到 rebase 前的状态。
git rebase --abort
git rebase --continuerebase 冲突解决后继续重放剩余提交。
git add resolved-file.ts && git rebase --continue
git cherry-pick <sha>把指定提交的改动作为新提交应用到当前分支。
⚠ 常见坑: cherry-pick 出来的提交 SHA 是新的;同一改动 cherry-pick 两次会有重复逻辑。
git cherry-pick a1b2c3d
git cherry-pick a1b2c3d..f4e5d6c
git cherry-pick -x a1b2c3d
git branch -a列出所有分支(本地 + 远程跟踪)。
git branch -a
git branch --merged列出已完全合并到当前分支的本地分支,可放心删除。
git branch --merged main
git branch --merged | grep -v "\*" | xargs git branch -d
git switch -切回上一个所在的分支(相当于分支版的 cd -)。
git switch -
git checkout -
git switch --detach <ref>有意进入 detached HEAD 去 checkout 某个提交或 tag,比如测试旧版本。
git switch --detach v1.0.0
git switch --detach HEAD~3
git branch -f <name> <ref>不切换的情况下,把已有分支指针强行移到另一个提交。
⚠ 常见坑: 不能强移你正待着的当前分支,先切走,或改用 git reset。
git branch -f staging main
git branch -f release HEAD~2
git branch --no-merged列出还没合并进当前分支的分支,这些里面有独有的工作没收。
git branch --no-merged
git branch --no-merged main
git branch --show-current只打印当前分支名(detached HEAD 时为空)。适合写脚本。
git branch --show-current
BR=$(git branch --show-current)
git merge --no-commit <branch>执行合并但停在提交之前,方便你先检查或微调结果。
git merge --no-commit --no-ff feature/login
git rebase --onto <newbase> <upstream> <branch>只把 <upstream>..<branch> 之间的提交重放到 <newbase> 上。精准搬一段分支。
⚠ 常见坑: 三个 ref 顺序搞错会悄悄丢提交或重复提交,做完用 git log --oneline 核对。
git rebase --onto main feature-base feature/login
git rebase --skiprebase 时跳过当前这个提交(比如它的改动上游已经有了)。
⚠ 常见坑: skip 会彻底丢掉这个提交,确认改动已存在再跳。
git rebase --skip
git merge-base <a> <b>打印两个提交的最佳共同祖先,也就是两个分支分叉的那一点。
git merge-base main feature/login
git merge-base HEAD origin/main
git cherry-pick --continuecherry-pick 冲突解决后,继续把这个提交应用完。
git add resolved.ts && git cherry-pick --continue
git cherry-pick --abort
git cherry-pick -n <sha>把某提交的改动应用到工作区和暂存区但不提交,方便把几个攒一起。
git cherry-pick -n a1b2c3d
git cherry-pick --no-commit a1b2c3d f4e5d6c
git reset HEAD <file>把文件从暂存区撤出(工作区改动保留)。
git reset HEAD src/index.ts
git reset HEAD .
git reset --soft HEAD~1撤销最后一次提交,但改动留在暂存区。最“无害”的 reset。
git reset --soft HEAD~1
git reset --mixed HEAD~1撤销最后一次提交并取消暂存,但工作区改动保留(reset 默认行为)。
git reset HEAD~1
git reset --mixed HEAD~1
git reset --hard HEAD~1彻底丢弃最后一次提交,并清空对应的工作区改动。破坏性操作。
⚠ 常见坑: 没 commit 又不在 reflog 里的东西就真没了。可能后悔就先 git stash。
git reset --hard HEAD~1
git reset --hard origin/main
git revert <sha>生成一个新提交,把 <sha> 的改动反向应用。共享分支安全,不改写历史。
git revert a1b2c3d
git revert HEAD
git revert -m 1 <merge-sha>
git restore <file>丢弃文件的未暂存改动(git checkout -- 的现代替代)。
git restore src/broken.ts
git restore .
git restore --staged <file>把文件从暂存区撤出但保留工作区改动(git reset HEAD <file> 的现代替代)。
git restore --staged src/index.ts
git stash把未提交改动(已暂存 + 未暂存)压栈,并把工作区还原。
⚠ 常见坑: 默认 git stash 不会包含未跟踪的新文件;要包含用 git stash -u。
git stash
git stash -u
git stash push -m "WIP login form"
git stash pop把最近一次 stash 应用回工作区并从栈里移除。
⚠ 常见坑: pop 冲突时 stash 不会被弹出,解决冲突后要手动 git stash drop。
git stash pop
git stash pop stash@{2}git stash list列出所有 stash,含索引和消息。
git stash list
git stash drop删除某个 stash 而不应用它。
git stash drop
git stash drop stash@{1}git reflog查看 HEAD 的本地移动历史。找回丢失提交/分支的救命稻草。
⚠ 常见坑: reflog 只存在本地,不会跟随 push/clone 走。默认 90 天过期。
git reflog
git reset --hard HEAD@{1}git clean -fd删除工作区里未跟踪的文件 (-f) 和目录 (-d)。
⚠ 常见坑: 不可逆。先用 git clean -nfd 干跑看会删什么。
git clean -nfd
git clean -fd
git clean -fdx
git restore --staged --worktree <file>同时丢弃文件在暂存区和工作区的改动,把它还原到 HEAD。
⚠ 常见坑: 未暂存的改动会真没,工作区状态没有 reflog 可救。
git restore --staged --worktree src/broken.ts
git stash apply应用某个 stash 但保留在栈里(和 pop 不同)。适合把同一 stash 应用到多个分支。
git stash apply
git stash apply stash@{1}git stash branch <name>从 stash 当初的基准提交建一个新分支并在那里应用 stash。解决 "stash 应用不干净" 的最佳办法。
git stash branch wip-login stash@{0}git stash show -p在决定应用还是丢弃前,先看 stash 的完整 diff。
git stash show -p
git stash show -p stash@{1}git stash clear一次性删除所有 stash,没有二次确认。
⚠ 常见坑: 清掉的 stash 普通 reflog 看不到,靠 git fsck --unreachable 找回很麻烦,想清楚再清。
git stash clear
git reset --hard <sha>把当前分支移到 <sha>,工作区也对齐成那个样子,之后的全丢。
⚠ 常见坑: 未提交的改动会被销毁。分支原来的位置在 git reflog 里大约保留 90 天。
git reset --hard a1b2c3d
git reset --hard origin/main
git revert --no-commit <sha>把某提交的反向改动暂存但不提交,方便把几个 revert 合成一个提交。
git revert --no-commit a1b2c3d
git revert -n HEAD~3..HEAD && git commit -m "revert last 3"
git revert --abort中止进行中的 revert(比如多提交 revert 撞上冲突)。
git revert --abort
git revert --continue
git clean -i交互式挑哪些未跟踪文件要删,而不是 -f 一把全清。
git clean -i
git clean -id
git checkout <sha> -- <file>从某个旧提交里取出单个文件到工作区(和暂存区),不动其他东西。
git checkout HEAD~3 -- src/config.ts
git checkout v1.0 -- README.md
git reset --merge类似 --hard 的 reset,但保留与暂存区不同的工作区改动。坏合并后更安全。
git reset --merge
git reset --merge ORIG_HEAD
git remote -v列出所有远端,含 fetch 和 push 的 URL。
git remote -v
git remote add <name> <url>用指定短名添加一个新远端(一般是 origin 或 upstream)。
git remote add origin https://github.com/me/repo.git
git remote add upstream https://github.com/orig/repo.git
git remote set-url <name> <url>修改已有远端的 URL(例如从 HTTPS 切到 SSH)。
git remote set-url origin git@github.com:me/repo.git
git remote rename <old> <new>重命名一个远端。
git remote rename origin github
git remote remove <name>彻底移除一个远端配置(不会删远端仓库本身)。
git remote remove old-upstream
git fetch --prune从远端拉取,并清理那些远端已删的远程跟踪分支。
git fetch --prune
git fetch -p origin
git pull --rebase从远端拉取并把本地提交 rebase 到上面,历史线性,没有 merge commit。
⚠ 常见坑: 远端有不相关改动导致 rebase 失败时,用 git rebase --abort 退回去。
git pull --rebase
git config --global pull.rebase true
git push --tags把本地 tag 推到远端(普通 push 不会带上 tag)。
git push --tags
git push origin v1.2.0
git push --delete origin <branch>删除远端的某个分支。
git push --delete origin feature/old
git push origin :feature/old
git ls-remote <url>不克隆即可列出远端的 refs(分支、tag)。下载前先看仓库情况很有用。
git ls-remote https://github.com/torvalds/linux.git
git ls-remote --heads origin
git push origin HEAD把当前分支推到同名的远端分支,不用把分支名打两遍。
git push origin HEAD
git push -u origin HEAD
git push --set-upstream origin HEAD一次性推当前分支并设置 upstream,新分支第一次推也行。
git push --set-upstream origin HEAD
git branch --set-upstream-to=<remote>/<branch>设置或修改当前本地分支跟踪哪个远端分支,无需推送。
git branch --set-upstream-to=origin/main
git branch -u origin/develop
git remote show <name>显示某个远端的详细信息:URL、跟踪分支、哪些是最新哪些过期。
git remote show origin
git remote prune <name>删除远端已不存在的本地远程跟踪引用,但不拉新提交。
git remote prune origin
git remote prune origin --dry-run
git fetch <remote> <branch>只从远端拉某一个分支到 FETCH_HEAD。
git fetch origin main
git fetch upstream release/2.0
git fetch <remote> <pr-ref>通过 refs/pull 引用直接拉某个 GitHub PR 分支,再 checkout 出来。
git fetch origin pull/42/head:pr-42
git switch pr-42
git push --force-with-lease=<ref>:<expected>强推,但仅当远端 ref 还精确指向你预期的 SHA 时。最严格的安全强推。
git push --force-with-lease=main:a1b2c3d origin main
git push --all一条命令把所有本地分支推到远端。
⚠ 常见坑: 它会把没成型的实验分支也推上去,最好还是显式逐个推。
git push --all origin
git remote get-url <name>打印某个远端的 URL(比解析 git remote -v 更适合脚本)。
git remote get-url origin
git remote get-url --push origin
git push --force-with-lease强推,但仅当远端 tip 还是你上次看到的状态。安全版强推。
⚠ 常见坑: --force 会无声覆盖同事的工作;共享分支永远用 --force-with-lease。
git push --force-with-lease
git push --force-with-lease origin feature/login
git rebase -i HEAD~N交互式改写最近 N 个提交:reorder / squash / fixup / reword / drop。
⚠ 常见坑: 改写已 push 的提交 = 改写历史。只在自己未 PR 的分支上做。
git rebase -i HEAD~5
git rebase -i main
git commit --fixup=<sha>生成一个针对 <sha> 的 fixup 提交。配合 git rebase -i --autosquash 会自动合到对应位置。
git commit --fixup=a1b2c3d
git rebase -i --autosquash main
git merge --squash <branch>把 <branch> 的所有提交压成一个未提交的暂存改动,由你写一条总结提交。
git merge --squash feature/login
git commit -m "feat: login flow"
git format-patch <branch>为自 <branch> 起的每个提交生成 .patch 文件。用于把补丁邮件发给邮件列表(Linux 内核风格)。
git format-patch main
git format-patch -1 HEAD
git am <patch>把 format-patch 生成的邮件式补丁作为提交应用上去。
git am 0001-fix-bug.patch
git request-pull <start> <url>生成变更摘要,请上游维护者从你这里 pull(GitHub 之前的协作流程)。
git request-pull v1.0 https://github.com/me/repo feature-x
git pull --rebase --autostash自动 stash 脏工作区 → pull --rebase → 自动 unstash。日常 pull 的好别名。
git pull --rebase --autostash
git config --global rebase.autoStash true
git worktree add <path> <branch>把另一个分支 checkout 到独立的工作目录,两个分支并行开发不用 stash。
⚠ 常见坑: worktree 共享同一个 .git,reflog/index 操作仍互相影响。用 git worktree list 查看。
git worktree add ../hotfix hotfix/login
git worktree list
git worktree remove ../hotfix
git commit -s在提交信息里追加 Signed-off-by 行,很多开源项目的 DCO 要求这个。
git commit -s -m "fix: null guard"
git commit --signoff --amend
git commit -S用 GPG 给提交签名,让作者身份可被密码学验证(就是那个 Verified 徽章)。
⚠ 常见坑: 要先配好 user.signingkey 和 gpg/ssh,否则提交会报 "gpg failed to sign"。
git commit -S -m "release: v2.0"
git config --global commit.gpgsign true
git rebase -i --autosquash <base>交互式 rebase,自动把 fixup!/squash! 提交排到对应目标旁边。
git rebase -i --autosquash main
git config --global rebase.autoSquash true
git commit --squash=<sha>类似 --fixup,但保留你的信息,autosquash 时能编辑合并后的信息。
git commit --squash=a1b2c3d -m "more detail"
git apply <patch>把普通 diff/patch 应用到工作区但不生成提交(和 git am 不同)。
⚠ 常见坑: patch 应用不干净时,加 --3way 退回到基于 blob 信息的三方合并。
git apply fix.patch
git apply --3way fix.patch
git apply --check fix.patch
git diff > <file>.patch把当前未暂存的改动存成 patch 文件,方便分享或在别处应用。
git diff > my-change.patch
git diff --staged > staged.patch
git range-diff <a>...<b>逐提交对比一组补丁的两个版本(比如 rebase 前后),看到底改了什么。
git range-diff main...feature@{1} main...featuregit range-diff origin/feature...feature
git worktree remove <path>用完后移除一个关联 worktree,并清理 .git 里的记账信息。
⚠ 常见坑: worktree 里有未提交改动会拒绝删除,先 commit/stash,确定要丢就加 --force。
git worktree remove ../hotfix
git worktree prune
git notes add -m "<text>"给提交附加一条 note 而不改变它的 SHA,适合存评审元信息或 CI 结果。
⚠ 常见坑: note 默认不会被推送,要单独 push refs/notes/commits 或加 refspec 才能分享。
git notes add -m "reviewed by Alice" a1b2c3d
git push origin refs/notes/commits
git bundle create <file> <refs>把提交打包成单个文件,没网时用 U 盘/邮件传,再从它 clone/fetch。
git bundle create repo.bundle --all
git clone repo.bundle restored-repo
git config --global user.name "Name"设置全局 git 作者名(对所有仓库生效)。
git config --global user.name "Alice Wang"
git config --global user.email "you@example.com"设置全局 git 作者邮箱。
⚠ 常见坑: 工作仓库里改用 git config user.email(不加 --global)单独配,跟个人项目分开。
git config --global user.email "alice@company.com"
git config user.email "alice@personal.com"
git config --list按生效顺序列出所有 config(system + global + local)。
git config --list
git config --list --show-origin
git config --global alias.<name> <cmd>创建自定义 git 别名。常用:co=checkout、br=branch、st=status、lg="log --oneline --graph"。
git config --global alias.co checkout
git config --global alias.lg "log --oneline --graph --all"
git config --global core.editor "code --wait"设置 git 写 commit 信息、交互式 rebase 等用的编辑器。
git config --global core.editor "code --wait"
git config --global core.editor "vim"
git config --global init.defaultBranch main让 git init 默认创建 main 分支而不是 master。
git config --global init.defaultBranch main
git config --global pull.rebase true让 git pull 默认 rebase(不再误产生 merge commit)。
git config --global pull.rebase true
git config --global core.autocrlf input提交时把 CRLF 转 LF,但 checkout 不转。macOS/Linux 跨平台仓库推荐这样设。
⚠ 常见坑: Windows 上推荐值是 true(checkout 时 CRLF、commit 时 LF)。两边混用会出现“假改动”diff。
git config --global core.autocrlf input
git config --unset <key>删除某条 git config 配置。
git config --global --unset user.email
git config --unset alias.co
git config --global core.excludesFile <path>设置对所有仓库生效的全局 ignore 文件(用来忽略 .DS_Store 这类系统/编辑器垃圾)。
git config --global core.excludesFile ~/.gitignore_global
git config --global rerere.enabled true开启 rerere(记住冲突解决),git 会自动重放你以前的冲突解法。
git config --global rerere.enabled true
git config --global merge.conflictstyle zdiff3在冲突标记里显示共同祖先,更容易看清两边各自改了什么。
git config --global merge.conflictstyle zdiff3
git config --global fetch.prune true让每次 fetch 都自动清理远端已删的远程跟踪分支。
git config --global fetch.prune true
git config --global push.autoSetupRemote true首次 push 时自动设置 upstream,新分支不用加 -u 也能 git push。
git config --global push.autoSetupRemote true
git config --global rebase.autoStash truerebase 或 pull --rebase 时自动 stash 脏改动再恢复回来。
git config --global rebase.autoStash true
git config --global diff.colorMoved zebra把移动的行和增删的行用不同颜色标,重构在 diff 里一眼能分清。
git config --global diff.colorMoved zebra
git config --global url.<base>.insteadOf <other>即时重写远端 URL,例如把所有 GitHub 的 HTTPS 地址强制走 SSH。
git config --global url."git@github.com:".insteadOf "https://github.com/"
git config --get-regexp <pattern>打印名字匹配正则的 config 键值(比如所有别名)。
git config --get-regexp alias
git config --get-regexp "^remote\."
git config --global credential.helper <helper>选 git 怎么缓存/存储凭据(macOS 用 osxkeychain,或带超时的 cache)。
⚠ 常见坑: 普通的 store helper 会把 token 明文写进 ~/.git-credentials,优先用系统钥匙串。
git config --global credential.helper osxkeychain
git config --global credential.helper "cache --timeout=3600"
git log显示当前分支的提交历史。
git log
git log -n 10
git log --author="Alice"
git log --oneline --graph --all所有分支的紧凑单行图状日志,最常用的 git log 组合。
git log --oneline --graph --all
git log --oneline --graph --all --decorate
git log -p显示提交历史,并附带每次提交的完整 diff。
git log -p
git log -p src/index.ts
git log --stat显示提交历史,附文件变更统计(哪些文件、多少行)。
git log --stat
git log --stat -n 5
git diff显示未暂存的改动(工作区 vs 暂存区)。
git diff
git diff src/index.ts
git diff --staged显示已暂存的改动(暂存区 vs 上次提交),即 git commit 会记录的内容。
git diff --staged
git diff --cached
git diff <branch1>..<branch2>显示两个分支顶端之间的 diff。
git diff main..feature/login
git diff origin/main..HEAD
git diff <branch1>...<branch2>显示 <branch2> 自从与 <branch1> 分叉以来的改动(用 merge base)。PR 预览常用。
⚠ 常见坑: 两点 vs 三点 diff 结果不同,PR 实际显示的是三点版本。
git diff main...feature/login
git blame <file>对文件每一行显示最后修改它的提交和作者。
⚠ 常见坑: 空格/格式化提交会把真作者挡住。用 git blame -w --ignore-rev <格式化提交> 跳过它们。
git blame src/index.ts
git blame -L 10,30 src/index.ts
git blame -w src/index.ts
git show <sha>显示一个提交的元信息和 diff。
git show a1b2c3d
git show HEAD
git show HEAD:src/index.ts
git shortlog -sn按作者汇总提交数(排序、编号)。生成 changelog/致谢列表很好用。
git shortlog -sn
git shortlog -sn --since="1 month ago"
git bisect在提交历史上二分查找引入 bug 的那次提交。
git bisect start
git bisect bad
git bisect good v1.0
git bisect reset
git log -S "<text>"查找新增或删除过指定文本的每个提交,回答“这个字符串是何时出现的?”很好用。
git log -S "TODO" --source --all
git log -S "DEBUG_FLAG"
git grep <pattern>在已跟踪文件里按正则搜索(比 grep 快且尊重 ignore 规则)。
git grep "TODO"
git grep -n "TODO" -- "*.ts"
git diff --name-only只列出有改动的文件名,不显示 diff 内容。配合 pipe 给其他命令很方便。
git diff --name-only
git diff --name-only origin/main...HEAD | xargs eslint
git log --since/--until按日期范围过滤提交。支持 "2 weeks ago" 这种自然语言或 ISO 日期。
git log --since="2 weeks ago"
git log --since=2026-01-01 --until=2026-02-01
git log --follow <file>跨重命名显示文件历史,git mv 之后也能看到完整脉络。
git log --follow src/renamed.ts
git log --follow -p src/renamed.ts
git log <a>..<b>列出 <b> 能到但 <a> 到不了的提交,例如「分支上有但 main 上没有的」。
git log main..feature/login
git log origin/main..HEAD
git log --first-parent合并时只跟第一父提交,得到没有特性分支噪音的干净主线视图。
git log --first-parent --oneline
git log --first-parent main
git log --merges只显示合并提交,方便回顾什么时候集成了什么。
git log --merges --oneline
git log --no-merges
git log --grep=<pattern>在提交信息里按正则搜索,配 -i 忽略大小写。
git log --grep="fix" -i
git log --grep="JIRA-123"
git log --pretty=format:"<fmt>"用 %h(短 sha)、%an(作者)、%ar(相对日期)、%s(标题)等占位符自定义日志输出。
git log --pretty=format:"%h %an %ar — %s"
git log --pretty=format:"%C(yellow)%h%Creset %s"
git show <ref>:<path>打印某个文件在指定提交/分支时的内容,不用 checkout 出来。
git show HEAD~3:package.json
git show main:src/config.ts
git diff --word-diff逐词而不是逐行显示 diff,看文章、文档和配置文件特别清楚。
git diff --word-diff
git diff --word-diff=color README.md
git diff --check在提交前检查空白错误和遗留的冲突标记。
git diff --check
git diff --staged --check
git blame -L <start>,<end> <file>只对文件的某一行号范围做 blame,而不是整个文件。
git blame -L 40,80 src/index.ts
git blame -L :functionName src/index.ts
git rev-parse <ref>把引用(分支/tag/HEAD~3)解析成完整 40 位 SHA,写脚本的瑞士军刀。
git rev-parse HEAD
git rev-parse --short HEAD
git rev-parse --abbrev-ref HEAD
git rev-list --count <ref>统计某个引用可达的提交数,比如分支上有多少个提交。
git rev-list --count HEAD
git rev-list --count main..feature
git cherry -v <upstream>列出你还没进 <upstream> 的提交,+ 表示未合并,- 表示已应用。
git cherry -v main
git cherry -v origin/main feature
git whatchanged类似 git log,但每个提交都显示改了哪些文件(更老、偏文件的日志)。
git whatchanged
git whatchanged --since="1 week ago"
git count-objects -vH以可读单位报告仓库对象占多少磁盘,在 git gc 前发现膨胀。
git count-objects -vH
git submodule add <url> <path>把另一个 git 仓库作为子模块加到指定路径。
⚠ 常见坑: submodule 钉的是某个具体提交,不是分支。新克隆要 git submodule update --init --recursive,否则子模块目录是空的。
git submodule add https://github.com/user/lib.git vendor/lib
git submodule init把 .gitmodules 里登记的 submodule 写进本地 .git/config。
git submodule init
git submodule update --init --recursive初始化、拉取并 checkout 所有 submodule(含嵌套)到登记的提交。
git submodule update --init --recursive
git clone --recurse-submodules <url>
git submodule update --remote把每个 submodule 推到其跟踪远端分支的最新提交(之后要在父仓库提交一次)。
git submodule update --remote
git submodule update --remote vendor/lib
git submodule foreach <cmd>在每个 submodule 里执行 shell 命令。适合批量 git 操作。
git submodule foreach git pull
git submodule foreach "git checkout main && git pull"
git submodule deinit <path>干净地移除 submodule:deinit 注销,再 git rm <path> 并提交。
⚠ 常见坑: 直接删目录会留下旧的 .gitmodules / .git/config 配置。要 deinit + rm 双步。
git submodule deinit vendor/lib
git rm vendor/lib && rm -rf .git/modules/vendor/lib
git submodule status显示每个 submodule 钉的提交,以及是已 checkout、有改动还是不同步。
git submodule status
git submodule status --recursive
git submodule syncsubmodule 的 URL 改了之后,把 .git/config 里记录的 URL 同步成 .gitmodules 里的。
git submodule sync
git submodule sync --recursive
git submodule set-branch --branch <branch> <path>记录某个 submodule 在 update --remote 时该跟踪哪个分支。
git submodule set-branch --branch main vendor/lib
git clone --recurse-submodules <url>克隆仓库并一步 checkout 所有 submodule,不用再单独 init/update。
git clone --recurse-submodules https://github.com/user/repo.git
git -c submodule.recurse=true pull一条命令拉父仓库并把 submodule 更新到新钉住的提交。
git -c submodule.recurse=true pull
git config --global submodule.recurse true
git checkout -- <file> (LEGACY — destructive)丢弃文件的所有未暂存改动。等价于 git restore <file>。不可撤销,工作区状态没有 reflog。
⚠ 常见坑: 没有提示、没有确认、没有备份。不确定就先 git stash。
git checkout -- broken.ts
git restore broken.ts
detached HEAD recovery直接 checkout 了某个 commit/tag(如 git checkout v1.0),这里产生的提交在你回到分支时会“丢失”,除非创建一个分支。
⚠ 常见坑: 不小心在 detached HEAD 里改了东西,先 git reflog 找回,立即 git branch save-me <sha> 收住。
git switch -c new-branch
git reflog
git branch save-me HEAD@{0}merge conflict resolutionmerge 中冲突时:编辑每个文件里的 <<<<<<< / ======= / >>>>>>> 标记,git add 已解决的文件,然后 git commit(或 git merge --continue)。
⚠ 常见坑: 忘记 git add 已解决的文件,merge 不会被算完成,commit 报 “you have unmerged paths”。
git status
git add resolved.ts
git commit
git merge --abort
recover lost commits with reflog错误的 reset/rebase/删分支后,git reflog 会列出每一次 HEAD 移动。找到目标 SHA 然后 git reset --hard <sha> 或 git branch rescue <sha>。
⚠ 常见坑: reflog 会过期(可达 90 天,不可达 30 天)。越早恢复越好。
git reflog
git branch rescue HEAD@{3}git reset --hard HEAD@{5}undo `git push --force`强推覆盖了同事的工作:让同事用自己本地的 reflog 找回旧 SHA 并强推回去(远端被覆盖了,本地还在)。
⚠ 常见坑: GitHub 在悬挂对象的 GC 里大约保留 14 天,有时能通过 API 找回。强推请永远 --force-with-lease。
# on a teammate's machine still holding the old SHAs:
git push --force-with-lease origin <sha>:main
remove a file from git history不小心提交了密钥。git rm 只是“以后没了”。要从全部历史里清掉,用 git filter-repo(现代推荐)或 BFG Repo Cleaner。
⚠ 常见坑: 清理完务必旋转那个密钥,已经克隆过的人本地还有。清理后强推干净历史。
git filter-repo --invert-paths --path secrets/key.pem
git push --force-with-lease origin --all
"fatal: refusing to merge unrelated histories"试图合并/拉取两个没有共同祖先的仓库(如克隆后又重新 init)。确定要合并就加 --allow-unrelated-histories。
git pull origin main --allow-unrelated-histories
"Your branch and origin/main have diverged"你的分支和远端各自有了新提交。选 git pull --rebase 把你的重放到上面,或 git merge 交织起来。别盲目 reset --hard。
⚠ 常见坑: 这里直接 git pull 会生出一个嘈杂的 merge commit,提交还没分享出去的话 rebase 能保持线性。
git pull --rebase
git log --oneline --graph HEAD origin/main
"error: failed to push some refs"远端有你本地没有的提交。先 git pull --rebase 把它们整合进来再推,不要上来就 --force。
⚠ 常见坑: 这时强推会悄悄删掉你没见过的远端提交,整合之后再考虑强推。
git fetch origin
git rebase origin/main
git push
accidentally committed to main instead of a branch在当前提交建一个分支收住这些工作,再把 main 重置回和远端一致。
⚠ 常见坑: 一定先建分支。先 reset --hard main 再建分支的话,提交就只剩 reflog 里有了。
git branch feature/oops
git reset --hard origin/main
git switch feature/oops
.gitignore not ignoring an already-tracked filegitignore 只管未跟踪的文件。已经提交过的文件还会被跟踪,用 git rm --cached 取消跟踪再提交。
git rm --cached .env
echo ".env" >> .gitignore
git commit -m "chore: stop tracking .env"
wrong author on a commit最后一次用 git commit --amend --reset-author 改;更早的用交互式 rebase 配 --exec,或 git rebase -r。
⚠ 常见坑: amend/rebase 会改写 SHA,已推到共享分支就先和大家沟通再强推。
git commit --amend --reset-author --no-edit
git config user.email "right@example.com"
recover a deleted branch被删分支的 tip 还在 reflog 里。用 git reflog 找到它的 SHA,在那里重建分支。
⚠ 常见坑: reflog 只在本地。如果删除是在你已经没有的那台机器上做的,tip 可能就找不回来了。
git reflog
git branch recovered a1b2c3d
git switch -c recovered HEAD@{5}abort a half-finished interactive rebase交互式 rebase 跑歪了,git rebase --abort 会把你原封不动送回起点。
⚠ 常见坑: 只在 rebase 进行中才能 abort。已经做完的话改用 git reset --hard ORIG_HEAD 回退。
git rebase --abort
git reset --hard ORIG_HEAD
CRLF / LF "whole file changed" diff整文件每行都显示改动,通常是行尾不一致。用 .gitattributes 的 * text=auto 规则统一并重新归一化。
echo "* text=auto" >> .gitattributes
git add --renormalize .
git commit -m "chore: normalize line endings"
可搜索的 git 命令速查,覆盖你日常真正会在终端里敲的 100+ 条命令。 每条都有完整语法、中英双语说明、对应的“常见坑”以及一两个能直接拷 贝的真实例子。九大分类:基础(init、clone、status、add、commit、 push、pull、fetch、tag、mv、rm),分支(branch、checkout、switch、 merge、rebase、cherry-pick),回退与恢复(reset --soft / --mixed / --hard、revert、restore、stash、reflog、clean),远程(remote、 fetch --prune、push -u、push --tags),协作(rebase -i、autosquash、 merge --squash、--force-with-lease、worktree),配置与别名,检查与 历史(log、diff、blame、show、bisect、grep、log -S),子模块(add、 init、update --remote、foreach、deinit),常见错误(detached HEAD 恢复、merge 冲突处理、reflog 找回丢失提交、撤销 --force 推送、用 filter-repo 清理密钥)。输入任何关键词即时跨命令/说明/坑/例子四个 字段过滤;点分类胶囊缩小范围。中英双语,纯浏览器执行,不追踪不弹广 告。配合正则速查表/Crontab 助手 一起用,开发者每周都会 Google 三回 的语法都在这里。
把内容粘贴或拖入工具面板。
点击按钮,在浏览器内本地处理,文件不上传。
一键复制结果或下载到本地。
适合穿插在写代码、查问题、做 Review、上线前的小任务里。
这些入口会把当前任务接到更完整的工具链里。
同事一个 force-push 把共享特性分支上你的三个提交冲掉了。你把速查 筛到“reflog”,拷 git reflog,找到覆盖前那个 SHA,再 git branch rescue HEAD@{6} 存成新分支强推回去。那条“常见坑”提醒 你 reflog 只在本地,所以你赶在 GC 跑之前,在提交最后待过的那台 机器上操作,10 分钟搞定。
新人对着终端发懵。你让他点“基础”分类胶囊,列表立刻缩到 7 条: init、clone、status、add、commit、push、pull。他从上往下 20 分钟 跑完,git stash 那条“默认不带未跟踪文件”的坑,在第三天帮他保住了 一个还没 add 的新文件。
评审说你的 git checkout main 写法过时了。你搜“switch”,读到那条 解释 Git 2.23 把 checkout 拆成 git switch(管分支)和 git restore(管文件),把这两行理由直接贴进 PR。一来一回三条评论 的拉扯,30 秒就收场。
你把带真实 token 的 .env 提交并推上去了。搜“密钥”,找到 git filter-repo 那条,照例子把文件从每个提交里剥掉,再强推一次并轮换 密钥。那条坑提醒你 filter-repo 会重写所有 SHA,于是你通知另外两个 协作者重新 clone,而不是直接 pull。
把 git stash 当成安全备份。不加 -u 它就不带未跟踪文件,一个你还没 add 的新文件会被直接落下。用之前先搜“stash”看那条坑。
习惯性敲 git push -f。它会悄悄抹掉同事更新的提交。改用 git push --force-with-lease,远端 ref 不是你上次看到的那个就拒绝推。
以为 git checkout -- 文件 能反悔。被丢弃的工作区改动从没进过提交,reflog 也救不回。先 stash 或 commit,再去丢弃。
全部在你浏览器里跑。命令清单是内存里的静态数组,搜索文字只在本地匹配, 零网络请求,你搜的词、点的分类、敲的命令都不会离开这个标签页。页面也 不往 URL 里写任何东西,公司代理后面用或完全离线都安全。
做你这行的人, 还会一起用这些。