Git 笔记
目录
- 一、Git 概述
- 二、Git 核心概念
- 三、Git 常用命令速查
- 四、Git 分支管理
- 五、Git 远程仓库
- 六、Git 高级操作
- 七、Git 工作流
- 八、Git 提交规范
- 九、常见问题与排查
- 十、面试高频考点
一、Git 概述
1.1 什么是 Git
Git 是一个分布式版本控制系统,用于跟踪文件的变更历史,支持多人协作开发。
核心特点:
- 分布式:每个开发者都有完整的仓库副本,离线也能工作
- 高效:快照存储,分支切换速度快
- 安全:SHA-1 哈希校验,保证数据完整性
1.2 Git vs SVN
| 对比项 | Git(分布式) | SVN(集中式) |
|---|---|---|
| 仓库结构 | 每个开发者有完整仓库 | 仅中央服务器有完整仓库 |
| 离线工作 | 支持 | 不支持 |
| 分支操作 | 轻量、快速 | 较重、较慢 |
| 提交方式 | 先提交到本地,再推送 | 直接提交到中央服务器 |
| 性能 | 本地操作快 | 依赖网络速度 |
二、Git 核心概念
2.1 工作区域划分
| 区域 | 说明 |
|---|---|
| 工作区(Workspace) | 正在编辑的文件所在目录,即项目根目录 |
| 暂存区(Stage/Index) | 使用 git add 后文件暂存的位置,准备提交 |
| 本地仓库(Repository) | 使用 git commit 后提交的位置,存储版本历史 |
| 远程仓库(Remote) | 如 GitHub、GitLab,用于团队协作共享代码 |
文件状态流转:
工作区 → git add → 暂存区 → git commit → 本地仓库 → git push → 远程仓库
↑ ↑ ↑
Untracked Staged Committed
Modified Unstaged Pushed
2.2 文件状态
| 状态 | 说明 |
|---|---|
| Untracked | 新文件,未被 Git 管理 |
| Tracked | 已被 Git 管理 |
| Staged | 已通过 git add 添加到暂存区 |
| Modified | 已被跟踪但工作区有修改,未添加到暂存区 |
| Committed | 已提交到本地仓库 |
2.3 分支概念
分支(Branch):一条独立的开发线,可以从主线上分离出来,独立开发而不影响主线。
HEAD 指针:指向当前所在分支的最新提交。
分支优势: - 并行开发:多人同时开发不同功能 - 功能隔离:新功能开发不影响主分支 - 安全实验:失败的实验分支可随时删除
三、Git 常用命令速查
3.1 配置与初始化
| 命令 | 说明 | 示例 |
|---|---|---|
git config |
配置用户信息 | git config --global user.name "name" |
git init |
初始化仓库 | git init |
git clone |
克隆远程仓库 | git clone <url> |
配置用户信息:
# 全局配置(所有仓库生效)
git config --global user.name "liutianba"
git config --global user.email "liutianba7@163.com"
# 当前仓库配置(仅当前仓库生效)
git config user.name "liutianba"
git config user.email "liutianba7@163.com"
# 查看配置
git config --list
初始化仓库:
# 在当前目录初始化
git init
# 克隆远程仓库
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git # SSH方式
3.2 基础操作
| 命令 | 说明 | 示例 |
|---|---|---|
git add |
添加文件到暂存区 | git add file.txt |
git status |
查看文件状态 | git status |
git commit |
提交到本地仓库 | git commit -m "message" |
git rm |
删除文件 | git rm file.txt |
将暂存区文件全部删除
添加文件:
# 添加单个文件
git add filename
# 添加所有修改
git add .
# 添加所有文件(包括删除)
git add -A
# 查看状态
git status
git status -s # 精简输出
提交:
# 提交暂存区内容
git commit -m "提交说明"
# 跳过暂存区直接提交(已跟踪文件)
git commit -a -m "提交说明"
# 修改上次提交(未推送前)
git commit --amend -m "新的提交说明"
3.3 查看历史
| 命令 | 说明 | 示例 |
|---|---|---|
git log |
查看提交历史 | git log |
git reflog |
查看所有操作记录 | git reflog |
git diff |
查看差异 | git diff |
git show |
查看某次提交详情 | git show <commit> |
查看提交历史:
# 详细历史
git log
# 精简历史(一行显示)
git log --oneline
# 最近 n 条
git log -n 5
# 图形化显示分支
git log --oneline --graph --all
# 显示文件变更统计
git log --stat
查看操作记录(包含回滚记录):
git log只显示提交历史,git reflog显示所有 HEAD 指针移动记录(包括回滚)。
查看差异:
# 工作区 vs 暂存区
git diff
# 暂存区 vs 最新提交
git diff --staged
git diff --cached # 同上
# 工作区 vs 某次提交
git diff <commit>
# 两个提交之间
git diff <commit1> <commit2>
# 仅显示文件名
git diff --name-only
3.4 版本回退
| 命令 | 说明 | 示例 |
|---|---|---|
git reset |
回退到指定版本 | git reset --hard <commit> |
git revert |
撤销某次提交(新建提交) | git revert <commit> |
git checkout |
撤销工作区修改 | git checkout -- file |
git reset 三种模式
| 模式 | 工作区 | 暂存区 | 提交历史 | 说明 |
|---|---|---|---|---|
--soft |
不变 | 不变 | 回退 | 仅回退提交,保留修改 |
--mixed(默认) |
不变 | 清空 | 回退 | 回退提交和暂存区,保留工作区修改 |
--hard |
清空 | 清空 | 回退 | 全部回退,修改丢失(危险) |
# 回退到上一个版本
git reset --soft HEAD^
git reset --mixed HEAD^ # 默认模式
git reset --hard HEAD^
# 回退到指定版本
git reset --hard <commit-id>
# 回退 n 个版本
git reset --hard HEAD~3
注意:
--hard会丢失工作区修改,谨慎使用!
git reset vs git revert
| 对比项 | git reset | git revert |
|---|---|---|
| 历史记录 | 删除提交历史 | 新建撤销提交,保留原历史 |
| 影响范围 | 回退多个提交 | 撤销单个提交 |
| 适用场景 | 本地未推送的提交 | 已推送的提交(不影响他人) |
| 安全性 | 可能影响他人 | 安全,适合公共分支 |
# revert 撤销某次提交
git revert <commit-id>
# revert 多次提交(从旧到新)
git revert <older-commit>..<newer-commit>
3.5 分支操作
| 命令 | 说明 | 示例 |
|---|---|---|
git branch |
查看/创建分支 | git branch / git branch dev |
git checkout |
切换分支 | git checkout dev |
git switch |
切换分支(新语法) | git switch dev |
git merge |
合并分支 | git merge dev |
git branch -d |
删除分支 | git branch -d dev |
查看分支:
创建与切换:
# 创建分支
git branch dev
# 切换分支
git checkout dev
git switch dev # Git 2.23+ 新语法,更明确
# 创建并切换
git checkout -b dev
git switch -c dev # 新语法
删除分支:
重命名分支:
3.6 远程仓库操作
| 命令 | 说明 | 示例 |
|---|---|---|
git remote |
管理远程仓库 | git remote -v |
git push |
推送到远程 | git push origin main |
git pull |
拉取远程更新 | git pull origin main |
git fetch |
获取远程更新(不合并) | git fetch origin |
关联远程仓库:
# 添加远程仓库
git remote add origin https://github.com/user/repo.git
git remote add origin git@github.com:user/repo.git # SSH
# 查看远程仓库
git remote -v
# 修改远程仓库地址
git remote set-url origin <new-url>
# 删除远程仓库关联
git remote remove origin
推送与拉取:
# 推送当前分支到远程
git push origin main
# 推送并建立关联
git push -u origin main
# 推送所有分支
git push origin --all
# 推送标签
git push origin --tags
# 拉取并合并(fetch + merge)
git pull origin main
# 仅获取更新(不自动合并)
git fetch origin
# 查看远程分支更新
git fetch origin
git log origin/main # 查看远程分支日志
克隆仓库:
# 克隆仓库(默认关联 origin)
git clone https://github.com/user/repo.git
# 克隆指定分支
git clone -b dev https://github.com/user/repo.git
# 克隆到指定目录
git clone <url> my-project
3.7 暂存操作(stash)
场景:正在 dev 分支开发,突然需要切换到 main 修复紧急 bug,但当前修改未完成不想提交。
| 命令 | 说明 | 示例 |
|---|---|---|
git stash |
暂存工作区修改 | git stash |
git stash list |
查看暂存列表 | git stash list |
git stash pop |
恢复并删除暂存 | git stash pop |
git stash apply |
恢复暂存(保留记录) | git stash apply |
git stash drop |
删除暂存记录 | git stash drop |
# 暂存当前修改
git stash
git stash save "暂存说明" # 带说明
# 查看暂存列表
git stash list
# 恢复最近一次暂存
git stash pop # 恢复并删除
git stash apply # 恢复但保留
# 恢复指定暂存
git stash apply stash@{0}
# 删除暂存
git stash drop stash@{0}
git stash clear # 清空所有暂存
3.8 标签操作(tag)
标签:用于标记重要的提交点,如版本发布(v1.0、v2.0)。
| 命令 | 说明 | 示例 |
|---|---|---|
git tag |
查看标签 | git tag |
git tag <name> |
创建轻量标签 | git tag v1.0 |
git tag -a |
创建附注标签 | git tag -a v1.0 -m "说明" |
git show <tag> |
查看标签详情 | git show v1.0 |
git push --tags |
推送标签 | git push origin --tags |
git tag -d |
删除本地标签 | git tag -d v1.0 |
# 查看标签
git tag
git tag -l "v1.*" # 匹配模式
# 创建标签
git tag v1.0 # 轻量标签(仅提交引用)
git tag -a v1.0 -m "版本1.0发布" # 附注标签(推荐)
# 给历史提交打标签
git tag -a v0.9 <commit-id> -m "说明"
# 推送标签到远程
git push origin v1.0 # 单个标签
git push origin --tags # 所有标签
# 删除标签
git tag -d v1.0
git push origin --delete v1.0 # 删除远程标签
四、Git 分支管理
4.1 分支合并
合并方式:
| 方式 | 说明 | 适用场景 |
|---|---|---|
git merge |
创建合并提交,保留分支历史 | 公共分支、团队协作 |
git rebase |
变基,线性历史,无合并提交 | 个人分支、清理历史 |
merge 合并:
# 合并指定分支到当前分支
git merge dev
# 合并并生成合并提交(即使可快进)
git merge --no-ff dev
# 快进合并(无合并提交)
git merge dev --ff
快进合并 vs 非快进合并:
| 类型 | 说明 | 图示 |
|---|---|---|
| 快进合并(Fast-forward) | 直接移动指针,无合并提交 | 线性历史 |
| 非快进合并(--no-ff) | 创建合并提交,保留分支历史 | 有分支节点 |
推荐:公共分支使用
--no-ff,保留历史便于回溯。
4.2 冲突解决
冲突产生原因:合并时,同一文件同一位置有不同修改。
解决步骤:
# 1. 合并分支(产生冲突)
git merge dev
# 2. 查看冲突文件
git status
# 3. 手动编辑冲突文件
# 冲突标记格式:
<<<<<<< HEAD
当前分支的内容
=======
要合并分支的内容
>>>>>>> dev
# 4. 解决后添加到暂存区
git add <conflicted-file>
# 5. 提交合并结果
git commit -m "解决合并冲突"
冲突标记说明:
<<<<<<< HEAD到=======:当前分支(HEAD)的内容=======到>>>>>>> dev:要合并分支的内容
查看冲突详情:
五、Git 远程仓库
5.1 SSH 配置
优势:免密推送/拉取代码,安全性更高。
配置步骤:
# 1. 生成 SSH 密钥对
ssh-keygen -t ed25519 -C "your_email@example.com"
# 或使用 RSA(兼容旧系统)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# 2. 启动 SSH 代理
eval "$(ssh-agent -s)"
# 3. 添加私钥到代理
ssh-add ~/.ssh/id_ed25519
# 4. 查看公钥(复制到 GitHub/GitLab)
cat ~/.ssh/id_ed25519.pub
# 5. 测试连接
ssh -T git@github.com
ssh -T git@gitee.com
多仓库密钥配置(.ssh/config):
# GitHub
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
# Gitee
Host gitee.com
HostName gitee.com
User git
IdentityFile ~/.ssh/id_ed25519_gitee
5.2 远程仓库命令
推送拉取流程图:
fetch vs pull:
| 命令 | 说明 |
|---|---|
git fetch |
仅获取远程更新,不自动合并,可先查看再决定 |
git pull |
fetch + merge,自动合并到当前分支 |
5.3 .gitignore 配置
作用:指定 Git 忽略的文件,不纳入版本管理。
Java 项目模板:
# Compiled class file
*.class
# Log file
*.log
# Package Files
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
# IDE Files
.idea/
*.iml
.project
.classpath
.settings/
# Build Output
target/
build/
out/
# Dependencies (Maven/Gradle)
.mvn/
!**/src/main/**/target/
!**/src/test/**/target/
Python 项目模板:
# Byte-compiled / optimized
__pycache__/
*.py[cod]
# Virtual Environment
venv/
.venv/
env/
# IDE
.vscode/
.idea/
# Distribution
dist/
build/
*.egg-info/
# Logs
*.log
全局配置:
规则说明:
| 规则 | 说明 | 示例 |
|---|---|---|
# |
注释 | # 这是注释 |
* |
通配符 | *.log |
? |
单字符 | file?.txt |
! |
否定(不忽略) | !important.log |
/ |
目录分隔 | build/ |
** |
多级目录 | **/node_modules/ |
六、Git 高级操作
6.1 git rebase(变基)
作用:将当前分支的提交"重新应用"到目标分支上,使历史更线性整洁。
merge vs rebase:
| 对比项 | git merge | git rebase |
|---|---|---|
| 历史 | 保留分支历史,有合并提交 | 线性历史,无合并提交 |
| 提交数 | 新增合并提交 | 不新增,原提交被"重写" |
| 适用 | 公共分支合并 | 个人分支整理历史 |
交互式变基选项:
| 选项 | 说明 |
|---|---|
pick |
保留该提交 |
reword |
修改提交信息 |
edit |
编辑该提交 |
squash |
合并到前一个提交 |
drop |
删除该提交 |
注意:不要对已推送的公共分支执行 rebase,会改变历史影响他人。
6.2 git cherry-pick
作用:选择性将某个提交应用到当前分支。
# 应用单个提交
git cherry-pick <commit-id>
# 应用多个提交
git cherry-pick <commit1> <commit2>
# 应用提交范围
git cherry-pick <start-commit>..<end-commit>
场景:紧急 bug 在 dev 分支修复,需要单独应用到 main 分支。
6.3 撤销操作汇总
| 场景 | 命令 |
|---|---|
| 撤销工作区修改(未 add) | git checkout -- <file> 或 git restore <file> |
| 撤销暂存区(已 add,未 commit) | git reset HEAD <file> 或 git restore --staged <file> |
| 撤销提交(未 push) | git reset --soft HEAD^ |
| 撤销已推送提交 | git revert <commit> |
| 修改上次提交信息 | git commit --amend |
# Git 2.23+ 新命令(推荐)
git restore <file> # 撤销工作区修改
git restore --staged <file> # 撤销暂存区
git restore --source=<commit> <file> # 从指定提交恢复
七、Git 工作流
7.1 Git Flow
分支结构:
| 分支 | 说明 | 生命周期 |
|---|---|---|
main |
生产环境,仅接受 merge | 永久 |
develop |
开发主分支 | 永久 |
feature/* |
功能开发分支 | 临时,完成后合并到 develop |
release/* |
发布准备分支 | 临时,完成后合并到 main 和 develop |
hotfix/* |
紧急修复分支 | 临时,完成后合并到 main 和 develop |
适用场景:有明确发布周期的项目。
7.2 GitHub Flow
简化流程:
特点:
- 只有一个长期分支
main - 随时可以部署
- 通过 Pull Request 进行代码审查
适用场景:持续部署的项目、开源项目。
八、Git 提交规范
8.1 Commit Message 格式
8.2 Type 类型
| 类型 | 说明 |
|---|---|
feat |
新功能 |
fix |
修复 bug |
docs |
文档变更 |
style |
代码格式(不影响逻辑) |
refactor |
重构(既非新功能也非 bug 修复) |
perf |
性能优化 |
test |
增加测试 |
chore |
构建过程或辅助工具变动 |
revert |
回滚提交 |
build |
构建系统或外部依赖变更 |
ci |
CI 配置文件和脚本变更 |
8.3 示例
# 新功能
feat(user): add login functionality
# bug 修复
fix(api): fix null pointer exception in user service
# 文档
docs: update README with installation instructions
# 重构
refactor(config): simplify config loading logic
# 简单提交(无 scope)
fix: correct file extension check
8.4 最佳实践
- 使用祈使句:"add feature" 而非 "added feature"
- 首字母小写:"fix bug" 而非 "Fix bug"
- 首行不超过 50 字符
- Body 解释 what 和 why,而非 how
- 一个提交只做一件事
九、常见问题与排查
9.1 撤销最后一次提交
# 保留修改,仅撤销提交
git reset --soft HEAD^
# 撤销提交和暂存区,保留工作区
git reset --mixed HEAD^
# 撤销全部(修改丢失)
git reset --hard HEAD^
9.2 撤销已推送的提交
# 使用 revert(推荐,保留历史)
git revert <commit-id>
git push origin main
# 强制回退(危险,影响他人)
git reset --hard <commit-id>
git push origin main --force
已推送的提交建议用
revert,不要用reset --hard。
9.3 合并冲突解决
# 1. 合并产生冲突
git merge dev
# 2. 查看冲突文件
git status
# 3. 手动解决冲突,删除冲突标记
# 4. 添加并提交
git add .
git commit -m "解决合并冲突"
9.4 分支开发中途切换
# 当前分支修改未完成,需要切换分支
git stash # 暂存修改
git switch main # 切换分支
# 处理完其他任务后回来
git switch dev
git stash pop # 恢复修改
9.5 回退错误后的恢复
9.6 删除远程分支已删除的本地分支
9.7 大文件误提交处理
# 从历史中彻底删除大文件
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch path/to/large-file' \
--prune-empty --tag-name-filter cat -- --all
# 强制推送(危险操作)
git push origin --force --all
# 清理本地仓库
git gc --prune=now
十、面试高频考点
1. Git 核心概念
Q:Git 和 SVN 的区别?
| Git | SVN |
|---|---|
| 分布式,每个开发者有完整仓库 | 集中式,仅服务器有完整仓库 |
| 离线可工作 | 必须联网 |
| 分支操作轻量快速 | 分支较重 |
| 提交到本地再推送 | 直接提交到服务器 |
Q:工作区、暂存区、版本库的区别?
- 工作区:实际文件目录
- 暂存区:
git add后暂存的位置(Index) - 版本库:
git commit后存储的位置(.git目录)
2. 分支与合并
Q:git merge 和 git rebase 的区别?
| merge | rebase |
|---|---|
| 保留分支历史,有合并提交 | 线性历史,无合并提交 |
| 适合公共分支 | 适合个人分支清理历史 |
| 不改变原有提交 | "重写"提交历史 |
Q:什么是快进合并(Fast-forward)?
当目标分支没有新提交时,直接将当前分支指针移动到目标分支,无需创建合并提交。
3. 版本回退
Q:git reset 三种模式的区别?
| --soft | --mixed(默认) | --hard |
|---|---|---|
| 仅回退提交 | 回退提交和暂存区 | 回退全部 |
| 保留暂存区和工作区 | 保留工作区 | 清空工作区 |
Q:git reset 和 git revert 的区别?
| reset | revert |
|---|---|
| 删除提交历史 | 新建撤销提交,保留历史 |
| 适合本地未推送提交 | 适合已推送的提交 |
4. 其他
Q:HEAD 是什么?
HEAD 是一个指针,指向当前分支的最新提交。切换分支时 HEAD 指向新分支。
Q:git stash 的作用?
临时保存工作区修改,用于分支切换时暂存未完成的修改。
Q:.gitignore 不生效怎么办?
Q:如何撤销 git add?