Git 概述
版本控制系统
版本控制系统是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。
- 本地版本控制系统
- 在本地保存文件的修订版本
- 缺点:无法跨设备协作,数据容易丢失
- 集中式版本控制系统(CVCS)
- 如 SVN、CVS
- 单一中央服务器存储所有版本
- 缺点:单点故障,必须联网才能工作
- 分布式版本控制系统(DVCS)
- 如 Git、Mercurial
- 每个客户端都保存完整的代码库镜像
- 优点:离线工作、速度快、安全性高
Git 的核心优势
- 分布式架构:每个开发者都有完整的仓库副本
- 快速高效:大部分操作在本地执行,速度极快
- 分支管理强大:创建、切换、合并分支非常轻量
- 数据完整性保证:使用 SHA-1 哈希算法确保数据完整性
- 快照而非差异:Git 保存的是文件快照,而非文件差异
Git 的工作原理
三个工作区域
Git 本地有三个工作区域:
- 工作区(Working Directory)
- 暂存区(Staging Area / Index)
- 临时存放改动的地方
- 通过
git add 将文件添加到这里
- 版本库(Repository / HEAD)
- Git 正式保存数据的地方
- 通过
git commit 将暂存区内容提交到这里
文件状态流转
文件在 Git 中有四种状态:
- Untracked(未跟踪):新创建的文件,Git 还未跟踪
- Modified(已修改):已跟踪的文件被修改,但未暂存
- Staged(已暂存):已修改的文件被添加到暂存区
- Committed(已提交):已暂存的文件被提交到版本库
状态转换流程:
1 2 3 4 5
| Untracked → (git add) → Staged → (git commit) → Committed ↓ Modified ← (修改文件) ↓ (git add) → Staged
|
安装配置
安装 Git
Linux 安装
1 2 3 4 5 6 7 8
| sudo apt-get install git
sudo yum install git
git --version
|
macOS 安装
1 2 3 4 5
| brew install git
xcode-select --install
|
Windows 安装
下载 Git for Windows 安装包:https://git-scm.com/install/windows
初始配置
安装完成后,需要配置用户信息,这些信息会出现在每次的 Git 提交中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
git config --list git config user.name git config user.email
|
常用配置项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| git config --global core.editor vim
git config --global merge.tool vimdiff
git config --global core.autocrlf input git config --global core.autocrlf true
git config --global color.ui true
git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit git config --global alias.st status git config --global alias.lg "log --oneline --graph --decorate"
git config --global credential.helper store
git config --global credential.helper cache git config --global credential.helper 'cache --timeout=3600'
|
基本操作
创建仓库
初始化新仓库
1 2 3 4 5
| git init
git init project-name
|
克隆现有仓库
1 2 3 4 5 6 7 8 9 10 11 12 13
| git clone <repository-url>
git clone <repository-url> <directory-name>
git clone https://github.com/user/repo.git git clone https://github.com/user/repo.git my-project
|
查看状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| git status
git status -s
|
暂存文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| git add <file>
git add .
git add *.txt
git add -i
git add hello.txt
git add src/
git add -A
|
提交更改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| git commit -m "commit message"
git commit -am "message"
git commit --amend
git commit
|
提交历史
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| git log
git log --oneline
git log --graph
git log --stat
git log --author="name"
git log --since="2 weeks ago" git log --until="2024-01-01"
git log -n 5
git log --oneline --graph --all -n 10
|
提交规范
使用规范的提交消息格式,便于自动化生成变更日志。
格式模版
1 2 3 4 5 6 7 8
| <type>(<scope>): <description>
[optional body]
[optional footer(s)]
1. type、scope、description:是必需的 2. body、footer:是可选的
|
常用类型
1 2 3 4 5 6 7 8 9
| `feat`:新功能 `fix`:修复 bug `docs`:文档更新 `style`:代码格式(不影响代码运行) `refactor`:代码重构 `test`:测试相关 `chore`:构建过程或辅助工具变动 `perf`:性能优化 `ci`:CI 配置相关
|
提交示例
1 2 3 4 5 6
| feat(auth): add login functionality
add JWT authentication update user model
Closes #123
|
撤销操作
撤销工作区修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| git checkout -- <file>
git restore <file>
git restore hello.txt git restore .
|
撤销暂存
1 2 3 4 5 6 7 8
| git reset HEAD <file>
git restore --staged <file>
git restore --staged hello.txt
|
修改最近一次提交
1 2 3 4 5 6 7 8 9 10 11
| git commit --amend -m "new message"
git add forgotten-file.txt git commit --amend --no-edit
|
回退版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| git reset --hard HEAD^
git reset --hard HEAD~N
git reset --hard <commit-hash>
git reset --soft <commit-hash>
git reset --mixed <commit-hash>
git reset --hard <commit-hash>
|
分支管理
分支是指向某个提交的指针,Git 的分支非常轻量,创建和切换几乎瞬间完成。
- HEAD 指针:指向当前所在的分支
- master/main 分支:默认主分支
- 分支本质:只是一个包含 40 个字符的 SHA-1 校验和的文件
查看分支
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| git branch
git branch -v
git branch -a
git branch --merged
git branch --no-merged
|
创建分支
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| git branch <branch-name>
git checkout -b <branch-name>
git switch -c <branch-name>
git branch feature-login git checkout -b feature-login git switch -c feature-login
|
切换分支
1 2 3 4 5 6 7 8 9 10
| git checkout <branch-name>
git switch <branch-name>
git switch main git switch feature-login
|
删除分支
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| git branch -d <branch-name>
git branch -D <branch-name>
git branch -d feature-login git branch -D feature-old
|
合并分支
合并分支
1 2 3 4 5 6 7 8 9 10
| git switch main
git merge <branch-name>
git switch main git merge feature-login
|
合并类型
- Fast-forward(快进合并)
- 当目标分支是当前分支的直接祖先时
- 只是移动指针,不创建新的合并提交
- Three-way merge(三方合并)
解决冲突
当两个分支修改了同一文件的同一部分时,会产生冲突。
1 2 3 4 5
| 解决步骤: 1. 查看冲突文件:`git status` 2. 手动编辑文件,解决冲突标记(`<<<<<<<`、`=======`、`>>>>>>>`) 3. 标记解决:`git add <file>` 4. 完成合并:`git commit`
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| git status
git add conflicted-file.txt git commit -m "resolve merge conflict"
git merge --abort
|
变基操作
Rebase 基础
变基可以将一系列提交重新应用到另一个分支上,保持线性历史。
1 2 3 4 5 6 7
| git rebase <branch-name>
git switch feature git rebase main
|
交互式变基
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| git rebase -i HEAD~N
git rebase -i <commit-hash>
|
Merge vs Rebase
| 特性 |
Merge |
Rebase |
| 历史记录 |
保留完整历史 |
保持线性历史 |
| 适用场景 |
公共分支 |
私有分支 |
| 安全性 |
更安全 |
可能丢失历史 |
| 协作友好 |
适合团队协作 |
适合个人开发 |
1 2 3 4
| 细节注意: 1. **不要在公共分支上使用 rebase** 2. rebase 会改写历史,已经推送的提交不要 rebase 3. 个人特性分支可以使用 rebase 保持整洁
|
分支策略
Git Flow
适合长期维护的项目,有明确的发布周期。
1 2 3 4 5 6
| 分支类型: - `master/main`:生产环境分支 - `develop`:开发分支 - `feature/*`:功能分支 - `release/*`:发布分支 - `hotfix/*`:紧急修复分支
|
GitHub Flow
适合持续部署的项目,简单灵活。
1 2 3 4 5
| 规则: - 只有一个主分支(main) - 从 main 创建特性分支 - 通过 Pull Request 合并到 main - 合并后立即部署
|
Trunk Based Development
适合大型团队,强调快速迭代。
1 2 3 4
| 特点: - 所有人都在主干上开发 - 特性通过特性开关控制 - 频繁小步提交
|
远程仓库
查看远程仓库
1 2 3 4 5
| git remote
git remote -v
|
添加远程仓库
1 2 3 4 5 6 7 8 9 10 11 12 13
| git remote add <name> <url>
git remote set-url <name> <new-url>
git remote remove <name>
git remote add origin https://github.com/user/repo.git git remote set-url origin https://github.com/user/new-repo.git
|
推送代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| git push <remote> <branch>
git push -u <remote> <branch>
git push --all <remote>
git push --force git push --force-with-lease
git push origin main git push -u origin feature-login
|
拉取代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| git pull
git pull --rebase
git fetch
git fetch --all
git fetch origin
git pull origin main git fetch origin git merge origin/main
|
标签管理
标签用于标记重要的版本节点,如发布版本。
创建标签
1 2 3 4 5 6 7 8
| git tag v1.0
git tag -a v1.0 -m "version 1.0"
git tag -a v1.0 <commit-hash> -m "version 1.0"
|
查看标签
1 2 3 4 5 6 7 8
| git tag
git tag -l "v1.*"
git show v1.0
|
推送标签
1 2 3 4 5
| git push origin v1.0
git push origin --tags
|
删除标签
1 2 3 4 5
| git tag -d v1.0
git push origin --delete v1.0
|
高级功能
储藏工作进度
当需要切换分支但工作未完成时,可以使用储藏。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| git stash
git stash save "work in progress"
git stash list
git stash pop
git stash pop stash@{0}
git stash apply
git stash drop stash@{0}
git stash clear
git stash show stash@{0}
git stash show -p stash@{0}
|
清理未跟踪文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| git clean -n
git clean -f
git clean -fd
git clean -i
|
查看差异
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| git diff
git diff --staged git diff --cached
git diff <commit1> <commit2>
git diff main develop
git diff <file>
git diff --stat
|
查找提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| git log --grep="keyword"
git log --author="name"
git log -S "function_name"
git blame <file>
git log --follow <file>
git log --grep="fix bug" git log -S "console.log" git blame src/app.js
|
选择提交
选择性地应用某个提交到当前分支。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| git cherry-pick <commit-hash>
git cherry-pick <commit1> <commit2>
git cherry-pick <commit1>..<commit2>
git cherry-pick -n <commit-hash>
|
子模块
子模块允许在一个 Git 仓库中嵌入另一个 Git 仓库。
添加子模块
1 2 3 4 5
| git submodule add <url> <path>
git submodule add https://github.com/user/lib.git libs/mylib
|
更新子模块
1 2 3 4 5 6 7 8 9 10 11
| git submodule init
git submodule update
git submodule update --init --recursive
git submodule foreach git pull
|
删除子模块
1 2 3 4 5 6 7 8
| git submodule deinit <path>
git rm <path>
rm -rf .git/modules/<path>
|
工具与优化
.gitignore 规则
创建 .gitignore 文件来指定哪些文件应该被 Git 忽略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| # 注释以 # 开头
# 忽略所有 .log 文件 *.log
# 忽略 node_modules 目录 node_modules/
# 忽略 build 目录 build/
# 例外规则:不忽略 important.log !important.log
# 忽略特定文件 config.local.json
# 忽略所有以 temp 开头的文件 temp*
# 忽略所有 .class 文件(Java) *.class
# 忽略 IDE 配置 .vscode/ .idea/ *.swp
# 细节注意: # 1. `.gitignore` 只对未跟踪的文件生效 # 2. 已跟踪的文件需要在 `.gitignore` 中添加后,先移除跟踪:`git rm --cached <file>` # 3. 可以使用多个 `.gitignore` 文件,放在不同目录下
|
全局忽略文件
1 2 3 4 5
| touch ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global
|
Hooks 钩子
Git Hooks 是在特定事件发生时自动执行的脚本。
客户端钩子
位于 .git/hooks/ 目录:
pre-commit:提交前执行,可用于代码检查
commit-msg:提交消息验证
post-commit:提交后执行
pre-push:推送前执行
post-checkout:切换分支后执行
服务端钩子
pre-receive:接收推送前执行
update:更新引用前执行
post-receive:接收推送后执行
例:创建 pre-commit 钩子进行代码检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| cd .git/hooks
cat > pre-commit << 'EOF'
npm run lint if [ $? -ne 0 ]; then echo "代码检查失败,提交中止" exit 1 fi EOF
chmod +x pre-commit
|
错误处理
误删提交
1 2 3 4 5
| git reflog
git reset --hard <commit-hash>
|
推送了敏感信息
1 2 3 4 5 6 7 8 9 10
| git filter-branch --force --index-filter \ 'git rm --cached --ignore-unmatch path/to/file' \ --prune-empty --tag-name-filter cat -- --all
|
合并冲突频繁
- 定期从主分支同步代码
- 使用
git pull --rebase 保持线性历史
- 分解大功能为小任务
- 加强团队沟通,避免多人修改同一文件
大文件导致仓库膨胀
1 2 3 4 5 6
| git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
git lfs track "*.psd" git lfs track "*.mp4"
|
报错处理
💗💗 git 报错信息:SSL certificate problem: certificate has expired 解决方案
1 2 3 4 5
| 使用git时报错,错误信息如下: unable to access 'https:/xxxxxxx.git/': SSL certificate problem: certificate has expired
修改配置:忽略SSL证书验证 git config --global http.sslVerify false
|
学习资源
- 视频
- 【尚硅谷】5h打通Git全套教程丨2021最新IDEA版:
https://www.bilibili.com/video/BV1vy4y1s7k6
- 书籍
- Pro Git 书籍(中文版):
https://git-scm.com/book/zh/v2
- 猴子都能懂的 Git 入门:
https://backlog.com/git-tutorial/cn/
- GitHub 漫游指南:
https://github.phodal.com/
- 文档
- Git 官方文档:
https://git-scm.com/doc
- GitHub 官方文档:
https://docs.github.com/cn
- 游戏
- Learning Git Branching:
https://learngitbranching.js.org/?locale=zh_CN
- Git 可视化学习:
https://learngitbranching.js.org