6949 字
35 分钟
Git 备忘
2026-09-28

建议配合 git help <command> 或 git <command> -h 使用。

目录#


0. Git#

0.1 Git 历史#

Git 诞生于 2005 年,和 Linux 内核开发直接相关。

在 Git 之前,Linux 内核长期使用 tarball 和 patch 来协作。随着内核规模和开发者数量增长,这种方式越来越吃力。2002 年,Linux 内核开始使用 BitKeeper 这样的专有分布式版本控制系统。BitMover 公司当时允许 Linux 内核社区免费使用它。

但到了 2005 年,社区中有人试图逆向 BitKeeper 的协议,BitMover 决定收回免费许可。Linux 内核社区一下子失去了可用的版本控制工具。Linus Torvalds 决定自己写一个。

他的目标很明确:

  • 必须分布式;
  • 必须非常快;
  • 必须能处理 Linux 内核这种规模的项目;
  • 必须支持非线性开发,也就是大量分支和合并;
  • 必须保证数据完整性;
  • 不能依赖中心服务器才能提交。

2005 年 4 月 3 日,Linus 开始开发 Git;4 月 7 日,Git 发布了初始版本。几周之内,Git 已经可以管理 Linux 内核源码。同年 7 月,Junio Hamano 成为 Git 的主要维护者。之后 Git 逐渐成为开源世界最主流的版本控制系统。

Git 这个名字本身带点自嘲。Linus 曾开玩笑说:

I’m an egotistical bastard, and I name all my projects after myself. First Linux, now Git.

0.2 Git 的设计目标#

  1. 分布式
    每个克隆都是完整仓库,包含完整历史。可以在离线状态下提交、查看日志、创建分支、合并。远程仓库只是另一个仓库。

  2. 速度
    Git 的大量操作都在本地完成,提交、查看历史、切换分支通常非常快。Linux 内核这种规模的项目也证明了它的性能。

  3. 数据完整性
    Git 用内容哈希标识对象。任何内容变化都会导致哈希变化。历史像一条哈希链,篡改旧提交会导致后续提交全部对不上。

  4. 非线性开发
    Git 鼓励频繁创建分支和合并。分支在 Git 里非常轻量,本质上只是一个指向提交的指针。

  5. 强抗压能力
    Git 需要处理大仓库、大量文件、大量分支和合并。它的对象模型和存储格式都为此服务。

0.3 Git 心智模型#

很多传统版本控制系统以“文件差异”为中心:记录每个文件从上一版到这一版改了什么。Git 的逻辑模型不同:每次提交记录的是整个项目在那一刻的快照。

但 Git 不会傻到把每个文件都完整复制一遍。它通过对象模型复用未变化的内容:

  • 文件内容相同,就复用同一个 blob 对象;
  • 目录结构相同,就复用同一棵 tree;
  • 只有真正变化的部分才会产生新对象。
逻辑模型:commit 是项目快照
存储实现:未变内容通过哈希复用,打包时还会做 delta 压缩
比较差异:需要时再计算,而不是提交时保存差异

这也是为什么 Git 切换分支、查看历史通常很快。

0.4 内容寻址与四种对象#

Git 的底层是一个内容寻址的对象数据库。所有对象都存放在 .git/objects 里,用哈希作为 ID。传统上使用 SHA-1,生成 40 位十六进制字符串;较新的 Git 也支持 SHA-256 仓库格式,但生态兼容性还在推进中。

Git 有四种核心对象:

1. blob#

blob 保存文件内容,但不保存文件名。也就是说,同样内容的两个文件,即使路径不同,也可能共享同一个 blob。

Terminal window
echo "hello git" | git hash-object -w --stdin

查看对象类型和内容:

Terminal window
git cat-file -t <hash>
git cat-file -p <hash>

2. tree#

tree 表示一个目录。它记录目录下的条目:

  • 文件模式;
  • 对象类型;
  • 对象哈希;
  • 文件名。

可以把它理解成“目录快照”。

Terminal window
git ls-tree HEAD

3. commit#

commit 表示一次提交。它包含:

  • 指向一棵 tree 的哈希;
  • 一个或多个父提交的哈希;
  • 作者、提交者、时间;
  • 提交信息。

查看当前提交对象:

Terminal window
git cat-file -p HEAD

4. tag#

带注释的标签是一个独立对象,指向某个提交、tree 或 blob,并包含标签名、打标签的人、说明信息。轻量标签则只是一个引用,不产生独立对象。

Terminal window
git tag -a v1.0.0 -m "release v1.0.0"
git cat-file -p v1.0.0

0.5 哈希链与不可变性#

Git 对象一旦写入,内容就由哈希决定。因此提交历史形成了一条级联关系:

修改一个文件
-> blob 哈希变化
-> tree 哈希变化
-> commit 哈希变化
-> 后续 commit 的 parent 哈希也变化

这意味着:

  • 旧提交不可变;
  • git commit --amend 不是修改旧提交,而是创建一个新提交;
  • git rebase 不是移动旧提交,而是重放并创建新提交;
  • 旧提交不会立刻消失,通常还能通过 reflog 找回,直到被垃圾回收。

0.6 提交图:DAG#

Git 的提交历史是一张有向无环图,简称 DAG。

A --- B --- C --- F (main)
\ /
D --- E (feature)

每个提交指向自己的父提交。普通提交有一个父提交,合并提交有两个或多个父提交。根提交没有父提交。

分支和标签只是指向这些提交的“引用”。

0.7 引用、HEAD 与分支#

Git 里的“引用”可以理解为一个带名字的指针,存放在 .git/refs 下:

refs/heads/main 本地分支
refs/remotes/origin/main 远程跟踪分支
refs/tags/v1.0.0 标签

查看引用:

Terminal window
git show-ref
git branch -vv

HEAD 是一个特殊引用,通常是一个符号引用,指向当前分支:

refs/heads/main
git symbolic-ref HEAD

当 HEAD 指向某个分支时,提交会移动这个分支指针。比如在 main 分支提交,Git 会:

  1. 创建新的 commit 对象;
  2. 把 refs/heads/main 指向新提交;
  3. HEAD 仍然指向 refs/heads/main。

如果 HEAD 直接指向某个提交,而不是分支,就是 detached HEAD 状态。此时提交不会移动任何分支,容易丢失。可以这样补救:

Terminal window
git switch -c new-branch

分支在 Git 里非常轻量。创建一个分支,本质上就是创建一个包含提交哈希的文件。删除分支,也只是删除一个引用。这就是为什么 Git 的分支操作这么快。

0.8 工作区、暂存区、HEAD#

工作区 实际文件
索引/暂存区 下一次提交的候选快照
HEAD 当前分支最新提交

工作区#

正在编辑的文件。git status 中“modified but not staged”就是指工作区和索引不一致。

索引 / 暂存区#

索引是 .git/index 文件,记录下一次提交要包含的内容。git add 会把工作区内容写入对象库,并更新索引。git commit 会根据索引创建 tree 和 commit。

暂存区是 Git 很有特色的设计:

  • 只提交部分文件;
  • 用 git add -p 只暂存某些代码块;
  • 在合并冲突时记录不同阶段的版本;
  • 精细组织提交,而不是一次性把工作区全部提交。

HEAD 通常指向当前分支的最新提交,作为比较基准。

三个常见比较命令对应三棵树:

Terminal window
git diff # 工作区 vs 索引
git diff --staged # 索引 vs HEAD
git diff HEAD # 工作区 vs HEAD

reset 和 restore 本质上就是在操作这三棵树:

命令HEAD索引工作区
git reset --soft HEAD~1移动不变不变
git reset --mixed HEAD~1移动重置不变
git reset --hard HEAD~1移动重置重置
git restore --staged file不变从 HEAD 恢复不变
git restore file不变不变从索引恢复

0.9 .git 目录#

一个典型 .git 目录:

.git/
├── HEAD
├── config
├── index
├── objects/
├── refs/
│ ├── heads/
│ ├── remotes/
│ └── tags/
├── logs/
├── hooks/
├── info/
│ └── exclude
└── packed-refs

常见内容:

  • HEAD:当前引用;
  • config:仓库配置;
  • index:暂存区;
  • objects/:对象数据库;
  • refs/:分支、远程跟踪分支、标签;
  • logs/:reflog;
  • hooks/:钩子脚本;
  • info/exclude:本地忽略规则;
  • packed-refs:打包后的引用。

查看 Git 目录:

Terminal window
git rev-parse --git-dir

0.10 合并与变基的原理#

merge#

合并分两种常见情况。

快进合并:如果当前分支没有新提交,而目标分支是当前分支的后代,Git 只需要移动指针。

Terminal window
git switch main
git merge feature

如果 main 可以直接前进到 feature,就是 fast-forward。

三方合并:如果两个分支都有新提交,Git 会找到共同祖先,进行三方合并:

共同祖先 + 当前分支 + 目标分支

然后生成一个合并提交。这个提交有两个父提交。

Terminal window
git merge --no-ff feature

rebase#

rebase 是“变基”。它会找到当前分支和目标分支的共同祖先,然后把当前分支自共同祖先之后的提交逐个“重放”到目标分支上。

Terminal window
git switch feature
git rebase main

重放会创建新提交。因此 rebase 会改写提交哈希。

  • 优点:历史更线性。
  • 代价:不要对已经共享的公共分支做 rebase。

cherry-pick#

cherry-pick 把某个提交的变更应用到当前分支,并生成一个新提交。

Terminal window
git cherry-pick <commit>

它适合把某个修复从一条分支搬到另一条分支。

0.11 fetch、pull、push 的原理#

远程仓库本质上也是 Git 仓库。远程跟踪分支,比如 origin/main,只是本地对远程状态的缓存。

Terminal window
git fetch origin

fetch 会:

  • 下载远程新增对象;
  • 更新 refs/remotes/origin/*;
  • 不修改工作区和本地分支。
Terminal window
git pull --rebase

pull 等于 fetch 加上 merge 或 rebase。推荐明确使用:

Terminal window
git pull --rebase

这样历史更干净。

Terminal window
git push

push 会把本地对象和引用更新发送给远程。如果远程分支有你本地没有的提交,推送会被拒绝,通常需要先:

Terminal window
git pull --rebase
git push

如果确实要覆盖远程,优先使用:

Terminal window
git push --force-with-lease

它比 --force 安全,因为会检查远程引用是否仍符合预期。

0.12 reflog 与恢复#

reflog 记录 HEAD 和分支引用的移动历史,存放在 .git/logs。

Terminal window
git reflog

误操作之后,它经常能救命:

Terminal window
git reset --hard HEAD@{1}
git branch recover <commit>

即使提交已经不在任何分支上,只要对象还没被垃圾回收,通常也能找回。

Terminal window
git fsck --lost-found
git gc

git gc 会打包对象并清理不可达对象。执行前要确认没有需要恢复的东西。

0.13 常见误区#

  1. “Git 保存的是差异。”
    不准确。Git 的逻辑模型是快照,差异是按需计算的。

  2. “分支是复制一份代码。”
    不是。分支只是一个指向提交的指针。

  3. “远程仓库才是唯一真相。”
    不是。每个克隆都是完整仓库,远程只是另一个仓库。

  4. “commit 可以修改。”
    旧提交不可变。amend 和 rebase 是创建新提交。

  5. “暂存区是多余的。”
    暂存区让你能精细组织提交,也能帮助处理合并冲突。

  6. “公共分支可以随便 rebase 和 force push。”
    这会改写别人已经依赖的历史,通常应该避免。

0.14 总结#

工作区 --git add--> 索引 --git commit--> 本地仓库 --git push--> 远程仓库
^ ^ ^ |
| git restore | git restore --staged | git reset | git fetch
| | | v
+--------------------+-----------------------+---------------- 远程跟踪分支

对象关系:

commit ---> tree ---> blob
|
+---> parent commit
|
+---> parent commit ...

历史关系:

A --- B --- C --- F (main)
\ /
D --- E (feature)

Git 小结#

  • Git 是为 Linux 内核这种大规模、分布式协作而生的;
  • Git 保存快照,但通过内容寻址复用未变内容;
  • 所有对象由哈希标识,历史形成不可变的 DAG;
  • 分支、标签、HEAD 都是引用,分支只是指针;
  • 工作区、暂存区、HEAD 构成日常操作的三棵树;
  • 远程仓库不是中心,只是另一个完整仓库;
  • merge 保留分叉历史,rebase 重写为线性历史;
  • 公共历史不要随便 rebase 或 force push;
  • git reflog 往往能拯救误操作。

Git 2.23+ 推荐使用:

  • git switch 切换分支
  • git restore 恢复文件

旧版本中常用 git checkout 完成类似操作。


1. 初始配置#

第一次使用 Git 时,至少配置用户名和邮箱:

Terminal window
git config --global user.name "Your Name"
git config --global user.email "you@example.com"

推荐的一些全局配置:

Terminal window
# 默认分支名设为 main
git config --global init.defaultBranch main
# 设置编辑器,例如 VS Code
git config --global core.editor "code --wait"
# 拉取时默认使用 rebase,而不是生成合并提交
git config --global pull.rebase true
# fetch 时自动清理远程已删除分支
git config --global fetch.prune true
# rebase 时自动暂存未提交修改
git config --global rebase.autoStash true
# 启用 rerere,复用冲突解决方案
git config --global rerere.enabled true
# 查看所有配置
git config --list --show-origin

查看某一项配置:

Terminal window
git config --global user.name
git config --global --get user.email

编辑全局配置:

Terminal window
git config --global --edit

SSH 配置#

如果使用 GitHub / GitLab,建议配置 SSH:

Terminal window
ssh-keygen -t ed25519 -C "you@example.com"
# 启动 ssh-agent
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# 查看公钥,复制到平台
cat ~/.ssh/id_ed25519.pub
# 测试连接
ssh -T git@github.com

2. 创建与克隆仓库#

初始化新仓库#

Terminal window
git init

克隆远程仓库#

Terminal window
# 克隆默认分支
git clone git@github.com:user/repo.git
# 克隆指定分支
git clone -b dev git@github.com:user/repo.git
# 克隆到指定目录
git clone git@github.com:user/repo.git my-project

3. 日常提交流程#

最常见的流程:

Terminal window
git status
git add <file>
git commit -m "feat: add login page"
git push

查看状态#

Terminal window
git status
git status -s # 简洁模式
git status -sb # 简洁模式 + 分支信息

添加到暂存区#

Terminal window
git add <file> # 添加指定文件
git add . # 添加当前目录及子目录变更
git add -A # 添加所有变更,包括删除
git add -u # 只添加已跟踪文件的修改和删除
git add -p # 交互式选择要暂存的代码块

提交#

Terminal window
git commit -m "feat: add login page"
# 添加已跟踪文件并提交,不能包含新文件
git commit -am "fix: correct typo"
# 修改最后一次提交信息
git commit --amend -m "new message"
# 修改最后一次提交,但不改提交信息
git commit --amend --no-edit
# 查看提交时改了哪些内容
git commit -v

提交信息建议#

可以使用 Conventional Commits:

feat: 新功能
fix: 修复 bug
docs: 文档变更
style: 格式调整,不影响逻辑
refactor: 重构
test: 测试相关
chore: 构建、依赖、工具等杂项

4. 查看状态、差异与历史#

查看差异#

Terminal window
git diff # 工作区与暂存区的差异
git diff --staged # 暂存区与最后一次提交的差异
git diff HEAD # 工作区+暂存区与最后一次提交的差异
git diff <commit1> <commit2> # 两个提交之间
git diff branch1..branch2 # 两个分支之间
git diff --name-only # 只看文件名
git diff --stat # 统计变更

查看提交历史#

Terminal window
git log
git log --oneline
git log --oneline --graph --decorate --all
git log -p -2 # 最近 2 次提交及 diff
git log --stat # 显示文件变更统计
git log --author="Alice"
git log --grep="fix"
git log --since="2024-01-01" --until="2024-12-31"
git log --follow -- file.txt # 追踪文件重命名历史
git log -S "functionName" # 搜索引入或删除某字符串的提交

推荐常用:

Terminal window
git log --oneline --graph --decorate --all

查看某次提交#

Terminal window
git show <commit>
git show <commit> --stat
git show <commit>:path/to/file

查看文件每一行是谁改的#

Terminal window
git blame file.txt
git blame -L 10,20 file.txt

搜索代码#

Terminal window
git grep "TODO"
git grep -n "TODO"

5. 分支管理#

查看分支#

Terminal window
git branch # 本地分支
git branch -a # 所有分支,包括远程
git branch -r # 远程分支
git branch -vv # 本地分支及上游信息

创建与切换#

Terminal window
git branch feature/login # 创建分支
git switch feature/login # 切换分支
git switch -c feature/login # 创建并切换
git switch - # 切回上一个分支
# 旧写法
git checkout feature/login
git checkout -b feature/login

重命名与删除#

Terminal window
git branch -m new-name # 重命名当前分支
git branch -m old-name new-name # 重命名指定分支
git branch -d feature/login # 删除已合并分支
git branch -D feature/login # 强制删除未合并分支

合并#

Terminal window
git switch main
git merge feature/login
# 禁止快进,保留分支历史
git merge --no-ff feature/login
# 压缩合并:把分支变更放入暂存区,需要再 commit
git merge --squash feature/login

解决冲突:

Terminal window
# 编辑冲突文件,保留需要的内容
git add <resolved-file>
git commit
# 或者继续合并
git merge --continue
# 放弃合并
git merge --abort

6. 远程仓库与协作#

查看远程#

Terminal window
git remote -v
git remote show origin

添加、修改、删除远程#

Terminal window
git remote add origin git@github.com:user/repo.git
git remote set-url origin git@github.com:user/repo.git
git remote remove origin

获取与拉取#

Terminal window
git fetch origin # 只下载,不合并
git fetch --all --prune # 获取所有远程并清理已删除分支
git pull # fetch + merge
git pull --rebase # fetch + rebase,推荐
git pull --rebase origin main

推送#

Terminal window
git push
git push -u origin main # 第一次推送并设置上游
git push origin feature/login
git push origin --delete feature/login
git push --tags

如果推送被拒绝:

Terminal window
git pull --rebase
git push

如果确实需要覆盖远程,使用更安全的强推:

Terminal window
git push --force-with-lease

不要轻易使用 git push --force。

设置上游分支#

Terminal window
git branch -u origin/main
git push -u origin main

7. 撤销与回滚#

撤销工作区修改#

Terminal window
git restore file.txt
git restore .

旧写法:

Terminal window
git checkout -- file.txt

取消暂存#

Terminal window
git restore --staged file.txt
git reset HEAD file.txt

修改最后一次提交#

Terminal window
git commit --amend
git commit --amend -m "new message"
git commit --amend --no-edit

已推送到远程的提交不要随便 amend,除非你确定可以强推。

reset:回退提交#

Terminal window
# 撤销最近一次提交,保留修改在暂存区
git reset --soft HEAD~1
# 撤销最近一次提交,保留修改在工作区,取消暂存
git reset HEAD~1
# 撤销最近一次提交,丢弃所有修改
git reset --hard HEAD~1
# 回退到指定提交
git reset --hard <commit>

revert:生成反向提交#

适合已经推送到公共分支的提交:

Terminal window
git revert <commit>
git revert <commit1> <commit2>

回滚合并提交:

Terminal window
git revert -m 1 <merge-commit>

reflog:救回误删提交#

Terminal window
git reflog
git reset --hard HEAD@{1}
git branch recover <commit>

reflog 是本地操作历史,非常适合误 reset、误删分支后的恢复。

查看丢失对象#

Terminal window
git fsck --lost-found

8. 暂存工作现场:stash#

正在改代码,但需要临时切换分支或拉取代码:

Terminal window
git stash
git stash push -m "wip: login form"
git stash -u # 包括未跟踪文件
git stash -a # 包括未跟踪和忽略文件
git stash list
git stash show -p stash@{0}
git stash apply stash@{0}
git stash pop
git stash drop stash@{0}
git stash clear

从 stash 创建分支:

Terminal window
git stash branch feature/login stash@{0}

9. 标签#

标签通常用于版本发布。

Terminal window
git tag # 查看标签
git tag v1.0.0
git tag -a v1.0.0 -m "release v1.0.0"
git show v1.0.0
git tag -d v1.0.0 # 删除本地标签
git push origin v1.0.0
git push origin --tags
git push origin --delete v1.0.0

从标签创建分支:

Terminal window
git switch -c hotfix/v1.0.1 v1.0.0

10. 变基、挑拣与历史整理#

rebase#

把当前分支变基到 main:

Terminal window
git switch feature/login
git rebase main

交互式整理最近 3 次提交:

Terminal window
git rebase -i HEAD~3

常用操作:

pick 保留提交
reword 修改提交信息
edit 修改提交内容
squash 合并到上一个提交并保留信息
fixup 合并到上一个提交并丢弃信息
drop 删除提交

继续、跳过、放弃:

Terminal window
git rebase --continue
git rebase --skip
git rebase --abort

不要对已经共享的公共分支做 rebase。

cherry-pick#

把某个提交应用到当前分支:

Terminal window
git cherry-pick <commit>
git cherry-pick <commit1> <commit2>
git cherry-pick --continue
git cherry-pick --abort

压缩提交#

Terminal window
git reset --soft HEAD~3
git commit -m "feat: complete login module"

或者使用交互式 rebase 的 squash / fixup。


11. 忽略文件与清理#

.gitignore#

示例:

# 依赖
node_modules/
vendor/
# 构建产物
dist/
build/
*.log
# 环境变量
.env
.env.local
# IDE
.idea/
.vscode/
*.swp
# 系统文件
.DS_Store
Thumbs.db
# 但保留这个文件
!important.log

如果文件已经被跟踪,再加入 .gitignore 不会生效:

Terminal window
git rm --cached file.txt
git rm -r --cached .
git add .
git commit -m "chore: refresh gitignore"

全局忽略:

Terminal window
git config --global core.excludesfile ~/.gitignore_global

清理未跟踪文件#

Terminal window
git clean -n # 预览
git clean -f # 删除未跟踪文件
git clean -fd # 删除未跟踪文件和目录
git clean -fdx # 连忽略文件也删除,危险

一个 .gitignore 模板#

语法说明#

内容说明
# 开头注释
/ 开头从仓库根目录开始匹配
/ 结尾只匹配目录
*匹配任意字符,不跨目录
**匹配任意多级目录
!取消忽略,后面的规则覆盖前面的规则

规则从上到下,后面的规则可以覆盖前面的规则。

使用建议#

  1. 按技术栈删减,不要全量复制。
  2. 锁文件通常要提交: package-lock.json、yarn.lock、pnpm-lock.yaml、 Gemfile.lock、composer.lock、Podfile.lock。 Cargo.lock 对应用提交,对库可忽略。
  3. 示例配置要提交: .env.example、config.sample.yml 等。
  4. 如果文件已被跟踪,再加入 .gitignore 不会生效,需要: git rm —cached 或 git rm -r —cached .
  5. 检查某文件为什么被忽略: git check-ignore -v
  6. 查看当前被忽略的文件: git status —ignored
  7. 配置全局忽略个人系统 / 编辑器文件: git config —global core.excludesfile ~/.gitignore_global

模板#

# ============================================================
# 1. 操作系统相关
# ============================================================
# macOS
.DS_Store
.AppleDouble
.LSOverride
Icon?
._*
.Spotlight-V100
.Trashes
.fseventsd
.DocumentRevisions-V100
.TemporaryItems
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
*.lnk
*.stackdump
# Linux
*~
.directory
.Trash-*
.fuse_hidden*
.nfs*
# ============================================================
# 2. 编辑器与 IDE
# ============================================================
# VS Code
# 通常忽略个人配置,但团队可以共享 settings / launch / tasks
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# JetBrains 系列:IntelliJ IDEA、WebStorm、PyCharm、GoLand 等
.idea/
*.iml
*.ipr
*.iws
out/
# Eclipse
.metadata/
.classpath
.project
.settings/
# NetBeans
nbproject/private/
nbbuild/
dist/
nbdist/
.nb-gradle/
# Vim
*.swp
*.swo
*.swn
.viminfo
# Emacs
*~
\#*\#
.\#*
# Sublime Text
*.sublime-workspace
# 如果团队共享项目配置,可以取消忽略:
# *.sublime-project
# ============================================================
# 3. 通用构建产物、缓存、临时文件
# ============================================================
# 日志
*.log
*.log.*
logs/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# 临时文件
*.tmp
*.temp
*.bak
*.backup
*.old
*.orig
*.rej
*.pid
*.seed
*.pid.lock
# 缓存
.cache/
cache/
.tmp/
.temp/
# 构建产物:按项目调整,避免误伤源码目录
/build/
/dist/
/out/
/target/
/bin/
/obj/
# 测试与覆盖率
coverage/
.nyc_output/
htmlcov/
.coverage
.coverage.*
*.lcov
TestResults/
# 数据库文件
*.sqlite
*.sqlite3
*.sqlite3-shm
*.sqlite3-wal
*.db
*.db-journal
*.mdb
*.accdb
# ============================================================
# 4. 环境变量、密钥与敏感信息
# ============================================================
# 环境变量:保留示例文件
.env
.env.*
!.env.example
!.env.sample
!.env.template
# 密钥和证书:按需保留公开证书
*.pem
*.key
*.der
*.csr
*.p12
*.pfx
*.jks
*.keystore
# 常见敏感配置
secrets.yml
secrets.yaml
credentials.json
service-account*.json
.npmrc
.pypirc
.netrc
id_rsa*
id_dsa*
# 云平台凭据
.aws/
.azure/
.gcloud/
# Terraform 状态和变量
.terraform/
*.tfstate
*.tfstate.*
crash.log
*.tfplan
# *.tfvars 可能含敏感信息,也可能需要提交示例
# *.tfvars
# !example.tfvars
# Kubernetes
kubeconfig
*.kubeconfig
# Firebase
.firebase/
firebase-debug.log
firestore-debug.log
# Serverless
.serverless/
.aws-sam/
# Heroku
.heroku/
# ============================================================
# 5. Node.js / JavaScript / TypeScript
# ============================================================
node_modules/
.pnpm-store/
.yarn/
.pnp.*
.npm/
# 锁文件通常应该提交
# package-lock.json
# yarn.lock
# pnpm-lock.yaml
# 构建输出
.next/
.nuxt/
.output/
.vercel/
.netlify/
.parcel-cache/
.turbo/
.eslintcache
.stylelintcache
# 测试覆盖率
coverage/
.nyc_output/
# 本地环境变量
.env.local
.env.development.local
.env.test.local
.env.production.local
# ============================================================
# 6. Python
# ============================================================
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# 虚拟环境
.venv/
venv/
ENV/
env/
# 测试与类型检查缓存
.pytest_cache/
.mypy_cache/
.ruff_cache/
.tox/
.nox/
.hypothesis/
# 覆盖率
.coverage
htmlcov/
coverage.xml
# Jupyter
.ipynb_checkpoints/
# Django
local_settings.py
db.sqlite3
db.sqlite3-journal
media/
staticfiles/
# Flask
instance/
.webassets-cache
# Scrapy
.scrapy/
# ============================================================
# 7. Java / JVM / Maven / Gradle
# ============================================================
*.class
*.jar
*.war
*.ear
*.nar
hs_err_pid*
replay_pid*
# Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# Maven Wrapper 的 jar 通常应提交:
# !.mvn/wrapper/maven-wrapper.jar
# Gradle
.gradle/
build/
!gradle/wrapper/gradle-wrapper.jar
!gradle-wrapper.properties
# Java 应用日志
*.log
# ============================================================
# 8. Android
# ============================================================
*.apk
*.aab
*.ap_
*.dex
*.class
*.hprof
bin/
gen/
out/
.gradle/
local.properties
captures/
.externalNativeBuild/
.cxx/
*.jks
*.keystore
# ============================================================
# 9. Go
# ============================================================
*.exe
*.exe~
*.dll
*.so
*.dylib
*.test
*.out
bin/
# go.work.sum 通常应提交,不建议忽略:
# go.work.sum
# vendor:使用 Go Modules 时,应用通常提交 vendor,库通常不提交
# vendor/
# ============================================================
# 10. Rust
# ============================================================
target/
**/*.rs.bk
*.pdb
# Cargo.lock:二进制应用通常提交,库通常忽略
# Cargo.lock
# ============================================================
# 11. C / C++ / CMake
# ============================================================
*.o
*.obj
*.a
*.lib
*.so
*.dll
*.dylib
*.exe
*.out
*.app
*.dSYM/
*.idb
*.pdb
*.ilk
*.exp
*.map
# 覆盖率
*.gcno
*.gcda
*.gcov
# CMake
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
compile_commands.json
# Makefile 通常应提交
# Makefile
# ============================================================
# 12. C# / .NET / Visual Studio
# ============================================================
bin/
obj/
*.user
*.suo
*.userosscache
*.sln.docstates
*.userprefs
.vs/
packages/
*.nupkg
*.snupkg
TestResults/
project.lock.json
project.assets.json
*.dll
*.pdb
*.exe
# NuGet.config 通常应提交
# ============================================================
# 13. Ruby / Rails
# ============================================================
*.gem
*.rbc
.bundle/
vendor/bundle
log/
tmp/
storage/
.byebug_history
coverage/
# Gemfile.lock:应用通常提交,gem 库通常忽略
# Gemfile.lock
# ============================================================
# 14. PHP / Composer / Laravel
# ============================================================
vendor/
.phpunit.result.cache
.php-cs-fixer.cache
.php-cs-fixer.php
# Laravel
storage/*.key
.env
.env.backup
.phpstorm.meta.php
_ide_helper.php
_ide_helper_models.php
# composer.lock 对应用通常应提交,不要随便忽略:
# composer.lock
# ============================================================
# 15. Swift / iOS / macOS / Xcode
# ============================================================
build/
DerivedData/
*.xcuserstate
xcuserdata/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
# CocoaPods
Pods/
# Podfile.lock 通常应提交
# Carthage
Carthage/Build/
# Swift Package Manager
.build/
.swiftpm/
Packages/
# ============================================================
# 16. Docker / 容器
# ============================================================
# Docker 本地覆盖文件
docker-compose.override.yml
# 数据卷:如果 data 是源码或必要资源,不要忽略
# data/
# Dockerfile 和 docker-compose.yml 通常应提交
# ============================================================
# 17. 前端框架 / 静态站点 / 工具补充
# ============================================================
.sass-cache/
.vuepress/dist/
.vitepress/cache/
.vitepress/dist/
storybook-static/
# 静态站点生成器
_site/
.jekyll-cache/
.jekyll-metadata
# public 可能是源目录,也可能是构建输出,按需决定
# public/
# ============================================================
# 18. 压缩包与文档生成
# ============================================================
# 压缩包通常不提交构建产物,按需保留
*.zip
*.tar
*.tar.gz
*.tgz
*.rar
*.7z
*.gz
*.bz2
*.xz
# 文档生成
<!-- docs/_build/ -->
site/
# 性能分析
*.prof
*.trace
perf.data
perf.data.old
# ============================================================
# 19. 取消忽略示例
# ============================================================
# 如果父目录被忽略,需要先取消忽略父目录,再取消忽略文件
# !important.log
# !.env.example
# !dist/
# !dist/.gitkeep

12. 常见问题速查#

撤销 git add#

Terminal window
git restore --staged file.txt

撤销工作区修改#

Terminal window
git restore file.txt

修改最后一次提交#

Terminal window
git commit --amend

回退到远程分支状态#

Terminal window
git fetch origin
git reset --hard origin/main

**危险:**会丢弃本地未提交修改和未推送提交。

push 被拒绝#

Terminal window
git pull --rebase
git push

解决冲突#

Terminal window
git status
# 编辑冲突文件
git add <file>
git commit

查看冲突文件#

Terminal window
git diff --name-only --diff-filter=U

detached HEAD#

Terminal window
git switch -c new-branch

忽略文件不生效#

Terminal window
git rm -r --cached .
git add .
git commit -m "chore: refresh gitignore"

查找引入 bug 的提交#

Terminal window
git bisect start
git bisect bad
git bisect good <good-commit>
# 测试后
git bisect good
git bisect bad
git bisect reset

查看某行代码的提交者#

Terminal window
git blame -L 10,20 file.txt

13. 推荐别名#

配置一些别名可以大幅提高效率:

Terminal window
git config --global alias.st "status -sb"
git config --global alias.co "checkout"
git config --global alias.br "branch"
git config --global alias.ci "commit"
git config --global alias.df "diff"
git config --global alias.dfs "diff --staged"
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --global alias.last "log -1 HEAD --stat"
git config --global alias.unstage "restore --staged --"
git config --global alias.undo "reset --soft HEAD~1"

使用:

Terminal window
git st
git lg
git last
git unstage file.txt
git undo

14. 速查表#

场景命令
初始化仓库git init
克隆仓库git clone <url>
查看状态git status -sb
添加所有变更git add -A
交互式暂存git add -p
提交git commit -m "msg"
修改最后一次提交git commit --amend
查看历史git log --oneline --graph --decorate --all
查看差异git diff / git diff --staged
创建并切换分支git switch -c <branch>
合并分支git merge <branch>
变基git rebase <branch>
交互式变基git rebase -i HEAD~3
挑拣提交git cherry-pick <commit>
拉取并变基git pull --rebase
推送git push
设置上游git push -u origin <branch>
删除远程分支git push origin --delete <branch>
暂存现场git stash push -m "msg"
恢复现场git stash pop
撤销暂存git restore --staged <file>
撤销工作区git restore <file>
软回退git reset --soft HEAD~1
硬回退git reset --hard HEAD~1
反向提交git revert <commit>
查看 refloggit reflog
标签git tag -a v1.0.0 -m "release"
清理未跟踪文件git clean -fd

结语#

Git 命令很多,但日常高频使用的并不多。真正重要的是理解:

  • 工作区、暂存区、本地仓库、远程仓库之间的关系;
  • add、commit、push、pull、fetch 的区别;
  • reset、revert、restore、reflog 分别适合什么场景;
  • 公共分支不要随便 rebase / force push。

最后,任何危险命令执行前,先 git status,再确认自己是否真的需要丢弃修改。

Git 备忘
https://laplacan.icu/posts/git-tech/
作者
LapLacan
发布于
2026-09-28
许可协议
CC BY-NC-SA 4.0