一、Git 简介
Git 是一个开源的分布式版本控制系统,由 Linus Torvalds 于 2005 年为管理 Linux 内核开发而创建。它可以记录文件的每一次修改,让你随时回到历史版本,也方便多人协同开发。
1.1 什么是版本控制
版本控制用于记录文件内容随时间的变化,主要解决以下问题:
- 修改出错后可以回退到之前的版本
- 可以查看每一次修改的内容、时间和作者
- 多人同时修改同一项目时,可以合并各自的工作成果
1.2 集中式与分布式
| 对比项 | 集中式(如 SVN) | 分布式(Git) |
|---|---|---|
| 版本库位置 | 中央服务器 | 每个开发者本地都有完整版本库 |
| 离线工作 | 无法提交 | 可以随时在本地提交 |
| 分支 | 创建成本较高 | 轻量,创建和切换非常快 |
| 故障影响 | 服务器故障时影响大 | 每个副本都是完整备份 |
1.3 Git 的三个区域
Git 中的文件分布在三个区域:
- 工作区(Working Directory):你平时编辑文件的目录
- 暂存区(Stage / Index):临时存放准备提交的修改
- 版本库(Repository):
.git目录中保存的全部历史记录
1 | 工作区 --git add--> 暂存区 --git commit--> 版本库(.git) |
1.4 文件的四种状态
- 未跟踪(Untracked):新建的文件,Git 尚未记录
- 已修改(Modified):已被跟踪的文件内容发生了变化
- 已暂存(Staged):已通过
git add放入暂存区 - 已提交(Committed):已通过
git commit保存到版本库
二、安装与配置
2.1 安装 Git
- Windows:从 https://git-scm.com/download/win 下载安装包,安装后可使用 Git Bash 运行命令。
- macOS:执行
brew install git,或执行xcode-select --install安装命令行工具。 - Debian / Ubuntu:执行
sudo apt update && sudo apt install git。 - CentOS / RHEL / Fedora:执行
sudo dnf install git(旧系统使用yum)。
安装完成后检查版本:
1 | git --version |
2.2 配置用户信息
每次提交都会记录作者信息,首次使用前需要配置用户名和邮箱:
1 | git config --global user.name "Your Name" |
Git 的配置分为三个级别:
| 级别 | 参数 | 作用范围 | 配置文件位置 |
|---|---|---|---|
| 系统级 | --system | 所有用户 | /etc/gitconfig |
| 用户级 | --global | 当前用户的所有仓库 | ~/.gitconfig |
| 仓库级 | --local(默认) | 当前仓库 | .git/config |
查看配置:
1 | git config --list # 查看所有配置 |
常用的其他配置:
1 | git config --global core.editor "code --wait" # 指定默认编辑器 |
三、Git 基本操作
3.1 创建仓库:git init
在一个空目录或已有项目目录中初始化仓库,会生成隐藏的 .git 目录:
1 | mkdir runoob-git |
执行后会输出类似 Initialized empty Git repository in .../.git/ 的提示。
3.2 添加到暂存区:git add
1 | git add README.md # 添加指定文件 |
3.3 提交修改:git commit
1 | git commit -m "添加 README 文件" |
提交信息建议遵循以下习惯:
- 第一行简要概括本次修改(建议不超过 50 个字符)
- 必要时空一行后补充详细说明,解释“为什么这样改”
- 每次提交只做一件相对独立的事情
3.4 查看状态:git status
1 | git status |
该命令会列出已暂存、已修改但未暂存以及未跟踪的文件,是使用 Git 时最常用的命令之一。
3.5 查看差异:git diff
1 | git diff # 工作区 与 暂存区 的差异 |
3.6 查看提交历史:git log
1 | git log # 显示完整提交历史 |
--oneline 的输出示例:
1 | 9e8f7a1 (HEAD -> main) 修改登录逻辑 |
四、版本回退
4.1 HEAD 与提交编号
HEAD指向当前所在的提交(即当前分支的最新位置)HEAD^表示上一个版本,HEAD^^表示上上个版本HEAD~3表示往前数第 3 个版本- 每个提交都有一个 40 位的 SHA-1 编号,通常只需使用前 7 位即可
4.2 git reset:回退版本
1 | git reset --soft HEAD~1 # 回退到上一版本,修改保留在暂存区 |
注意:--hard 会丢弃工作区和暂存区中所有未提交的修改,执行前请确认没有需要保留的内容。4.3 git reflog:找回“丢失”的版本
回退后想再回到较新的版本,但找不到提交编号时,可以通过 reflog 查看 HEAD 的移动记录:
1 | git reflog |
4.4 git revert:安全地撤销某次提交
git reset 会改写历史,不适合用于已经推送到远程的提交。git revert 会新建一个提交来抵消指定提交的改动,历史记录保持完整:
1 | git revert 9e8f7a1 |
五、撤销修改与删除文件
5.1 撤销工作区的修改
文件被修改但还没有 git add 时,可以用以下命令恢复为最近一次提交的内容:
1 | git restore README.md # 新版写法 |
5.2 撤销暂存区的修改
已经 git add 但还没有提交时,先把文件移出暂存区,再撤销工作区的修改:
1 | git restore --staged README.md # 新版写法:仅取消暂存 |
5.3 删除与移动文件
1 | git rm old.txt # 删除文件并将删除操作加入暂存区 |
删除文件后需要执行 git commit 才会真正记录到历史中。如果误删了已提交的文件,可以用 git restore --source=HEAD~1 文件名 或 git checkout <commit-id> -- 文件名 找回。
六、远程仓库
6.1 配置 SSH 密钥
使用 SSH 方式连接 GitHub、Gitee 等平台时,需要先配置公钥:
1 | ssh-keygen -t ed25519 -C "you@example.com" |
6.2 添加远程仓库:git remote
1 | git remote add origin git@github.com:username/runoob-git.git |
origin 是默认的远程仓库名称,可以自定义。
6.3 推送:git push
1 | git push -u origin main # 首次推送,并建立本地 main 与远程 main 的关联 |
6.4 克隆:git clone
1 | git clone git@github.com:username/runoob-git.git |
6.5 拉取:git fetch 与 git pull
git fetch:只下载远程的新提交,不修改当前工作内容git pull:相当于git fetch加上git mergegit pull --rebase:下载后使用变基的方式整合,保持历史更整洁
1 | git fetch origin |
七、分支管理
7.1 分支的概念
分支本质上是一个指向某个提交的可移动指针。HEAD 指向当前所在的分支。创建分支只是新增一个指针,因此速度很快。在分支上的新提交会让该分支指针向前移动,不影响其他分支。
7.2 创建、切换与删除分支
1 | git branch # 查看本地分支(当前分支前有 * 标记) |
7.3 合并分支:git merge
1 | git switch main |
- 快进合并(Fast-forward):目标分支没有新提交时,直接移动指针,不产生新的合并提交。
- 非快进合并(--no-ff):始终生成一个合并提交,历史中可以看出分支合并的过程。
1 | git merge --no-ff -m "合并 dev 分支的新功能" dev |
7.4 解决冲突
当两个分支修改了同一文件的同一位置时,合并会产生冲突,Git 会在文件中标记出差异:
1 | <<<<<<< HEAD |
解决冲突的步骤:
- 打开冲突文件,手动保留正确的内容并删除
<<<<<<<、=======、>>>>>>>标记 - 执行
git add 文件名标记冲突已解决 - 执行
git commit完成合并
可以使用 git status 查看所有冲突文件,使用 git merge --abort 放弃本次合并。
7.5 分支管理策略
在团队中,通常会约定如下分支模型:
main:随时可以发布的稳定版本,只接受合并,不直接开发dev:日常开发的集成分支feature/*:新功能分支,完成后合并回devbugfix/*:普通缺陷修复分支hotfix/*:紧急修复线上问题的分支,从main创建,修复后同时合并到main和devrelease/*:发布准备分支
建议合并时使用 --no-ff,以保留分支的开发历史。
7.6 临时保存现场:git stash
正在开发时需要切换分支处理紧急问题,但当前修改还没完成,可以使用 stash 临时保存:
1 | git stash # 保存当前未提交的修改 |
7.7 多人协作流程
一个典型的协作流程如下:
1 | git clone git@github.com:team/project.git |
如果推送时被拒绝(提示 non-fast-forward),通常是远程有新的提交,先执行 git pull 整合后再推送即可。
7.8 变基:git rebase
rebase 可以把当前分支的提交“搬到”另一个分支的最新提交之后,使历史呈线性:
1 | git switch feature/login |
注意:不要对已经推送到公共远程并被他人使用的分支执行 rebase,否则会导致他人的历史冲突。八、标签管理
标签(Tag)通常用于标记重要的版本,例如 v1.0.0。
1 | git tag # 查看所有标签 |
九、忽略文件:.gitignore
项目中有些文件(如编译产物、日志、依赖目录、密码配置)不应该被提交,可以在仓库根目录创建 .gitignore 文件进行配置:
1 | # 忽略所有 .log 文件 |
说明:
- 以
#开头的行为注释 - 以
/结尾表示目录 - 以
!开头表示取消忽略 - 已经被 Git 跟踪的文件不会因为加入
.gitignore而被忽略,需要先执行git rm --cached 文件名
检查某个文件为什么被忽略:
1 | git check-ignore -v build/app.js |
GitHub 官方仓库中提供了各种语言和框架的 .gitignore 模板,可以直接参考。
十、配置别名
可以为常用命令设置简短的别名,提高效率:
1 | git config --global alias.st status |
设置后即可使用 git st、git lg 等命令。
十一、完整示例
下面演示从创建项目到推送远程的完整流程:
1 | # 1. 创建并初始化项目 |
十二、常用命令速查表
| 类别 | 命令 | 说明 |
|---|---|---|
| 配置 | git config --global user.name "名字" | 设置用户名 |
| 创建 | git init | 初始化仓库 |
| 创建 | git clone <url> | 克隆远程仓库 |
| 查看 | git status | 查看工作区状态 |
| 查看 | git diff | 查看未暂存的差异 |
| 查看 | git log --oneline | 查看提交历史 |
| 暂存 | git add <file> | 添加到暂存区 |
| 提交 | git commit -m "说明" | 提交到版本库 |
| 回退 | git reset --hard <commit> | 回退到指定版本 |
| 回退 | git revert <commit> | 生成一个撤销提交 |
| 撤销 | git restore <file> | 撤销工作区修改 |
| 撤销 | git restore --staged <file> | 取消暂存 |
| 分支 | git switch -c <branch> | 创建并切换分支 |
| 分支 | git merge <branch> | 合并指定分支到当前分支 |
| 分支 | git branch -d <branch> | 删除分支 |
| 临时 | git stash / git stash pop | 临时保存与恢复修改 |
| 远程 | git remote add origin <url> | 添加远程仓库 |
| 远程 | git push -u origin <branch> | 推送并关联分支 |
| 远程 | git pull | 拉取并合并远程更新 |
| 标签 | git tag -a <tag> -m "说明" | 创建附注标签 |
十三、常见问题
1. 提交信息写错了怎么办?
如果是最近一次提交且尚未推送,可以执行 git commit --amend -m "新的说明"。
2. 提交了不该提交的文件怎么办?
如果尚未推送,可以执行 git reset --soft HEAD~1 撤销提交,再用 git rm --cached 移出该文件,并将其加入 .gitignore 后重新提交。
3. 推送时提示 non-fast-forward 怎么办?
说明远程有本地没有的提交。先执行 git pull(或 git pull --rebase)整合远程代码,解决冲突后再推送。
4. 误删了分支怎么办?
可以通过 git reflog 找到该分支最后的提交编号,然后执行 git branch 分支名 提交编号 恢复。
5. 提示 LF will be replaced by CRLF 怎么办?
这是 Windows 与 macOS / Linux 换行符不同导致的提示,可以通过设置 core.autocrlf 统一处理(参见第二章)。
6. 不小心把密码提交到了仓库怎么办?
仅删除文件并提交是不够的,历史中仍然保留着该内容。应立即修改密码,并使用 git filter-repo 等工具清理历史,然后强制推送。
以上内容覆盖了 Git 的核心用法。建议结合实际项目多加练习,熟练掌握 add、commit、branch、merge 和 push 这几个最常用的命令。