建议配合
git help <command>或git <command> -h使用。
目录
- 0. Git
- 1. 初始配置
- 2. 创建与克隆仓库
- 3. 日常提交流程
- 4. 查看状态、差异与历史
- 5. 分支管理
- 6. 远程仓库与协作
- 7. 撤销、回滚与后悔药
- 8. 暂存工作现场:stash
- 9. 标签
- 10. 变基、挑拣与历史整理
- 11. 忽略文件与清理
- 12. 常见问题速查
- 13. 推荐别名
- 14. 速查表
- 结语
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 的设计目标
-
分布式
每个克隆都是完整仓库,包含完整历史。可以在离线状态下提交、查看日志、创建分支、合并。远程仓库只是另一个仓库。 -
速度
Git 的大量操作都在本地完成,提交、查看历史、切换分支通常非常快。Linux 内核这种规模的项目也证明了它的性能。 -
数据完整性
Git 用内容哈希标识对象。任何内容变化都会导致哈希变化。历史像一条哈希链,篡改旧提交会导致后续提交全部对不上。 -
非线性开发
Git 鼓励频繁创建分支和合并。分支在 Git 里非常轻量,本质上只是一个指向提交的指针。 -
强抗压能力
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。
echo "hello git" | git hash-object -w --stdin查看对象类型和内容:
git cat-file -t <hash>git cat-file -p <hash>2. tree
tree 表示一个目录。它记录目录下的条目:
- 文件模式;
- 对象类型;
- 对象哈希;
- 文件名。
可以把它理解成“目录快照”。
git ls-tree HEAD3. commit
commit 表示一次提交。它包含:
- 指向一棵 tree 的哈希;
- 一个或多个父提交的哈希;
- 作者、提交者、时间;
- 提交信息。
查看当前提交对象:
git cat-file -p HEAD4. tag
带注释的标签是一个独立对象,指向某个提交、tree 或 blob,并包含标签名、打标签的人、说明信息。轻量标签则只是一个引用,不产生独立对象。
git tag -a v1.0.0 -m "release v1.0.0"git cat-file -p v1.0.00.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 标签查看引用:
git show-refgit branch -vvHEAD 是一个特殊引用,通常是一个符号引用,指向当前分支:
git symbolic-ref HEAD当 HEAD 指向某个分支时,提交会移动这个分支指针。比如在 main 分支提交,Git 会:
- 创建新的 commit 对象;
- 把
refs/heads/main指向新提交; - HEAD 仍然指向
refs/heads/main。
如果 HEAD 直接指向某个提交,而不是分支,就是 detached HEAD 状态。此时提交不会移动任何分支,容易丢失。可以这样补救:
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
HEAD 通常指向当前分支的最新提交,作为比较基准。
三个常见比较命令对应三棵树:
git diff # 工作区 vs 索引git diff --staged # 索引 vs HEADgit diff HEAD # 工作区 vs HEADreset 和 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 目录:
git rev-parse --git-dir0.10 合并与变基的原理
merge
合并分两种常见情况。
快进合并:如果当前分支没有新提交,而目标分支是当前分支的后代,Git 只需要移动指针。
git switch maingit merge feature如果 main 可以直接前进到 feature,就是 fast-forward。
三方合并:如果两个分支都有新提交,Git 会找到共同祖先,进行三方合并:
共同祖先 + 当前分支 + 目标分支然后生成一个合并提交。这个提交有两个父提交。
git merge --no-ff featurerebase
rebase 是“变基”。它会找到当前分支和目标分支的共同祖先,然后把当前分支自共同祖先之后的提交逐个“重放”到目标分支上。
git switch featuregit rebase main重放会创建新提交。因此 rebase 会改写提交哈希。
- 优点:历史更线性。
- 代价:不要对已经共享的公共分支做 rebase。
cherry-pick
cherry-pick 把某个提交的变更应用到当前分支,并生成一个新提交。
git cherry-pick <commit>它适合把某个修复从一条分支搬到另一条分支。
0.11 fetch、pull、push 的原理
远程仓库本质上也是 Git 仓库。远程跟踪分支,比如 origin/main,只是本地对远程状态的缓存。
git fetch originfetch 会:
- 下载远程新增对象;
- 更新
refs/remotes/origin/*; - 不修改工作区和本地分支。
git pull --rebasepull 等于 fetch 加上 merge 或 rebase。推荐明确使用:
git pull --rebase这样历史更干净。
git pushpush 会把本地对象和引用更新发送给远程。如果远程分支有你本地没有的提交,推送会被拒绝,通常需要先:
git pull --rebasegit push如果确实要覆盖远程,优先使用:
git push --force-with-lease它比 --force 安全,因为会检查远程引用是否仍符合预期。
0.12 reflog 与恢复
reflog 记录 HEAD 和分支引用的移动历史,存放在 .git/logs。
git reflog误操作之后,它经常能救命:
git reset --hard HEAD@{1}git branch recover <commit>即使提交已经不在任何分支上,只要对象还没被垃圾回收,通常也能找回。
git fsck --lost-foundgit gcgit gc 会打包对象并清理不可达对象。执行前要确认没有需要恢复的东西。
0.13 常见误区
-
“Git 保存的是差异。”
不准确。Git 的逻辑模型是快照,差异是按需计算的。 -
“分支是复制一份代码。”
不是。分支只是一个指向提交的指针。 -
“远程仓库才是唯一真相。”
不是。每个克隆都是完整仓库,远程只是另一个仓库。 -
“commit 可以修改。”
旧提交不可变。amend和rebase是创建新提交。 -
“暂存区是多余的。”
暂存区让你能精细组织提交,也能帮助处理合并冲突。 -
“公共分支可以随便 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 时,至少配置用户名和邮箱:
git config --global user.name "Your Name"git config --global user.email "you@example.com"推荐的一些全局配置:
# 默认分支名设为 maingit config --global init.defaultBranch main
# 设置编辑器,例如 VS Codegit 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查看某一项配置:
git config --global user.namegit config --global --get user.email编辑全局配置:
git config --global --editSSH 配置
如果使用 GitHub / GitLab,建议配置 SSH:
ssh-keygen -t ed25519 -C "you@example.com"
# 启动 ssh-agenteval "$(ssh-agent -s)"ssh-add ~/.ssh/id_ed25519
# 查看公钥,复制到平台cat ~/.ssh/id_ed25519.pub
# 测试连接ssh -T git@github.com2. 创建与克隆仓库
初始化新仓库
git init克隆远程仓库
# 克隆默认分支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-project3. 日常提交流程
最常见的流程:
git statusgit add <file>git commit -m "feat: add login page"git push查看状态
git statusgit status -s # 简洁模式git status -sb # 简洁模式 + 分支信息添加到暂存区
git add <file> # 添加指定文件git add . # 添加当前目录及子目录变更git add -A # 添加所有变更,包括删除git add -u # 只添加已跟踪文件的修改和删除git add -p # 交互式选择要暂存的代码块提交
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: 修复 bugdocs: 文档变更style: 格式调整,不影响逻辑refactor: 重构test: 测试相关chore: 构建、依赖、工具等杂项4. 查看状态、差异与历史
查看差异
git diff # 工作区与暂存区的差异git diff --staged # 暂存区与最后一次提交的差异git diff HEAD # 工作区+暂存区与最后一次提交的差异git diff <commit1> <commit2> # 两个提交之间git diff branch1..branch2 # 两个分支之间git diff --name-only # 只看文件名git diff --stat # 统计变更查看提交历史
git loggit log --onelinegit log --oneline --graph --decorate --allgit log -p -2 # 最近 2 次提交及 diffgit 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" # 搜索引入或删除某字符串的提交推荐常用:
git log --oneline --graph --decorate --all查看某次提交
git show <commit>git show <commit> --statgit show <commit>:path/to/file查看文件每一行是谁改的
git blame file.txtgit blame -L 10,20 file.txt搜索代码
git grep "TODO"git grep -n "TODO"5. 分支管理
查看分支
git branch # 本地分支git branch -a # 所有分支,包括远程git branch -r # 远程分支git branch -vv # 本地分支及上游信息创建与切换
git branch feature/login # 创建分支git switch feature/login # 切换分支git switch -c feature/login # 创建并切换git switch - # 切回上一个分支
# 旧写法git checkout feature/logingit checkout -b feature/login重命名与删除
git branch -m new-name # 重命名当前分支git branch -m old-name new-name # 重命名指定分支git branch -d feature/login # 删除已合并分支git branch -D feature/login # 强制删除未合并分支合并
git switch maingit merge feature/login
# 禁止快进,保留分支历史git merge --no-ff feature/login
# 压缩合并:把分支变更放入暂存区,需要再 commitgit merge --squash feature/login解决冲突:
# 编辑冲突文件,保留需要的内容git add <resolved-file>git commit
# 或者继续合并git merge --continue
# 放弃合并git merge --abort6. 远程仓库与协作
查看远程
git remote -vgit remote show origin添加、修改、删除远程
git remote add origin git@github.com:user/repo.gitgit remote set-url origin git@github.com:user/repo.gitgit remote remove origin获取与拉取
git fetch origin # 只下载,不合并git fetch --all --prune # 获取所有远程并清理已删除分支
git pull # fetch + mergegit pull --rebase # fetch + rebase,推荐git pull --rebase origin main推送
git pushgit push -u origin main # 第一次推送并设置上游git push origin feature/logingit push origin --delete feature/logingit push --tags如果推送被拒绝:
git pull --rebasegit push如果确实需要覆盖远程,使用更安全的强推:
git push --force-with-lease不要轻易使用 git push --force。
设置上游分支
git branch -u origin/maingit push -u origin main7. 撤销与回滚
撤销工作区修改
git restore file.txtgit restore .旧写法:
git checkout -- file.txt取消暂存
git restore --staged file.txtgit reset HEAD file.txt修改最后一次提交
git commit --amendgit commit --amend -m "new message"git commit --amend --no-edit已推送到远程的提交不要随便 amend,除非你确定可以强推。
reset:回退提交
# 撤销最近一次提交,保留修改在暂存区git reset --soft HEAD~1
# 撤销最近一次提交,保留修改在工作区,取消暂存git reset HEAD~1
# 撤销最近一次提交,丢弃所有修改git reset --hard HEAD~1
# 回退到指定提交git reset --hard <commit>revert:生成反向提交
适合已经推送到公共分支的提交:
git revert <commit>git revert <commit1> <commit2>回滚合并提交:
git revert -m 1 <merge-commit>reflog:救回误删提交
git refloggit reset --hard HEAD@{1}git branch recover <commit>reflog 是本地操作历史,非常适合误 reset、误删分支后的恢复。
查看丢失对象
git fsck --lost-found8. 暂存工作现场:stash
正在改代码,但需要临时切换分支或拉取代码:
git stashgit stash push -m "wip: login form"git stash -u # 包括未跟踪文件git stash -a # 包括未跟踪和忽略文件
git stash listgit stash show -p stash@{0}git stash apply stash@{0}git stash popgit stash drop stash@{0}git stash clear从 stash 创建分支:
git stash branch feature/login stash@{0}9. 标签
标签通常用于版本发布。
git tag # 查看标签git tag v1.0.0git 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.0git push origin --tagsgit push origin --delete v1.0.0从标签创建分支:
git switch -c hotfix/v1.0.1 v1.0.010. 变基、挑拣与历史整理
rebase
把当前分支变基到 main:
git switch feature/logingit rebase main交互式整理最近 3 次提交:
git rebase -i HEAD~3常用操作:
pick 保留提交reword 修改提交信息edit 修改提交内容squash 合并到上一个提交并保留信息fixup 合并到上一个提交并丢弃信息drop 删除提交继续、跳过、放弃:
git rebase --continuegit rebase --skipgit rebase --abort不要对已经共享的公共分支做 rebase。
cherry-pick
把某个提交应用到当前分支:
git cherry-pick <commit>git cherry-pick <commit1> <commit2>git cherry-pick --continuegit cherry-pick --abort压缩提交
git reset --soft HEAD~3git 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_StoreThumbs.db
# 但保留这个文件!important.log如果文件已经被跟踪,再加入 .gitignore 不会生效:
git rm --cached file.txtgit rm -r --cached .git add .git commit -m "chore: refresh gitignore"全局忽略:
git config --global core.excludesfile ~/.gitignore_global清理未跟踪文件
git clean -n # 预览git clean -f # 删除未跟踪文件git clean -fd # 删除未跟踪文件和目录git clean -fdx # 连忽略文件也删除,危险一个 .gitignore 模板
语法说明
| 内容 | 说明 |
|---|---|
# 开头 | 注释 |
/ 开头 | 从仓库根目录开始匹配 |
/ 结尾 | 只匹配目录 |
* | 匹配任意字符,不跨目录 |
** | 匹配任意多级目录 |
! | 取消忽略,后面的规则覆盖前面的规则 |
规则从上到下,后面的规则可以覆盖前面的规则。
使用建议
- 按技术栈删减,不要全量复制。
- 锁文件通常要提交: package-lock.json、yarn.lock、pnpm-lock.yaml、 Gemfile.lock、composer.lock、Podfile.lock。 Cargo.lock 对应用提交,对库可忽略。
- 示例配置要提交: .env.example、config.sample.yml 等。
- 如果文件已被跟踪,再加入 .gitignore 不会生效,需要:
git rm —cached
或 git rm -r —cached . - 检查某文件为什么被忽略:
git check-ignore -v
- 查看当前被忽略的文件: git status —ignored
- 配置全局忽略个人系统 / 编辑器文件: git config —global core.excludesfile ~/.gitignore_global
模板
# ============================================================# 1. 操作系统相关# ============================================================
# macOS.DS_Store.AppleDouble.LSOverrideIcon?._*.Spotlight-V100.Trashes.fseventsd.DocumentRevisions-V100.TemporaryItems.VolumeIcon.icns.com.apple.timemachine.donotpresent
# WindowsThumbs.dbehthumbs.dbDesktop.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*.iwsout/
# Eclipse.metadata/.classpath.project.settings/
# NetBeansnbproject/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.**.lcovTestResults/
# 数据库文件*.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.ymlsecrets.yamlcredentials.jsonservice-account*.json.npmrc.pypirc.netrcid_rsa*id_dsa*
# 云平台凭据.aws/.azure/.gcloud/
# Terraform 状态和变量.terraform/*.tfstate*.tfstate.*crash.log*.tfplan# *.tfvars 可能含敏感信息,也可能需要提交示例# *.tfvars# !example.tfvars
# Kuberneteskubeconfig*.kubeconfig
# Firebase.firebase/firebase-debug.logfirestore-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*.eggMANIFEST
# 虚拟环境.venv/venv/ENV/env/
# 测试与类型检查缓存.pytest_cache/.mypy_cache/.ruff_cache/.tox/.nox/.hypothesis/
# 覆盖率.coveragehtmlcov/coverage.xml
# Jupyter.ipynb_checkpoints/
# Djangolocal_settings.pydb.sqlite3db.sqlite3-journalmedia/staticfiles/
# Flaskinstance/.webassets-cache
# Scrapy.scrapy/
# ============================================================# 7. Java / JVM / Maven / Gradle# ============================================================
*.class*.jar*.war*.ear*.narhs_err_pid*replay_pid*
# Maventarget/pom.xml.tagpom.xml.releaseBackuppom.xml.versionsBackuppom.xml.nextrelease.propertiesdependency-reduced-pom.xmlbuildNumber.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*.hprofbin/gen/out/.gradle/local.propertiescaptures/.externalNativeBuild/.cxx/*.jks*.keystore
# ============================================================# 9. Go# ============================================================
*.exe*.exe~*.dll*.so*.dylib*.test*.outbin/
# 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
# CMakeCMakeFiles/CMakeCache.txtcmake_install.cmakecompile_commands.json
# Makefile 通常应提交# Makefile
# ============================================================# 12. C# / .NET / Visual Studio# ============================================================
bin/obj/*.user*.suo*.userosscache*.sln.docstates*.userprefs.vs/packages/*.nupkg*.snupkgTestResults/project.lock.jsonproject.assets.json*.dll*.pdb*.exe
# NuGet.config 通常应提交
# ============================================================# 13. Ruby / Rails# ============================================================
*.gem*.rbc.bundle/vendor/bundlelog/tmp/storage/.byebug_historycoverage/
# Gemfile.lock:应用通常提交,gem 库通常忽略# Gemfile.lock
# ============================================================# 14. PHP / Composer / Laravel# ============================================================
vendor/.phpunit.result.cache.php-cs-fixer.cache.php-cs-fixer.php
# Laravelstorage/*.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/*.xcuserstatexcuserdata/*.moved-aside*.pbxuser!default.pbxuser*.mode1v3!default.mode1v3*.mode2v3!default.mode2v3*.perspectivev3!default.perspectivev3*.hmap*.ipa*.dSYM.zip*.dSYM
# CocoaPodsPods/# Podfile.lock 通常应提交
# CarthageCarthage/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*.traceperf.dataperf.data.old
# ============================================================# 19. 取消忽略示例# ============================================================
# 如果父目录被忽略,需要先取消忽略父目录,再取消忽略文件# !important.log# !.env.example# !dist/# !dist/.gitkeep12. 常见问题速查
撤销 git add
git restore --staged file.txt撤销工作区修改
git restore file.txt修改最后一次提交
git commit --amend回退到远程分支状态
git fetch origingit reset --hard origin/main**危险:**会丢弃本地未提交修改和未推送提交。
push 被拒绝
git pull --rebasegit push解决冲突
git status# 编辑冲突文件git add <file>git commit查看冲突文件
git diff --name-only --diff-filter=Udetached HEAD
git switch -c new-branch忽略文件不生效
git rm -r --cached .git add .git commit -m "chore: refresh gitignore"查找引入 bug 的提交
git bisect startgit bisect badgit bisect good <good-commit># 测试后git bisect goodgit bisect badgit bisect reset查看某行代码的提交者
git blame -L 10,20 file.txt13. 推荐别名
配置一些别名可以大幅提高效率:
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"使用:
git stgit lggit lastgit unstage file.txtgit undo14. 速查表
| 场景 | 命令 |
|---|---|
| 初始化仓库 | 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> |
| 查看 reflog | git 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,再确认自己是否真的需要丢弃修改。
鲁公网安备37160202001015号