417 lines
6.4 KiB
Markdown
417 lines
6.4 KiB
Markdown
# Git(版本控制系统)
|
|
|
|
Git 是一个免费、开源的分布式版本控制系统,用来记录代码历史、多人协作和版本回退。
|
|
|
|
- 官网:https://git-scm.com/
|
|
- 中文教程:https://git-scm.com/book/zh/v2
|
|
|
|
## 安装
|
|
|
|
### Windows
|
|
|
|
下载安装包并按默认步骤安装:
|
|
|
|
```text
|
|
https://git-scm.com/
|
|
```
|
|
|
|
### Linux
|
|
|
|
```bash
|
|
sudo apt update
|
|
sudo apt install git
|
|
```
|
|
|
|
检查是否安装成功:
|
|
|
|
```bash
|
|
git --version
|
|
```
|
|
|
|
## 基础配置
|
|
|
|
查看当前配置:
|
|
|
|
```bash
|
|
git config --list
|
|
```
|
|
|
|
设置用户名和邮箱:
|
|
|
|
```bash
|
|
git config --global user.name "你的用户名"
|
|
git config --global user.email "你的邮箱"
|
|
```
|
|
|
|
设置默认分支名:
|
|
|
|
```bash
|
|
git config --global init.defaultBranch main
|
|
```
|
|
|
|
设置代理:
|
|
|
|
```bash
|
|
git config --global http.proxy http://127.0.0.1:7890
|
|
git config --global https.proxy http://127.0.0.1:7890
|
|
```
|
|
|
|
取消代理:
|
|
|
|
```bash
|
|
git config --global --unset http.proxy
|
|
git config --global --unset https.proxy
|
|
```
|
|
|
|
## 核心概念
|
|
|
|

|
|
|
|
Git 管理代码时,通常会经过四个位置:
|
|
|
|
- 工作区:你正在编辑的目录和文件。
|
|
- 暂存区:准备提交的改动。
|
|
- 本地仓库:保存在电脑上的提交历史。
|
|
- 远程仓库:GitHub、Gitee、GitLab 等代码托管平台。
|
|
|
|
## 日常流程
|
|
|
|
:::tip 常用顺序
|
|
写代码前先拉取,写完后查看状态、暂存、提交、推送。
|
|
:::
|
|
|
|
```bash
|
|
# 拉取远程最新代码
|
|
git pull
|
|
|
|
# 查看当前改动
|
|
git status
|
|
|
|
# 查看具体修改
|
|
git diff
|
|
|
|
# 暂存全部改动
|
|
git add .
|
|
|
|
# 提交
|
|
git commit -m "说明本次修改"
|
|
|
|
# 推送
|
|
git push
|
|
```
|
|
|
|
克隆远程仓库:
|
|
|
|
```bash
|
|
git clone 仓库地址
|
|
```
|
|
|
|
初始化本地仓库:
|
|
|
|
```bash
|
|
git init
|
|
```
|
|
|
|
## 分支
|
|
|
|
```bash
|
|
# 查看本地分支
|
|
git branch
|
|
|
|
# 查看本地和远程分支
|
|
git branch -a
|
|
|
|
# 创建并切换分支
|
|
git checkout -b feature/login
|
|
|
|
# 切换分支
|
|
git checkout main
|
|
|
|
# 拉取远程分支
|
|
git fetch
|
|
|
|
# 合并分支
|
|
git merge feature/login
|
|
|
|
# 删除本地分支
|
|
git branch -d feature/login
|
|
|
|
# 删除远程分支
|
|
git push origin --delete feature/login
|
|
```
|
|
|
|
也可以使用新版命令:
|
|
|
|
```bash
|
|
git switch main
|
|
git switch -c feature/login
|
|
```
|
|
|
|
## 远程仓库
|
|
|
|
```bash
|
|
# 查看远程仓库
|
|
git remote -v
|
|
|
|
# 添加远程仓库
|
|
git remote add origin 仓库地址
|
|
|
|
# 修改远程仓库地址
|
|
git remote set-url origin 新仓库地址
|
|
|
|
# 首次推送并关联上游分支
|
|
git push -u origin main
|
|
```
|
|
|
|
## 撤销与恢复
|
|
|
|
:::warning
|
|
撤销命令会改变工作区或提交历史。执行前先用 `git status` 和 `git diff` 确认当前状态。
|
|
:::
|
|
|
|
### 撤销未暂存的文件修改
|
|
|
|
```bash
|
|
git restore 文件名
|
|
```
|
|
|
|
撤销当前目录所有未暂存修改:
|
|
|
|
```bash
|
|
git restore .
|
|
```
|
|
|
|
### 取消暂存
|
|
|
|
```bash
|
|
git restore --staged 文件名
|
|
```
|
|
|
|
取消全部暂存:
|
|
|
|
```bash
|
|
git restore --staged .
|
|
```
|
|
|
|
### 修改最后一次提交信息
|
|
|
|
```bash
|
|
git commit --amend -m "新的提交说明"
|
|
```
|
|
|
|
### 回退到某个提交
|
|
|
|
保留代码改动,只撤销提交记录:
|
|
|
|
```bash
|
|
git reset --soft 提交ID
|
|
```
|
|
|
|
撤销提交和暂存,但保留工作区改动:
|
|
|
|
```bash
|
|
git reset --mixed 提交ID
|
|
```
|
|
|
|
:::danger
|
|
`git reset --hard` 会丢弃提交后的工作区改动,除非明确知道后果,否则不要使用。
|
|
:::
|
|
|
|
## 临时保存改动
|
|
|
|
当前代码还没写完,但需要切换分支时,可以用 stash。
|
|
|
|
```bash
|
|
# 保存当前改动
|
|
git stash
|
|
|
|
# 查看保存列表
|
|
git stash list
|
|
|
|
# 恢复最近一次保存,并从 stash 列表删除
|
|
git stash pop
|
|
|
|
# 恢复最近一次保存,但保留 stash 记录
|
|
git stash apply
|
|
|
|
# 删除最近一次 stash
|
|
git stash drop
|
|
```
|
|
|
|
## 标签
|
|
|
|
```bash
|
|
# 创建标签
|
|
git tag v1.0.0
|
|
|
|
# 推送标签
|
|
git push origin v1.0.0
|
|
|
|
# 查看标签
|
|
git tag
|
|
|
|
# 删除本地标签
|
|
git tag -d v1.0.0
|
|
|
|
# 删除远程标签
|
|
git push origin --delete v1.0.0
|
|
```
|
|
|
|
## 命令速查表
|
|
|
|

|
|
|
|
## 子模块
|
|
|
|
主仓库只记录子模块的仓库地址和具体提交版本,子模块本身仍然是一个独立仓库。
|
|
|
|
:::tip
|
|
修改子模块代码后,先进入子模块提交并推送,再回到主仓库提交子模块引用变化。
|
|
:::
|
|
|
|
### 添加子模块
|
|
|
|
```bash
|
|
git submodule add <url> <path>
|
|
```
|
|
|
|
示例:
|
|
|
|
```bash
|
|
git submodule add https://github.com/oneao/docusaurus code/docusaurus
|
|
```
|
|
|
|
添加后,主仓库会生成 `.gitmodules` 文件。
|
|
|
|
### 初始化和更新子模块
|
|
|
|
```bash
|
|
git submodule update --init --recursive
|
|
```
|
|
|
|
### 拉取包含子模块的仓库
|
|
|
|
```bash
|
|
git clone --recurse-submodules 仓库地址
|
|
```
|
|
|
|
如果克隆时忘了加参数:
|
|
|
|
```bash
|
|
git submodule update --init --recursive
|
|
```
|
|
|
|
### 更新子模块到远程最新提交
|
|
|
|
```bash
|
|
git submodule update --remote --merge
|
|
```
|
|
|
|
### 移除子模块
|
|
|
|
```bash
|
|
git submodule deinit -f 子模块路径
|
|
git rm -f 子模块路径
|
|
```
|
|
|
|
然后提交 `.gitmodules` 和主仓库的变更。
|
|
|
|
## 常见问题
|
|
|
|
### push 之前未 pull
|
|
|
|
报错通常类似:
|
|
|
|
```bash
|
|
! [rejected] main -> main (fetch first)
|
|
error: failed to push some refs
|
|
```
|
|
|
|
原因是远程仓库已有你本地没有的提交。先拉取,再推送:
|
|
|
|
```bash
|
|
git pull
|
|
git push
|
|
```
|
|
|
|
如果产生冲突,先解决冲突,再提交和推送。
|
|
|
|
:::warning
|
|
不要随意使用 `git push -f`,它可能覆盖他人的远程提交。
|
|
:::
|
|
|
|
### 合并冲突
|
|
|
|
当多人修改同一文件的同一位置,Git 无法自动合并,会出现冲突标记:
|
|
|
|
```text
|
|
<<<<<<< HEAD
|
|
本地内容
|
|
=======
|
|
远程内容
|
|
>>>>>>> 分支或提交ID
|
|
```
|
|
|
|
处理步骤:
|
|
|
|
1. 打开冲突文件,保留正确内容,删除冲突标记。
|
|
2. 暂存已解决的文件。
|
|
3. 提交并推送。
|
|
|
|
```bash
|
|
git add 冲突文件
|
|
git commit -m "解决冲突"
|
|
git push
|
|
```
|
|
|
|
### 修改文件但 git status 显示未修改
|
|
|
|
可能原因:
|
|
|
|
- 只修改了换行符或编码。
|
|
- 编辑器保存规则导致内容没有真正变化。
|
|
- 改动发生在未被 Git 跟踪的目录。
|
|
|
|
排查:
|
|
|
|
```bash
|
|
git status
|
|
git diff
|
|
git ls-files 文件名
|
|
```
|
|
|
|
### 误删文件
|
|
|
|
文件已被 Git 跟踪,但还没有提交删除时,可以恢复:
|
|
|
|
```bash
|
|
git restore 文件名
|
|
```
|
|
|
|
如果删除已经被暂存,先取消暂存,再恢复:
|
|
|
|
```bash
|
|
git restore --staged 文件名
|
|
git restore 文件名
|
|
```
|
|
|
|
恢复当前目录下所有未提交的误删文件:
|
|
|
|
```bash
|
|
git restore .
|
|
```
|
|
|
|
### 本地分支落后远程
|
|
|
|
```bash
|
|
git fetch
|
|
git status
|
|
git pull
|
|
```
|
|
|
|
如果只是想查看远程有哪些更新:
|
|
|
|
```bash
|
|
git log --oneline --decorate --graph --all -20
|
|
```
|