初始化仓库
git init
git init 默认创建的分支名是 master。GitHub 等平台现在推荐用 main,有三种方式:
方式一:一劳永逸(推荐)
git config --global init.defaultBranch main
设置后,所有 git init 创建的仓库默认分支就是 main。只需执行一次,永久生效。
方式二:创建时指定(Git 2.28+)
git init -b main
只对当前仓库生效,不影响全局配置。
方式三:创建后改名
git init
git branch -M main
兼容所有 Git 版本。但注意改名只是本地生效,首次 push 前还没远程分支,所以直接 push 即可。
验证
git branch # 查看当前分支,前面带 * 的就是
创建 SSH 公钥
ssh-keygen -t ed25519 -C "your_email@example.com"
查看公钥:
cat ~/.ssh/id_ed25519.pub
将公钥内容添加到 GitHub/GitLab 的 SSH Keys 设置中。
配置用户信息
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
添加远程仓库
git remote add origin <url>
<url> 是 GitHub 仓库地址。
克隆远程仓库
git clone <url>
直接下载远程仓库到本地,无需手动 init 和 remote。
.gitignore 忽略文件
# 在项目根目录创建 .gitignore 文件
常见忽略规则:
# 依赖
node_modules/
vendor/
# 构建产物
dist/
build/
# 环境变量
.env
.env.local
# 系统文件
.DS_Store
Thumbs.db
# IDE
.vscode/
.idea/
# 日志
*.log
快速开始
# 场景 A:从零开始
git init -b main # 以 main 为主分支初始化
git add .
git commit -m "first commit"
git remote add origin <url>
git push -u origin main
# 场景 B:克隆已有项目
git clone <url>
cd <project>
文件操作
git add <file> # 添加指定文件到暂存区
git add . # 添加所有修改
git add -p # 交互式选择添加(逐块确认,推荐)
git add *.js # 通配符添加
git add src/ # 添加整个目录
git rm <file> # 删除文件并暂存
git mv <old> <new> # 重命名文件
git restore <file> # 丢弃工作区修改(回到最近一次 add/commit 的状态)
git restore --staged <file> # 取消暂存(修改回到工作区)
提交管理
git status # 查看工作区状态
git status -s # 简洁状态
git diff # 查看未暂存的修改内容
git diff --staged # 查看已暂存但未提交的修改
git commit -m "提交说明" # 提交暂存区
git commit -am "提交说明" # add + commit(仅已跟踪文件)
git commit --amend -m "新的信息" # 修改最近一次提交的信息
git commit --amend --no-edit # 追加修改到最近一次提交,不改信息
提交信息规范(Conventional Commits)
<type>: <简短描述>
feat: 添加用户登录
fix: 修复登录超时
refactor: 提取 token 刷新逻辑
docs: 更新 README
chore: 升级依赖
远程同步
git remote -v # 查看远程仓库列表
git remote add origin <url> # 添加远程仓库
git remote set-url origin <url> # 修改远程仓库地址
git remote rm origin # 删除远程仓库关联
git fetch origin # 下载远程更新,不合并
git fetch --prune # 同时清理远程已删除的分支
git pull origin main # 拉取并合并(= fetch + merge)
git pull --rebase origin main # 拉取并变基(= fetch + rebase,推荐)
git push origin <branch> # 推送到远程
git push -u origin <branch> # 首次推送并设置上游(之后直接 git push)
git push --force-with-lease # 安全强制推送(不会覆盖别人新推的提交)
git push origin --delete <branch> # 删除远程分支
临时保存(stash)
git stash # 暂存工作进度
git stash save "描述" # 带描述暂存
git stash list # 查看 stash 列表
git stash pop # 恢复最近一次并删除
git stash apply # 恢复但不删除
git stash drop # 删除最近一次
git stash pop stash@{1} # 恢复指定的 stash
典型场景:开发到一半需要切分支修 bug,但又不想提交半成品代码。
分支策略
大厂常用的两种模型:Trunk-Based Development(主流)和 Git Flow(传统)。
Trunk-Based Development(推荐)
Google、Facebook 等公司的主流选择。核心思想:所有人都往 main 提交,分支存活不超过 1 天。
main ───●────●────●────●────●────●──▶
│ │ │
│ │ └── 新功能 C(分支存活 4 小时)
│ └── 新功能 B(分支存活 8 小时)
└── 新功能 A(分支存活 6 小时)
特点:
- 分支短命(≤ 1 天),减少合并冲突
- 未完成功能用 feature flag 隐藏,不影响线上
- 高频集成,CI/CD 自动化测试和部署
- Code Review 通过 PR/MR 完成
适用场景: CI/CD 成熟、测试覆盖率高、迭代快的团队。
Git Flow(传统方案)
适合有固定发布周期的项目(客户端软件、SDK)。
main ──●──────────────●──────────────●──▶
│ │ │
develop ──●──●──●──●──●──●──●──●──●──●──●──▶
│ │ │
feature/A ──┘ │ │
│ │
release/1.0 ───┘ ●──●──┘
│
hotfix/xxx ───────────●──┘
| 分支 | 来源 | 合入 | 说明 |
|---|---|---|---|
main |
— | — | 生产环境代码 |
develop |
— | — | 开发主线 |
feature/* |
develop | develop | 新功能 |
release/* |
develop | main + develop | 发布前冻结 |
hotfix/* |
main | main + develop | 线上紧急修复 |
适用场景: 固定版本号、长发布周期。
分支命名规范
| 前缀 | 用途 | 示例 |
|---|---|---|
feature/ |
新功能 | feature/user-auth |
fix/ |
修 bug | fix/login-error |
refactor/ |
重构 | refactor/api-layer |
docs/ |
文档 | docs/api-guide |
chore/ |
杂项 | chore/update-deps |
hotfix/ |
紧急修复 | hotfix/crash-on-start |
分支命令
git branch # 查看本地分支
git branch -r # 查看远程分支
git branch -a # 查看所有分支
git branch <name> # 创建分支(不切换)
git switch <name> # 切换分支(推荐,Git 2.23+)
git switch -c <name> # 创建并切换
git checkout -b <name> # 创建并切换(旧写法)
git branch -m <old> <new> # 重命名分支
git branch -d <name> # 删除已合并分支
git branch -D <name> # 强制删除
git push origin --delete <name> # 删除远程分支
合并策略
# merge:保留分支拓扑
git merge feature/login
# squash merge:整个分支压缩成一条提交(推荐用于 PR 合入)
git merge --squash feature/login
git commit -m "feat: 添加登录功能"
# rebase:把当前分支搬到目标分支顶部,历史线性
git rebase main
| 方式 | 历史形态 | 场景 |
|---|---|---|
| merge | 保留分支图 | 多人协作分支 |
| squash merge | 一条直线 | PR 合入 main(大厂推荐) |
| rebase | 线性历史 | 同步上游、整理本地提交 |
大厂惯例: PR 合入 main 用 squash merge,日常同步用 rebase。
标准开发流程(Feature Branch + PR)
1. 拉取最新
git checkout main
git pull origin main
2. 创建特性分支
git switch -c feature/add-login
3. 开发 + 提交
git status
git diff
git add .
git commit -m "feat: 添加登录功能"
git push -u origin feature/add-login
4. 同步上游(main 有新提交时)
# rebase 方式(推荐)
git checkout main
git pull origin main
git checkout feature/add-login
git rebase main
# 或者 merge 方式
git checkout feature/add-login
git merge main
推送 rebase 后的分支用
git push --force-with-lease,不会覆盖别人的提交。
5. 提交 Pull Request
推送到远程后,在 GitHub/GitLab 网页上创建 PR,填写:
- 标题:一句话描述
- 描述:背景、改动、测试方式、截图
- Reviewer:指定审核人
6. Code Review 后修改
Reviewer 提意见后,在同一分支上继续改:
git add .
git commit -m "fix: 根据 review 意见调整"
git push origin feature/add-login
不要另开新分支。PR 会自动更新到最新提交。
7. 合入后清理
git checkout main
git pull origin main
git branch -d feature/add-login
git push origin --delete feature/add-login # 或直接在 PR 页面点删除
冲突解决
多人改了同一文件时,合并产生冲突:
git merge main
# CONFLICT: Merge conflict in src/app.js
Git 在冲突文件中标记:
<<<<<<< HEAD
你的修改
=======
别人的修改
>>>>>>> main
解决步骤:
# 1. 手动编辑文件,删除标记,保留正确内容
# 2. 标记已解决
git add src/app.js
# 3. 继续
git merge --continue # merge 场景
git rebase --continue # rebase 场景
# 想放弃?
git merge --abort # 或 git rebase --abort
同步上游变更
# 方法一:rebase(推荐)
git fetch origin
git rebase origin/main
# 方法二:merge
git pull origin main
常用组合
# 对比两个分支
git diff main..feature/xxx
git diff main..feature/xxx --name-only # 只看文件名
# 查看还没 push 的提交
git log origin/main..HEAD --oneline
# 把最近 3 次提交压缩成一条
git rebase -i HEAD~3
# 把某次提交应用到当前分支
git cherry-pick <hash>
撤销与回滚
撤销操作分为四个层级,逐级递进:工作区 → 暂存区 → 本地提交 → 远程提交。
层级一:撤销工作区修改(还没 add)
git restore <file> # 丢弃单个文件的修改
git restore . # 丢弃所有文件的修改
本质是从暂存区(或最新提交)恢复文件。不可逆。
层级二:取消暂存(已经 add,还没 commit)
git restore --staged <file> # 取消单个文件的暂存,修改回到工作区
git restore --staged . # 取消所有暂存
修改还在工作区,只是从暂存区拿出来了。
层级三:撤销本地提交(已经 commit,还没 push)
reset — 回退到指定提交
工作区 ← 暂存区 ← 本地仓库 ← 远程
↑
这里
三种模式:
git reset --soft <commit> 修改保留在暂存区(可以直接重新 commit)
git reset --mixed <commit> 修改回到工作区(需要重新 add)
git reset --hard <commit> 修改全部丢弃(不可恢复)
<commit> 的写法:
| 写法 | 含义 |
|---|---|
HEAD~1 |
回退 1 次提交 |
HEAD~3 |
回退 3 次提交 |
abc1234 |
回退到指定 commit hash |
origin/main |
回退到远程 main 的最新状态 |
示例
当前提交历史:
A --- B --- C --- D (HEAD)
回退到 B(撤销 C 和 D):
# 方式一:相对引用
git reset --soft HEAD~2 # 撤销 C、D,修改在暂存区
git reset --mixed HEAD~2 # 撤销 C、D,修改在工作区
git reset --hard HEAD~2 # 撤销 C、D,修改彻底丢弃
# 方式二:用 commit hash
git log --oneline # 先查到目标 commit 的 hash
git reset --hard abc1234 # 直接跳到 abc1234
# 方式三:回退到远程版本
git fetch origin
git reset --hard origin/main
三种模式效果对比
假设工作区有文件 f(v2),暂存区有 f(v2),最新提交是 f(v2):
git reset --soft HEAD~1 → f 保留在暂存区(v2),工作区不变
适合:把多个 commit 合并成一个
git reset --mixed HEAD~1 → f 不在暂存区,在工作区(v2)
适合:重新整理后再 commit(默认行为)
git reset --hard HEAD~1 → f 全部丢弃,回到 HEAD~1 的状态
适合:确认要彻底放弃最近的修改
commit --amend
git commit --amend -m "新的提交信息" # 修改提交信息
git commit --amend --no-edit # 追加内容,不改信息
只适用于还没 push 的提交。本质是把新修改"塞进"上一次提交。
层级四:撤销远程提交(已经 push)
已 push 的提交不能用 reset(会破坏别人拉取的历史),必须用 revert:
git revert abc1234 # 撤销指定提交
git revert abc1234..def5678 --no-commit # 撤销多个,确认后手动 commit
git revert HEAD~2..HEAD # 撤销最近 3 次
revert不删除原提交,而是创建一次新的"反向操作"提交。历史完整、安全、可追溯。
清除工作区
清除未跟踪文件
git clean -n # 预览:列出会被删除的文件(安全)
git clean -f # 删除未跟踪文件
git clean -fd # 删除未跟踪文件和目录
git clean -fx # 连 .gitignore 里的也删
一步回到干净状态
git reset --hard HEAD # 丢弃工作区 + 暂存区所有修改
git reset --hard HEAD && git clean -fd # 连未跟踪文件一起清
切换到指定版本(只读,不回退)
和 reset 不同,切换只是让工作区临时变成历史版本的样子,不移动分支指针,不改历史。
git checkout <commit-hash> # 进入 "detached HEAD" 状态
# 看看代码、运行测试...
git switch main # 看完回来
detached HEAD 图解
正常状态: detached HEAD:
HEAD → main → D --- C --- B --- A HEAD → B --- A
↑
main → D --- C
HEAD 直接指向 commit 而非分支。此时做的提交,切回分支后就"找不到"了。
想基于旧版本改代码?
git checkout -b fix-from-old <commit-hash> # 从旧版本拉新分支
只看不切
git show <hash>:<file> # 查看历史中某个文件的内容
git show HEAD~3:src/app.js
找回误删的提交(reflog)
git reflog # 查看 HEAD 移动记录
即使 reset --hard 或删了分支,只要提交过,reflog 里就能找到 hash,然后恢复:
# 从 reflog 找到要恢复的 hash
git checkout -b recovered-branch abc1234
默认保留 90 天。只要 commit 过,就不会真正丢失。
场景速查
| 我想... | 命令 |
|---|---|
| 丢弃某个文件的修改 | git restore <file> |
| 取消暂存 | git restore --staged <file> |
| 撤销 commit 但保留修改 | git reset --soft HEAD~1 |
| 撤销 commit,回到工作区 | git reset --mixed HEAD~1 |
| 彻底丢弃最近一次 commit | git reset --hard HEAD~1 |
| 回退到远程最新状态 | git reset --hard origin/main |
| 回退到指定 commit | git log --oneline → git reset --hard <hash> |
| 撤销已 push 的提交 | git revert <hash> 然后 git push |
| 改最后一次提交信息 | git commit --amend -m "新的" |
| 删除未跟踪文件 | git clean -f |
| 完全回到干净状态 | git reset --hard HEAD && git clean -fd |
| 临时看历史版本代码 | git checkout <hash> |
| 找回误删的提交 | git reflog → git checkout -b <name> <hash> |
reset vs revert 决策
提交已经 push 到共享分支?(main / develop / 协作分支)
├── 是 → 用 git revert(安全)
└── 否 → 用 git reset(干净)
没把握时先用 revert,永远不会出错。
速查表
| 命令 | 说明 |
|---|---|
git init |
初始化新仓库 |
git clone <url> |
克隆远程仓库 |
git status |
查看工作区状态 |
git diff |
查看未暂存的修改 |
git diff --staged |
查看已暂存的修改 |
git add <file> |
添加指定文件到暂存区 |
git add . |
添加所有修改到暂存区 |
git add -p |
交互式选择添加 |
git commit -m "msg" |
提交暂存区文件 |
git commit --amend |
修改最近一次提交 |
git log --oneline --graph --all |
图形化查看提交历史 |
git blame <file> |
查看文件每行的修改者 |
git branch |
列出本地分支 |
git branch -r |
列出远程分支 |
git switch <branch> |
切换分支 |
git switch -c <branch> |
创建并切换分支 |
git branch -d <branch> |
删除已合并分支 |
git merge <branch> |
合并指定分支到当前分支 |
git rebase <branch> |
将当前分支变基到目标分支 |
git cherry-pick <hash> |
将指定提交应用到当前分支 |
git stash |
暂存工作进度 |
git stash pop |
恢复最近暂存 |
git restore <file> |
丢弃工作区修改 |
git restore --staged <file> |
取消暂存 |
git revert <hash> |
安全撤销某次提交 |
git reset --soft HEAD~1 |
撤销提交,保留修改 |
git reset --hard HEAD~1 |
彻底回退一次提交 |
git remote -v |
查看远程仓库 |
git remote add origin <url> |
添加远程仓库 |
git fetch origin |
拉取远程更新(不合并) |
git pull origin <branch> |
拉取并合并远程分支 |
git push origin <branch> |
推送分支到远程 |
git push -u origin <branch> |
推送并设置上游 |
git push origin --delete <branch> |
删除远程分支 |
git tag v1.0.0 |
创建标签 |
git push origin v1.0.0 |
推送标签到远程 |
工作流一:日常开发(Feature Branch)
# 1. 每天开始:拉取最新
git checkout main
git pull origin main
# 2. 创建特性分支
git switch -c feature/my-feature
# 3. 开发 + 提交
git add .
git commit -m "feat: 添加某某功能"
git push -u origin feature/my-feature
# 4. 期间同步 main 的新变更(如果有)
git fetch origin
git rebase origin/main
# 5. 推送并提 PR → Code Review → 修改 → 合入
# 6. 合入后清理
git checkout main
git pull origin main
git branch -d feature/my-feature
工作流二:紧急修复(Hotfix)
# 1. 从 main 拉最新
git checkout main
git pull origin main
# 2. 创建修复分支
git switch -c hotfix/critical-bug
# 3. 修复 + 提交 + 推送
git add .
git commit -m "fix: 修复线上紧急问题"
git push -u origin hotfix/critical-bug
# 4. 提 PR → 加急 Review → 合入 main
# 5. 确认线上修复后清理
git checkout main
git pull origin main
git branch -d hotfix/critical-bug
工作流三:临时切换任务
# 开发到一半需要切去修 bug
git stash save "WIP: 正在开发用户模块"
# 切去修 bug...
git checkout main
git switch -c hotfix/xxx
# ... 修复、提交、提 PR、合入 ...
# 回到原任务
git checkout feature/my-feature
git stash pop
常用组合
# 看最近一周谁改了什么
git log --oneline --since="1 week ago" --author="你的名字"
# 撤销最近一次 commit(保留修改)
git reset --soft HEAD~1
# 把当前分支的提交整理成一条
git rebase -i HEAD~3 # 交互式整理最近 3 次提交
# 对比两个分支的差异
git diff main..feature/xxx
# 查看哪些文件在 main 上改了但我还没同步
git fetch origin
git diff HEAD..origin/main --name-only