Git 是目前最流行的分布式版本控制系统。本文将系统介绍 Git 仓库管理中的常用命令,从基础配置到高级操作,每个命令都配有详细说明和实际示例。
本文基于 Git 2.x 版本,涵盖日常开发 90% 以上的使用场景。
一、基础配置
在使用 Git 之前,需要先配置用户信息,这些信息会记录在每次提交中。
1. git config --- 配置 Git 选项
语法
bash
git config [--global] <key> <value>
git config --list
常用选项
| 选项 | 说明 |
|---|---|
--global |
全局配置(当前用户) |
--system |
系统配置(所有用户) |
--local |
仓库级配置(默认) |
--list |
列出所有配置 |
--unset |
删除配置项 |
--edit |
用编辑器打开配置文件 |
示例
bash
# 设置用户名和邮箱(必须)
git config --global user.name "张三"
git config --global user.email "zhangsan@example.com"
# 设置默认编辑器为 VS Code
git config --global core.editor "code --wait"
# 设置别名(简化命令)
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --all"
# 查看所有配置
git config --list
# 查看特定配置
git config user.name
# 修改已有配置
git config --global user.name "李四"
# 删除配置
git config --global --unset user.name
# 设置不同仓库使用不同身份(仓库级配置)
cd myproject
git config user.email "work@company.com"
二、创建与克隆仓库
2. git init --- 初始化一个新的 Git 仓库
语法
bash
git init [目录名]
常用选项
| 选项 | 说明 |
|---|---|
--bare |
创建裸仓库(无工作区,用于远程中心仓库) |
--template |
指定模板目录 |
--initial-branch |
指定初始分支名(Git 2.28+) |
示例
bash
# 在当前目录初始化仓库
cd my-project
git init
# 输出:Initialized empty Git repository in /path/to/my-project/.git/
# 在指定目录初始化
git init new-project
# 初始化时指定默认分支为 main
git init --initial-branch=main
# 创建裸仓库(常用于服务器端)
git init --bare my-project.git
# 使用模板目录初始化
git init --template=/path/to/template
3. git clone --- 克隆远程仓库到本地
语法
bash
git clone <仓库地址> [本地目录名]
常用选项
| 选项 | 说明 |
|---|---|
--depth <深度> |
浅克隆,只拉取最近的几次提交 |
--branch <分支名> |
克隆指定分支 |
--single-branch |
只克隆一个分支 |
--recursive |
递归克隆子模块 |
--origin <名称> |
设置远程仓库别名(默认 origin) |
--no-checkout |
克隆后不自动检出工作区 |
示例
bash
# 基本克隆
git clone https://github.com/user/repo.git
# 克隆到指定目录
git clone https://github.com/user/repo.git my-folder
# 使用 SSH 协议
git clone git@github.com:user/repo.git
# 浅克隆(只拉取最近 1 次提交,节省带宽)
git clone --depth 1 https://github.com/user/repo.git
# 克隆指定分支
git clone --branch develop https://github.com/user/repo.git
# 只克隆 main 分支
git clone --single-branch --branch main https://github.com/user/repo.git
# 克隆并递归初始化所有子模块
git clone --recursive https://github.com/user/repo.git
# 克隆后不自动 checkout(用于只读仓库或 CI)
git clone --no-checkout https://github.com/user/repo.git
三、基本快照操作(工作区 ↔ 暂存区 ↔ 仓库)
4. git status --- 查看工作区和暂存区的状态
语法
bash
git status [选项]
常用选项
| 选项 | 说明 |
|---|---|
-s / --short |
简洁模式输出 |
-b |
显示分支信息(与 -s 连用) |
--ignored |
显示被忽略的文件 |
示例
bash
# 标准输出
git status
# On branch main
# Changes not staged for commit:
# modified: README.md
# Untracked files:
# newfile.txt
# 简洁模式
git status -s
# M README.md
# ?? newfile.txt
# 显示被忽略的文件
git status --ignored
5. git add --- 将文件添加到暂存区
语法
bash
git add <文件/目录>...
常用选项
| 选项 | 说明 |
|---|---|
-A / --all |
添加所有修改、删除、新增的文件 |
-u / --update |
只添加已跟踪文件的修改/删除,不添加新文件 |
-p / --patch |
交互式选择部分修改块添加 |
-i / --interactive |
交互式添加 |
-f / --force |
强制添加被忽略的文件 |
示例
bash
# 添加单个文件
git add index.html
# 添加多个文件
git add index.html style.css
# 添加整个目录
git add src/
# 添加所有变更(包括删除和新增)
git add -A
# 或者
git add .
# 只添加已跟踪文件的修改(不添加新文件)
git add -u
# 交互式选择部分修改块(非常有用)
git add -p README.md
# 会显示每个修改块,询问是否暂存:y/n/q/a/d/e...
# 强制添加被 .gitignore 忽略的文件
git add -f ignored-file.log
# 交互式添加界面
git add -i
6. git commit --- 将暂存区内容提交到仓库
语法
bash
git commit [-m "消息"]
常用选项
| 选项 | 说明 |
|---|---|
-m "<消息>" |
直接提供提交消息 |
-a / --all |
自动暂存所有已跟踪文件的修改(跳过 git add) |
--amend |
修改上一次提交(消息或内容) |
--no-edit |
使用原消息修改提交(配合 --amend) |
-s / --signoff |
添加 Signed-off-by 签名 |
--allow-empty |
允许空提交 |
-v |
在消息编辑器中显示差异 |
示例
bash
# 基本提交(会打开编辑器输入消息)
git commit
# 带消息的提交
git commit -m "修复登录页面的样式问题"
# 多行消息
git commit -m "添加用户认证模块" -m "实现了 JWT 令牌验证"
# 跳过暂存区,直接提交所有已跟踪文件的修改
git commit -a -m "更新配置文件和文档"
# 修改上一次提交(修正提交消息)
git commit --amend -m "修正的提交消息"
# 修改上一次提交的内容(先 add 遗漏的文件)
git add forgotten-file.txt
git commit --amend --no-edit # 保持原消息
# 空提交(用于触发 CI 等)
git commit --allow-empty -m "触发构建"
# 添加签名
git commit -s -m "更新版权信息"
7. git rm --- 从工作区和暂存区删除文件
语法
bash
git rm <文件>...
常用选项
| 选项 | 说明 |
|---|---|
--cached |
只从暂存区删除,保留工作区文件 |
-f / --force |
强制删除(如果文件有未暂存的修改) |
-r |
递归删除目录 |
示例
bash
# 删除文件并暂存删除操作
git rm old-file.txt
# 删除目录
git rm -r old-dir/
# 只从 Git 中移除,但保留工作区文件(相当于停止跟踪)
git rm --cached config.local.json
# 强制删除(文件有本地修改时)
git rm -f important.txt
8. git mv --- 移动或重命名文件
语法
bash
git mv <源文件> <目标文件>
说明
相当于 mv old new + git add new + git rm old 的快捷方式。
示例
bash
# 重命名文件
git mv index.html home.html
# 移动文件到子目录
git mv style.css assets/css/
# 移动并重命名
git mv old-name.txt src/new-name.txt
四、查看历史与差异
9. git log --- 查看提交历史
语法
bash
git log [选项] [分支/提交范围]
常用选项
| 选项 | 说明 |
|---|---|
--oneline |
单行简洁输出 |
--graph |
以 ASCII 图形显示分支结构 |
--all |
显示所有分支 |
--decorate |
显示分支/标签指向 |
--author=<作者> |
按作者过滤 |
--since=<时间> / --after |
限定时间范围 |
--until=<时间> / --before |
限定时间范围 |
--grep=<模式> |
按提交消息过滤 |
-p / --patch |
显示每次提交的差异 |
--stat |
显示简略统计(修改的文件和行数) |
--pretty=format: |
自定义输出格式 |
-n <数量> |
限制显示条数 |
--no-merges |
不显示合并提交 |
示例
bash
# 完整历史
git log
# 单行显示最近 10 条
git log --oneline -10
# 图形化显示所有分支
git log --oneline --graph --all --decorate
# 查看某个作者的提交
git log --author="张三"
# 查看最近一周的提交
git log --since="1 week ago"
# 查看包含特定关键词的提交消息
git log --grep="修复"
# 显示每次提交的修改内容
git log -p -2
# 显示简略统计
git log --stat
# 自定义格式(哈希、作者、时间、消息)
git log --pretty=format:"%h - %an, %ar : %s"
# 查看某个文件的提交历史
git log README.md
# 查看两个分支之间的差异提交
git log main..develop
10. git diff --- 查看差异
语法
bash
git diff [选项] [<路径>...]
git diff <提交1> <提交2>
常用场景
- 工作区 vs 暂存区
- 暂存区 vs 最新提交(HEAD)
- 工作区 vs 最新提交
- 两次提交之间
- 两个分支之间
常用选项
| 选项 | 说明 |
|---|---|
--cached / --staged |
暂存区 vs HEAD |
HEAD |
工作区 vs HEAD |
--stat |
只显示统计信息 |
--name-only |
只显示文件名 |
--color-words |
按单词高亮差异 |
--ignore-space-change |
忽略空格变化 |
示例
bash
# 工作区 vs 暂存区(默认)
git diff
# 暂存区 vs 最新提交
git diff --cached
git diff --staged
# 工作区 vs 最新提交
git diff HEAD
# 比较两个提交
git diff abc123 def456
# 比较两个分支
git diff main..develop
# 或者
git diff main develop
# 只显示修改的文件名
git diff --name-only
# 显示统计
git diff --stat
# 比较某个文件在不同版本
git diff HEAD~2 README.md
# 查看某个提交引入的变更(也可以用 git show)
git diff abc123^! # ^! 表示该提交与其父提交的差异
11. git show --- 显示某个提交的详细信息
语法
bash
git show [提交哈希|标签|分支]
示例
bash
# 显示最新提交
git show
# 显示指定提交
git show abc123
# 显示某个标签的信息
git show v1.0
# 只显示某个文件在某次提交中的变化
git show abc123:README.md
# 显示提交的统计信息
git show --stat abc123
# 简洁模式
git show --oneline -s # -s 不显示差异
五、分支管理
12. git branch --- 管理分支
语法
bash
git branch [选项] [分支名]
git branch -d <分支名> # 删除分支
常用选项
| 选项 | 说明 |
|---|---|
| (无参数) | 列出本地分支,当前分支带 * |
-r |
列出远程分支 |
-a |
列出所有分支(本地+远程) |
-v |
显示每个分支的最新提交 |
-vv |
显示本地分支关联的远程分支 |
-d |
删除已合并的分支 |
-D |
强制删除分支(无论是否合并) |
-m |
重命名分支 |
-M |
强制重命名(覆盖同名) |
--set-upstream-to=<远程分支> |
设置上游分支 |
--unset-upstream |
取消上游关联 |
--contains <提交> |
显示包含该提交的分支 |
--no-merged |
显示未合并到当前分支的分支 |
示例
bash
# 列出本地分支
git branch
# * main
# develop
# feature-login
# 列出远程分支
git branch -r
# 列出所有分支
git branch -a
# 创建新分支(但不切换)
git branch feature-payment
# 创建分支并切换(等价于 git branch + git checkout)
git checkout -b feature-payment
# 删除已合并的分支
git branch -d feature-old
# 强制删除未合并的分支
git branch -D feature-abandoned
# 重命名当前分支
git branch -m new-name
# 重命名其他分支
git branch -m old-branch new-branch
# 设置上游分支(关联远程分支)
git branch --set-upstream-to=origin/develop develop
# 查看所有分支及其最后一次提交
git branch -v
# 查看哪些分支已合并到当前分支
git branch --merged
# 查看哪些分支未合并到当前分支
git branch --no-merged
# 显示包含特定提交的分支
git branch --contains abc123
13. git checkout / git switch --- 切换分支或恢复文件
注意:Git 2.23 引入了
git switch和git restore来分离checkout的功能。
git checkout 用法(传统方式)
bash
git checkout <分支名> # 切换分支
git checkout -b <新分支> # 创建并切换
git checkout -- <文件> # 丢弃工作区的修改
git checkout <提交> -- <文件> # 从某次提交恢复文件
git switch 用法(推荐,更清晰)
bash
git switch <分支名> # 切换分支
git switch -c <新分支> # 创建并切换
git switch --detach <提交> # 切换到分离 HEAD 状态
示例
bash
# 传统 checkout 切换分支
git checkout develop
# 创建并切换分支
git checkout -b feature-xyz
# 切换到上一个分支
git checkout -
# 丢弃工作区中某个文件的修改(不可恢复)
git checkout -- README.md
# 从某个提交恢复文件到工作区
git checkout abc123 -- src/app.js
# --- 使用 switch(Git 2.23+)---
git switch main
# 创建并切换
git switch -c new-feature
# 切换到上一个分支
git switch -
# 切换到某次提交(分离 HEAD)
git switch --detach abc123
14. git merge --- 合并分支
语法
bash
git merge <分支名>
常用选项
| 选项 | 说明 |
|---|---|
--no-ff |
禁用快进合并,总是创建合并提交 |
--ff-only |
只允许快进合并,否则失败 |
--squash |
压缩合并(不记录合并来源,将所有提交压缩为一个) |
--abort |
中止合并(解决冲突前) |
--continue |
解决冲突后继续合并 |
--no-commit |
合并后不自动提交(用于进一步调整) |
--edit |
在合并前编辑合并消息 |
示例
bash
# 首先切换到目标分支(如 main)
git checkout main
# 将 feature 分支合并到 main
git merge feature-login
# 快进合并(默认行为,若可能)
git merge --ff-only feature-bugfix
# 强制创建合并提交(即使可以快进)
git merge --no-ff feature-new-ui
# 压缩合并(将 feature 的所有提交合并为一个)
git merge --squash feature-long
git commit -m "合并 feature-long 的所有更改"
# 合并后不自动提交(用于手动调整)
git merge --no-commit feature-test
# 中止合并(遇到冲突想放弃)
git merge --abort
# 解决冲突后继续合并
# 编辑冲突文件,然后:
git add .
git merge --continue
15. git merge 冲突解决示例
当两个分支修改了同一文件的同一区域时,Git 无法自动合并,需要手动解决。
bash
# 尝试合并时出现冲突
git merge feature-branch
# Auto-merging index.html
# CONFLICT (content): Merge conflict in index.html
# Automatic merge failed; fix conflicts and then commit the result.
# 查看冲突文件
git status
# both modified: index.html
# 编辑冲突文件,查找 <<<<<<<, =======, >>>>>>> 标记
# 手动修改后保存
# 标记为已解决
git add index.html
# 完成合并
git commit -m "解决合并冲突"
# 或者放弃合并
git merge --abort
16. git mergetool --- 使用图形化工具解决冲突
bash
# 启动配置的合并工具(如 vimdiff, meld, beyond compare)
git mergetool
# 设置默认合并工具
git config --global merge.tool meld
六、远程仓库协作
17. git remote --- 管理远程仓库
语法
bash
git remote [选项] [<名称>] [<URL>]
常用选项
| 选项 | 说明 |
|---|---|
| (无参数) | 列出远程仓库名称 |
-v |
显示远程仓库 URL(详细) |
add <名称> <URL> |
添加新的远程仓库 |
remove <名称> |
移除远程仓库 |
rename <旧名> <新名> |
重命名远程仓库 |
set-url <名称> <新URL> |
修改远程仓库 URL |
show <名称> |
显示远程仓库信息 |
prune <名称> |
删除本地不存在的远程分支引用 |
示例
bash
# 查看远程仓库
git remote
# origin
# 查看详细信息(含 URL)
git remote -v
# origin https://github.com/user/repo.git (fetch)
# origin https://github.com/user/repo.git (push)
# 添加远程仓库
git remote add upstream https://github.com/original/repo.git
# 修改远程仓库 URL
git remote set-url origin https://new-url.git
# 删除远程仓库
git remote remove upstream
# 重命名
git remote rename origin upstream
# 显示某个远程仓库的详细信息
git remote show origin
# 清理远程分支引用(本地已不存在的远程分支)
git remote prune origin
18. git fetch --- 从远程仓库拉取更新(不合并)
语法
bash
git fetch [<远程名>] [<分支名>]
常用选项
| 选项 | 说明 |
|---|---|
--all |
从所有远程仓库获取 |
--prune |
删除本地不存在的远程分支引用 |
--depth |
浅拉取 |
--tags |
同时拉取所有标签 |
--no-tags |
不拉取标签 |
示例
bash
# 从 origin 拉取所有分支的更新
git fetch
# 拉取特定分支
git fetch origin main
# 拉取所有远程仓库
git fetch --all
# 拉取并清理已删除的远程分支引用
git fetch --prune
# 拉取所有标签
git fetch --tags
# 查看拉取后本地与远程的差异
git log origin/main..main # 本地领先的提交
git log main..origin/main # 远程领先的提交
19. git pull --- 拉取并合并远程分支
语法
bash
git pull [<远程名>] [<分支名>]
常用选项
| 选项 | 说明 |
|---|---|
--rebase |
使用 rebase 而不是 merge 合并 |
--ff-only |
只允许快进合并 |
--no-commit |
拉取后不自动提交 |
--autostash |
自动暂存本地修改 |
示例
bash
# 等同于 git fetch + git merge origin/main
git pull
# 拉取并 rebase(保持线性历史)
git pull --rebase
# 拉取指定远程分支
git pull origin develop
# 设置默认使用 rebase 方式拉取
git config --global pull.rebase true
# 拉取时自动暂存未提交的修改
git pull --autostash
20. git push --- 推送本地提交到远程仓库
语法
bash
git push [<远程名>] [<本地分支>[:<远程分支>]]
常用选项
| 选项 | 说明 |
|---|---|
-u / --set-upstream |
设置上游分支并推送 |
--force / -f |
强制推送(覆盖远程历史) |
--force-with-lease |
更安全的强制推送(如果远程有他人推送则拒绝) |
--all |
推送所有分支 |
--tags |
推送所有标签 |
--delete |
删除远程分支 |
--dry-run |
模拟推送,不实际执行 |
示例
bash
# 推送当前分支到 origin 的对应分支
git push
# 推送本地 main 到远程 main
git push origin main
# 推送本地 main 到远程 master(不同名称)
git push origin main:master
# 推送并设置上游跟踪
git push -u origin feature-branch
# 之后可以直接 git push
# 删除远程分支
git push origin --delete feature-old
# 或
git push origin :feature-old
# 强制推送(谨慎使用!会覆盖远程历史)
git push --force origin main
# 安全的强制推送(如果远程有新增提交会失败)
git push --force-with-lease origin main
# 推送所有分支
git push --all origin
# 推送标签
git push --tags
# 模拟推送(不实际执行)
git push --dry-run
21. git push 冲突解决
当远程有本地没有的提交时,push 会被拒绝。需要先 pull 合并或 rebase。
bash
# 推送被拒绝
git push
# ! [rejected] main -> main (fetch first)
# 方法一:pull 后合并
git pull origin main
# 解决冲突(如果有)
git push
# 方法二:pull --rebase 保持线性历史
git pull --rebase origin main
# 解决冲突(如果有)
git rebase --continue
git push
# 方法三:强制推送(仅当确定覆盖远程,如个人分支)
git push --force-with-lease
七、撤销与恢复
22. git reset --- 重置 HEAD 和暂存区/工作区
语法
bash
git reset [--soft|--mixed|--hard] [<提交>]
三种模式
| 模式 | HEAD 指向 | 暂存区 | 工作区 |
|---|---|---|---|
--soft |
改变 | 不变 | 不变 |
--mixed (默认) |
改变 | 重置到目标提交 | 不变 |
--hard |
改变 | 重置到目标提交 | 重置到目标提交 |
示例
bash
# 撤销最后一次提交,保留修改在工作区(等同于 uncommit)
git reset --soft HEAD~1
# 撤销最后一次提交,并将修改移回工作区(默认)
git reset HEAD~1
# 或
git reset --mixed HEAD~1
# 彻底丢弃最近 3 次提交的所有更改(危险!)
git reset --hard HEAD~3
# 取消暂存区的文件(等同于 git restore --staged)
git reset HEAD README.md
# 重置到指定提交,保留之后提交的更改在工作区
git reset --soft abc123
# 重置到某个标签
git reset --hard v1.0
# 撤销合并
git reset --hard ORIG_HEAD # ORIG_HEAD 保存了合并前的 HEAD
23. git revert --- 通过创建新提交来撤销某次提交
与 reset 不同,revert 不会修改历史,而是生成一个反向的新提交,适合公共分支。
语法
bash
git revert <提交哈希>
常用选项
| 选项 | 说明 |
|---|---|
-n / --no-commit |
不自动提交(可多次 revert 后统一提交) |
-m <编号> |
指定主线(用于 revert 合并提交) |
--continue / --abort |
处理冲突后继续/中止 |
示例
bash
# 撤销某次提交
git revert abc123
# 会打开编辑器,确认撤销消息,然后创建新提交
# 撤销最近一次提交
git revert HEAD
# 撤销但不自动提交(用于批量撤销)
git revert -n abc123 def456
git commit -m "撤销 abc123 和 def456"
# 撤销一个合并提交(需要指定主线)
git revert -m 1 merge-commit-hash
# 处理冲突后继续
git revert abc123
# 解决冲突
git add .
git revert --continue
# 中止撤销
git revert --abort
24. git restore --- 恢复工作区或暂存区文件(Git 2.23+)
分离自 git checkout 的功能,更直观。
语法
bash
git restore [--source=<提交>] [--staged] [--worktree] <文件>
示例
bash
# 丢弃工作区的修改(恢复文件到暂存区或 HEAD 的状态)
git restore README.md
# 取消暂存(将文件移出暂存区,保留修改)
git restore --staged README.md
# 同时取消暂存并丢弃工作区修改
git restore --staged --worktree README.md
# 从某个提交恢复文件到工作区
git restore --source=abc123 README.md
# 从某个提交恢复文件到暂存区
git restore --source=HEAD~2 --staged src/app.js
25. git clean --- 删除未跟踪的文件
语法
bash
git clean [选项]
常用选项
| 选项 | 说明 |
|---|---|
-n / --dry-run |
预览要删除的文件(安全) |
-f / --force |
强制删除(必须) |
-d |
同时删除未跟踪的目录 |
-x |
删除被 .gitignore 忽略的文件 |
-X |
只删除被 .gitignore 忽略的文件 |
示例
bash
# 预览会删除哪些未跟踪文件
git clean -n
# 删除所有未跟踪文件(不包含目录)
git clean -f
# 删除未跟踪文件和目录
git clean -fd
# 删除包括被忽略的文件(如临时文件、构建产物)
git clean -fdx
# 只删除被 .gitignore 忽略的文件
git clean -fX
26. git reflog --- 查看引用日志(救命命令)
Git 会记录 HEAD 和分支的每一次移动。即使 reset --hard 丢失了提交,也能通过 reflog 找回。
语法
bash
git reflog [<分支名>]
git reflog expire ... # 清理过期的引用
示例
bash
# 查看所有 HEAD 的移动历史
git reflog
# abc123 HEAD@{0}: commit: 添加新功能
# def456 HEAD@{1}: reset: moving to HEAD~2
# 789xyz HEAD@{2}: commit: 修复bug
# 找回被 reset 丢弃的提交
git reflog
# 找到丢弃前的提交哈希(如 abc123)
git checkout abc123 # 切换到该提交
# 或基于它创建新分支
git branch recovered-branch abc123
# 查看某个分支的 reflog
git reflog main
# 恢复误删的分支(通过 reflog 找到分支最后一次指向的提交)
git reflog
# 找到类似 "branch: created from main" 的记录
git checkout -b recovered-branch abc123
八、储藏(Stash)------临时保存工作区
27. git stash --- 临时保存未提交的修改
当需要切换分支但当前工作区有未提交的修改时,可以使用 stash。
语法
bash
git stash [push] [-m "<消息>"]
git stash list
git stash pop
git stash apply
git stash drop
git stash clear
常用选项/子命令
| 命令 | 说明 |
|---|---|
stash / stash push |
保存当前修改(包括暂存区) |
stash save "<消息>" |
旧语法,同上 |
stash list |
列出所有储藏 |
stash pop |
应用最新的储藏并删除它 |
stash apply [stash@{n}] |
应用储藏(不删除) |
stash drop [stash@{n}] |
删除指定储藏 |
stash clear |
删除所有储藏 |
stash show [stash@{n}] |
显示储藏的差异 |
stash branch <分支名> |
从储藏创建新分支 |
stash push --keep-index |
保存工作区,但保持暂存区不变 |
stash push --include-untracked |
同时保存未跟踪的文件 |
示例
bash
# 保存当前修改(自动生成消息)
git stash
# 保存并添加描述
git stash push -m "WIP: 登录验证逻辑"
# 查看所有储藏
git stash list
# stash@{0}: On main: WIP: 登录验证逻辑
# stash@{1}: On feature: 未完成的功能
# 应用最新的储藏(保留储藏)
git stash apply
# 应用并删除最新的储藏
git stash pop
# 应用指定的储藏
git stash apply stash@{1}
# 查看储藏的修改内容
git stash show stash@{0}
git stash show -p stash@{0} # 显示详细差异
# 删除指定的储藏
git stash drop stash@{0}
# 删除所有储藏
git stash clear
# 从储藏创建新分支(自动应用并删除)
git stash branch new-feature stash@{0}
# 保存未跟踪的文件
git stash push -u
九、标签(Tag)------标记重要版本
28. git tag --- 管理标签
标签用于标记特定的提交(如版本号 v1.0.0)。
语法
bash
git tag [选项] [标签名] [提交]
常用选项
| 选项 | 说明 |
|---|---|
| (无参数) | 列出所有标签 |
-l "<模式>" |
匹配模式的标签 |
-a |
创建附注标签(带信息) |
-m "<消息>" |
附注标签的消息 |
-d |
删除标签 |
-f |
强制覆盖已存在的标签 |
-s |
使用 GPG 签名标签 |
示例
bash
# 列出所有标签
git tag
# v1.0.0
# v1.1.0
# 列出匹配模式的标签
git tag -l "v1.*"
# 创建轻量标签(仅指针)
git tag v1.0.0
# 创建附注标签(推荐,包含作者、日期、消息)
git tag -a v1.0.0 -m "发布 1.0.0 版本"
# 为历史提交打标签
git tag -a v0.9.0 abc123 -m "预发布版本"
# 查看标签信息
git show v1.0.0
# 删除本地标签
git tag -d v1.0.0
# 推送标签到远程
git push origin v1.0.0
# 推送所有标签
git push --tags
# 删除远程标签
git push origin --delete v1.0.0
# 或
git push origin :refs/tags/v1.0.0
# 覆盖已存在的标签(本地+远程)
git tag -f v1.0.0 -m "更新标签"
git push --force --tags
# 切换到标签(分离 HEAD)
git checkout v1.0.0
十、高级操作
29. git rebase --- 变基(重新整理提交历史)
Rebase 可以将一系列提交复制到另一个基础之上,使历史线性化。
语法
bash
git rebase <上游分支>
git rebase -i <基础提交> # 交互式变基
常用选项
| 选项 | 说明 |
|---|---|
-i / --interactive |
交互式变基(编辑、合并、删除提交) |
--onto |
将提交移动到另一个目标上 |
--continue |
解决冲突后继续 |
--skip |
跳过当前提交 |
--abort |
中止变基 |
--autostash |
自动暂存未提交的修改 |
示例
bash
# 将当前分支的提交变基到 main 分支上
git rebase main
# 当前分支的提交会重新应用在 main 的最新提交之后
# 交互式变基最近 3 个提交
git rebase -i HEAD~3
# 会打开编辑器,可以执行以下操作:
# pick = 使用提交
# reword = 修改提交消息
# edit = 修改提交内容
# squash = 合并到前一个提交
# fixup = 合并并丢弃消息
# drop = 删除提交
# 将 feature 分支的某段提交移动到另一个分支上
git rebase --onto main develop feature
# 从远程拉取并变基(代替 merge)
git pull --rebase
# 处理冲突
git rebase main
# 出现冲突,解决后:
git add .
git rebase --continue
# 或者跳过
git rebase --skip
# 或者放弃
git rebase --abort
30. git cherry-pick --- 挑选其他分支的提交
语法
bash
git cherry-pick <提交哈希>...
常用选项
| 选项 | 说明 |
|---|---|
-n / --no-commit |
只应用更改,不自动提交 |
--continue / --abort |
处理冲突后继续/中止 |
--edit |
在提交前编辑消息 |
-x |
在消息中记录来源提交 |
示例
bash
# 挑选一个提交到当前分支
git cherry-pick abc123
# 挑选多个提交
git cherry-pick abc123 def456
# 挑选一个范围
git cherry-pick abc123..def456
# 只应用更改,不提交(合并到工作区)
git cherry-pick -n abc123
git commit -m "手动提交"
# 处理冲突
git cherry-pick abc123
# 解决冲突后
git add .
git cherry-pick --continue
# 放弃
git cherry-pick --abort
31. git bisect --- 二分查找定位引入 bug 的提交
语法
bash
git bisect start
git bisect bad [<提交>]
git bisect good <提交>
git bisect reset
示例
bash
# 开始二分查找
git bisect start
# 标记当前版本有问题
git bisect bad
# 标记某个旧版本正常(如 v1.0)
git bisect good v1.0
# Git 会检出中间的一个提交,需要测试该版本是否有问题
# 根据测试结果标记
git bisect good # 如果这个版本正常
git bisect bad # 如果这个版本有问题
# 重复上述步骤,直到找到第一个 bad 提交
# Git 会输出引入问题的提交哈希
# 结束二分查找,回到原来的分支
git bisect reset
# 使用脚本自动测试(如运行测试套件)
git bisect start HEAD v1.0
git bisect run npm test
32. git submodule --- 管理子模块
常用子命令
| 命令 | 说明 |
|---|---|
git submodule add <URL> [路径] |
添加子模块 |
git submodule init |
初始化子模块配置 |
git submodule update |
更新子模块到记录的提交 |
git submodule status |
查看子模块状态 |
git submodule foreach <命令> |
在每个子模块中执行命令 |
示例
bash
# 添加子模块
git submodule add https://github.com/example/lib.git libs/example-lib
# 克隆包含子模块的仓库
git clone --recursive https://github.com/main/repo.git
# 已克隆但未拉取子模块
git submodule init
git submodule update
# 更新所有子模块到最新
git submodule update --remote
# 更新指定子模块
git submodule update --remote libs/example-lib
# 查看子模块状态
git submodule status
# 在每个子模块中执行 git pull
git submodule foreach git pull origin main
# 删除子模块(需要多个步骤)
git submodule deinit libs/example-lib
git rm libs/example-lib
# 手动删除 .git/modules/libs/example-lib
33. git worktree --- 多工作树管理
允许同时检出多个分支到不同的目录,避免频繁切换。
语法
bash
git worktree add <路径> [分支]
git worktree list
git worktree remove <路径>
git worktree prune
示例
bash
# 在当前仓库外创建一个新的工作树,检出 feature 分支
git worktree add ../myproject-feature feature
# 创建新分支并检出新工作树
git worktree add -b hotfix ../myproject-hotfix main
# 列出所有工作树
git worktree list
# /path/to/main abc123 [main]
# /path/to/feature def456 [feature]
# 移除工作树
git worktree remove ../myproject-feature
# 清理已删除工作树的引用
git worktree prune
34. git grep --- 在 Git 管理的文件中搜索
语法
bash
git grep [选项] <模式>
常用选项
| 选项 | 说明 |
|---|---|
-n |
显示行号 |
-c |
显示匹配计数 |
-p |
显示包含匹配的函数名 |
-l |
只列出文件名 |
-i |
忽略大小写 |
--untracked |
同时搜索未跟踪文件 |
<提交> |
在指定提交中搜索 |
示例
bash
# 在工作区搜索 "TODO"
git grep "TODO"
# 忽略大小写搜索
git grep -i "error"
# 显示行号
git grep -n "function"
# 只列出包含匹配的文件名
git grep -l "import React"
# 在旧版本中搜索
git grep "console.log" HEAD~5
# 跨分支搜索
git grep "fixme" main develop
# 使用正则表达式
git grep -E "TODO|FIXME"
35. git archive --- 导出仓库快照为归档文件
语法
bash
git archive --format=<格式> --output=<文件> <提交或分支>
示例
bash
# 导出当前 HEAD 为 zip 包
git archive --format=zip --output=project.zip HEAD
# 导出为 tar.gz
git archive --format=tar.gz --output=project.tar.gz v1.0
# 导出指定分支,并排除某些目录
git archive --format=zip main | tar -x -C /tmp/project
# 带前缀的导出
git archive --prefix=myproject/ --format=zip HEAD > myproject.zip
# 导出时只包含特定路径
git archive --format=zip HEAD:src/ > src.zip
十一、维护与优化
36. git gc --- 垃圾回收和仓库优化
语法
bash
git gc [选项]
常用选项
| 选项 | 说明 |
|---|---|
--aggressive |
更积极的优化(更慢,但压缩更好) |
--auto |
只在必要时运行 |
--prune=<时间> |
删除过期对象 |
示例
bash
# 执行常规垃圾回收
git gc
# 激进优化(适合大型仓库)
git gc --aggressive
# 自动模式(通常由 Git 自动触发)
git gc --auto
# 同时修剪过时的 reflog
git gc --prune=now
37. git fsck --- 验证仓库完整性
语法
bash
git fsck [选项]
常用选项
| 选项 | 说明 |
|---|---|
--full |
完全检查 |
--unreachable |
显示无法访问的对象 |
--no-dangling |
不显示悬空对象 |
示例
bash
# 检查仓库完整性
git fsck
# 详细输出
git fsck --full
# 检查悬空对象(可能是可恢复的数据)
git fsck --unreachable
38. git prune --- 删除无法访问的对象
通常由 git gc 自动调用,但也可手动执行。
bash
# 删除无法访问的对象(谨慎使用)
git prune
# 立即删除所有无法访问的对象
git prune --expire now
十二、调试与信息查看
39. git blame --- 查看每一行代码的最后修改者
语法
bash
git blame [选项] <文件>
常用选项
| 选项 | 说明 |
|---|---|
-L <开始>,<结束> |
只显示指定行范围 |
-C |
检测跨文件复制的行 |
-M |
检测跨文件移动的行 |
-w |
忽略空白变化 |
示例
bash
# 显示文件的每行修改记录
git blame README.md
# 显示第 10 到 20 行
git blame -L 10,20 src/app.js
# 忽略空白变化
git blame -w config.js
# 显示更详细的移动/复制检测
git blame -C -C index.html
40. git describe --- 为提交生成可读的名称
基于最近的标签生成描述,如 v1.0-3-gabc123(表示在 v1.0 之后第 3 次提交,哈希 abc123)。
语法
bash
git describe [选项] [<提交>]
示例
bash
# 为当前 HEAD 生成描述
git describe
# v1.0.0-5-gabc123
# 使用标签名称,不显示提交计数
git describe --tags
# 总是显示完整哈希
git describe --always
# 匹配特定模式
git describe --match "v*"
41. git shortlog --- 按作者分组显示提交摘要
语法
bash
git shortlog [选项]
示例
bash
# 按作者分组显示所有提交
git shortlog
# 显示统计(每个作者的提交数)
git shortlog -s -n
# 15 张三
# 8 李四
# 显示邮箱
git shortlog -e
# 限制版本范围
git shortlog v1.0..v2.0
十三、实用组合与技巧
42. 常用别名配置
bash
# 美观的日志
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset - %C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
# 查看所有分支的最后提交
git config --global alias.lb "branch -vv"
# 撤销上一次提交(保留修改)
git config --global alias.undo "reset --soft HEAD~1"
# 查看所有贡献者
git config --global alias.contributors "shortlog -sn --no-merges"
# 清理已合并的本地分支
git config --global alias.clean-branches "!git branch --merged | grep -v '\\*\\|main\\|master\\|develop' | xargs -n 1 git branch -d"
# 查看今天的状态
git config --global alias.today "log --since='00:00:00' --oneline"
43. 常用场景命令组合
场景1:放弃所有本地修改
bash
git reset --hard HEAD
git clean -fd
场景2:将某个文件恢复到指定版本
bash
git checkout abc123 -- path/to/file
场景3:移动最近一次提交到新分支
bash
git branch new-feature
git reset --hard HEAD~1
git checkout new-feature
场景4:合并多个提交为一个(交互式变基)
bash
git rebase -i HEAD~3
# 将后两个的 pick 改为 squash 或 fixup
场景5:修改历史中的某个提交消息
bash
git rebase -i HEAD~5
# 将对应提交的 pick 改为 reword
# 保存后编辑消息
场景6:找回误删的分支
bash
git reflog
git checkout -b recovered-branch abc123
场景7:同步 fork 仓库与上游
bash
git remote add upstream https://github.com/original/repo.git
git fetch upstream
git checkout main
git merge upstream/main
git push origin main
场景8:暂存部分修改(交互式添加)
bash
git add -p file.py
# 选择 y(暂存该块)、n(不暂存)、e(手动编辑块)等
场景9:撤销 git add(取消暂存)
bash
git restore --staged file.txt
# 或
git reset HEAD file.txt
场景10:查看两个分支的差异文件列表
bash
git diff --name-only main..develop
十四、常见错误与解决方案
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
fatal: not a git repository |
不在 Git 仓库目录中 | git init 或 cd 到正确目录 |
Updates were rejected because the remote contains work |
远程有本地没有的提交 | git pull --rebase 后再 push |
fatal: refusing to merge unrelated histories |
合并两个独立仓库 | git pull --allow-unrelated-histories |
CONFLICT (content): Merge conflict |
合并时文件冲突 | 手动解决冲突后 git add + git commit |
detached HEAD |
处于分离 HEAD 状态 | 创建新分支 git switch -c new-branch |
fatal: cannot lock ref |
引用锁定问题 | 删除 .git/refs/heads/ 下的锁文件 |
error: failed to push some refs |
强制推送被拒绝 | 使用 --force-with-lease 或先 pull |
fatal: unable to auto-detect email address |
未配置 user.email | git config --global user.email "you@example.com" |
十五、命令速查表
| 分类 | 命令 | 作用 |
|---|---|---|
| 配置 | git config --global user.name "name" |
设置用户名 |
git config --global user.email "email" |
设置邮箱 | |
git config --global alias.co checkout |
设置别名 | |
| 初始化 | git init |
初始化仓库 |
git clone <url> |
克隆仓库 | |
| 基本操作 | git status |
查看状态 |
git add <file> |
暂存文件 | |
git commit -m "msg" |
提交 | |
git rm <file> |
删除文件 | |
git mv <old> <new> |
重命名文件 | |
| 历史查看 | git log --oneline --graph |
查看历史 |
git diff |
查看差异 | |
git show <commit> |
查看提交详情 | |
git blame <file> |
查看行归属 | |
| 分支 | git branch |
列出分支 |
git branch <name> |
创建分支 | |
git checkout <name> / git switch |
切换分支 | |
git merge <branch> |
合并分支 | |
git branch -d <name> |
删除分支 | |
| 远程 | git remote -v |
查看远程 |
git fetch |
拉取更新 | |
git pull |
拉取并合并 | |
git push |
推送 | |
| 撤销 | git reset --soft HEAD~1 |
撤销提交保留修改 |
git reset --hard HEAD |
丢弃所有修改 | |
git revert <commit> |
反转提交 | |
git restore <file> |
丢弃工作区修改 | |
git clean -fd |
删除未跟踪文件 | |
| 储藏 | git stash |
暂存修改 |
git stash pop |
应用并删除暂存 | |
| 标签 | git tag -a v1.0 -m "msg" |
创建附注标签 |
git push --tags |
推送标签 | |
| 高级 | git rebase -i HEAD~3 |
交互式变基 |
git cherry-pick <commit> |
挑选提交 | |
git bisect start |
二分查找 | |
git reflog |
查看引用日志 | |
| 维护 | git gc |
垃圾回收 |
git fsck |
验证完整性 |
结语
本文涵盖了 Git 仓库管理的绝大部分常用命令和典型场景。Git 功能极其丰富,实际工作中不需要记住所有选项,但理解核心概念(工作区、暂存区、本地仓库、远程仓库、分支、提交哈希)和常用命令的用法,足以应对日常开发。遇到不确定的情况,善用 git --help 或 git <command> --help 查看详细文档。
不断练习和探索,你会逐渐掌握 Git 的强大能力。