GIT-基础架构
简介
什么是Git
Git 是一个开源的分布式版本控制系统,用以高效处理从很小到非常大的项目版本管理。一个原始 Git 版本仓库,可以让其他主机克隆这个原始版本仓库,从而使得一个 Git 版本仓库可以同时分布到不同的主机上,并且每台主机的版本库都是一样的,并没有主次之分,极大的保证了数据的安全性。
什么是GitHub
GitHub 是一个面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名GitHub。GitHub 可以提供给用户空间创建 Git 仓储,保存用户的一些数据文档或者代码等。GitHub 作为开源代码库以及版本控制系统,目前拥有 140 多万开发者用户。随着越多的应用程序转移到了云上,GitHub 已经成为了管理软件开发以及发现已有代码的首选方法。GitHub 可以托管各种 Git 库,并提供一个 Web 界面,但与其它像 SourceForge 或 Google Code 这样的服务不同,GitHub 的独特卖点在于从另外一个项目进行分支的简易性。为一个项目贡献代码非常简单:首先点击项目站点的“fork”的按钮,然后将代码检出并将修改加入到刚才分出的代码库中,最后通过内建的“pull request”机制向项目负责人申请代码合并。
什么是GitLab
GitLab 是一个基于 Git 的项目管理软件,用于仓库管理系统的开源项目。使用 Git 作为代码管理工具,并在此基础上搭建起来 Web 服务。
什么是Gitee
码云Gitee是国内开软件以及私有化软件项目托管平台。
Git的功能特性
Git 是关注于文件数据整体的变化,直接会将文件提交时的数据保存成快照,而非仅记录差异内容,并且使用 SHA-1 加密算法保证数据的完整性。主要功能如下:
- 克隆数据库版本:从服务器上克隆版本数据库(包括代码和版本信息)到本机上;
- 提交代码:在本机上自己创建的分支上提交代码;
- 合并分支:在本机上合并分支;
- 拉取合并分支:新建一个分支,把服务器上最新版的代码 Fetch 下来,然后跟自己的主分支合并;
- 代码冲突解决:一般开发者之间解决冲突的方法,开发者之间可以使用 pull 命令解决冲突,解决完冲突之后再向主开发者提交补丁。
分布式架构设计
仓库独立性
- 全量复制:每个
git clone操作会下载完整的仓库数据(包括所有提交历史、分支、标签),形成独立的本地仓库(.git目录),支持离线操作(如提交、分支切换)。 - 冗余备份:任意本地仓库均可作为灾难恢复节点,中央服务器故障时可通过本地仓库重建数据。
- 全量复制:每个
数据同步机制
- 推送(Push):传输本地新增对象(Commit/Tree/Blob)到远程仓库,并更新远程引用(如
refs/heads/main)。 - 拉取(Pull):
git fetch下载远程对象到本地,更新远程跟踪分支(如origin/main);git merge将变更合并到当前分支。
- 推送(Push):传输本地新增对象(Commit/Tree/Blob)到远程仓库,并更新远程引用(如
区域工作流程
工作区(Working Directory)
- 用户直接编辑文件的目录(如修改
main.py),文件状态分为Untracked(未跟踪)或Modified(已修改)。
- 用户直接编辑文件的目录(如修改
暂存区(Staging Area)
- 索引文件(
.git/index)存储待提交内容,支持选择性提交(git add -p可部分暂存)。 - 作用:构建下一次提交的 Tree 对象(
git commit时基于索引生成)。
- 索引文件(
本地仓库(Local Repository)
git commit将暂存区内容转换为 Tree 对象,创建 Commit 对象,并更新分支指针(如refs/heads/feature指向新 Commit 哈希)。
graph LR
subgraph WORKSPACE[工作区]
style WORKSPACE fill:#eee,stroke:#666,stroke-width:1px
direction LR
WFILE1[文件]
WFILE2[文件]
WFILE3[文件]
WFILE4[文件]
end
subgraph REPO[Git仓库]
direction TB
style REPO fill:#e6f7ff,stroke:#3399ff,stroke-width:2px
subgraph STAGING[暂存区]
style STAGING fill:#e0e0e0,stroke:#666,stroke-width:1px
SFILE[文件]
end
subgraph VERSION[版本库]
style VERSION fill:#ffecd9,stroke:#ff9900,stroke-width:1px
V1[版本1]
V2[版本2]
V3[版本3]
end
end
WFILE1 -- "git add" --> SFILE
WFILE2 -- "git add" --> SFILE
WFILE3 -- "git add" --> SFILE
WFILE4 -- "git add" --> SFILE
SFILE -- "git commit" --> V3
V2 --> V3
V1 --> V2
classDef fileStyle fill:#4CAF50,stroke:#2E7D32,stroke-width:1px,color:white
class WFILE1,WFILE2,WFILE3,WFILE4,SFILE,V1,V2,V3 fileStyle版本控制核心机制
分支实现原理
- 分支本质是指向 Commit 的轻量级指针(约 41 字节),存储在
.git/refs/heads/目录中。 HEAD引用(.git/HEAD文件)指向当前活动分支。
- 分支本质是指向 Commit 的轻量级指针(约 41 字节),存储在
合并与冲突解决
- 快进合并(Fast-Forward):目标分支是源分支的直接祖先时,直接移动指针。
- 三方合并(Three-Way Merge):冲突时插入
<<<<<<< HEAD/=======/>>>>>>> feature标记,需手动解决。
历史追溯(DAG)
- 提交通过父指针形成有向无环图(DAG),支持多父提交(表示合并)。
- 命令:
git log --graph可视化 DAG,git blame逐行追溯修改者。
SVN与Git的最主要的区别?
- SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就纳闷了。
- Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。既然每个人的电脑都有一个完整的版本库,那多个人如何协作呢?比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了
.git目录解析
.git是 Git 版本控制的核心数据库,存储项目的所有元数据和对象数据。
关键文件
| 文件 | 路径 | 作用 |
|---|---|---|
HEAD | .git/HEAD | 指向当前分支的最新提交(如 ref: refs/heads/main)或直接指向提交哈希(分离头状态) |
config | .git/config | 存储仓库级配置(如远程仓库 URL、分支跟踪),优先级高于全局配置 |
index | .git/index | 二进制文件,记录暂存区的文件状态(路径、哈希、时间戳),可通过 git ls-files --stage查看 |
核心子目录
| 目录 | 路径 | 内容与功能 |
|---|---|---|
objects/ | .git/objects/ | 存储所有 Git 对象: - Blob:文件内容 - Tree:目录结构 - Commit:提交信息 对象按 SHA-1 前两位哈希分目录存储(如 5f/1dda1...) |
refs/ | .git/refs/ | 存储引用指针: - heads/:本地分支(如 main) - tags/:标签(如 v1.0) - remotes/:远程跟踪分支(如 origin/main) |
hooks/ | .git/hooks/ | 存放钩子脚本(如 pre-commit、post-receive),用于在特定 Git 操作前后触发自定义逻辑(如代码检查、自动部署) |
logs/ | .git/logs/ | 记录引用变更历史(如分支移动、提交),支持 git reflog恢复误删提交 |
GIT 部署
Windows
下载地址:https://git-scm.com/downloads
Linux
dnf -y install gitGIT 操作命令
仓库初始化与克隆
# 初始化新仓库
git init
# 克隆远程仓库
git clone <仓库URL> # 例如:git clone https://github.com/user/repo.git配置与用户信息
# 设置全局用户名和邮箱
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
# 查看当前配置
git config --list
git config --global --list # 全局
git config --local --list # 本地
# 删除全局单个配置项
git config --global --unset user.name "name"
git config --global --unset user.email "email"
# 删除本地仓库配置
git config --unset user.name "name"
git config --unset user.email "email"- global生成的配置文件在
~/.gitconfig
文件操作与提交
# 添加文件到暂存区
git add <文件名> # 添加单个文件
git add . # 添加所有修改
# 提交到本地仓库
git commit -m "提交说明"
# 查看状态与差异
git status # 查看文件状态
git diff [filename] # 查看未暂存的修改
git diff --cached [filename] # 查看已暂存的修改分支管理
# 创建与切换分支
git branch <分支名> # 创建分支
git checkout <分支名> # 切换分支
git checkout -b <新分支名> # 创建并切换分支
# 合并与删除分支
git merge <分支名> # 合并分支到当前分支
git branch -d <分支名> # 删除本地分支
# 查看分支
git branch # 查看本地分支
git branch -a # 查看所有分支(含远程)远程仓库操作
# 关联远程仓库
git remote add origin <远程仓库URL>
# 推送与拉取
git push origin <分支名> # 推送本地分支到远程
git pull origin <分支名> # 拉取远程分支并合并
# 查看远程仓库
git remote -vLog 历史记录
git log # 显示完整提交历史(时间倒序)
git log --oneline # 仅显示提交哈希和消息(缩写为7位哈希)
git log --graph --decorate # 可视化分支合并与分叉
git log --author="John" # 显示特定作者的提交
git log --since="2023-01-01" --until="2023-12-31" # 日期区间筛选
git log --grep="bugfix" # 搜索包含"bugfix"的提交
git log --no-merges # 排除合并提交
git log --stat # 展示每次提交的文件修改统计(增删行数)
git log -p # 显示每次提交的具体代码变更(补丁形式)
git log --follow <filename> # 包含文件重命名历史
# 简洁查看
git log --pretty=oneline --decorate
# 查看改变详情
git log --pretty=oneline -p
# 查看所有操作历史(包括回滚前的)
git reflog
# 回滚历史记录
git reflog hash
--pretty=oneline:将每个提交压缩为单行输出,格式为:
[完整哈希值] [提交信息]。例如:
ac8085fd32d9f6fba258191dab3b318aca2c46a6 test a--decorate:显示指向提交的引用(如分支、标签),格式为
(引用1, 引用2, ...)。例如:
(HEAD, master)表示当前提交被HEAD和master分支引用
撤销与回退
# 撤销工作区修改
git checkout -- <文件名>
# 撤销暂存区修改
git reset HEAD <文件名>
# 回退到指定提交
git reset --hard <commit-hash> # 彻底回退
git revert <commit-hash> # 创建新提交以撤销旧提交标签管理
# 创建与推送标签
git tag <标签名> # 创建轻量标签
git tag -a <标签名> -m "描述" # 创建附注标签
git push origin <标签名> # 推送标签到远程
# 删除标签
git tag -d <标签名> # 删除本地标签
git push origin --delete <标签名> # 删除远程标签临时保存与恢复
# 暂存当前修改
git stash
# 恢复暂存内容
git stash pop # 恢复并删除最近一次暂存
git stash apply # 恢复但不删除暂存记录以上命令覆盖了 Git 的常用操作场景,适用于日常开发中的版本控制需求。更多高级命令可参考 https://git-scm.com/doc。
