本文不包括 Git 命令的介绍与使用,只分享 Git 的关键概念与 Github 项目的基本工作流程。作者相信先了解它们对后续的学习和工作大有裨益。(如有错误和建议请大家评论告知)

版本控制系统

VCS → Version Control System,版本控制系统 → 一个跟踪文件变化、记录修订情况、协助开发项目的系统。

分为 本地 VCS、集中式 VCS 和分布式 VCS:

  1. 本地 VCS——早期的版本控制系统,所有的版本信息都存储在本地计算机上。

    1. 有名的示例——RCS——在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。
    2. 缺点:无法支持多人协作,数据容易丢失。
  2. 集中式 VCS(Centralized Version Control System, CVCS):所有版本信息集中存储在一个中央服务器上,开发者通过客户端访问。
    1. 示例:SVN(Subversion)、CVS(Concurrent Versions System)、Perforce
    2. 缺点:
      1. 单点故障问题:如果中央服务器宕机或数据丢失,整个系统可能瘫痪,因为客户端只保存快照,而不记录版本信息。
      2. 开发者需要联网才能提交或创建分支。(没有网络几乎做不了任何事情)
  3. 分布式 VCS(Distributed Version Control System, DVCS):每个开发者都有一个完整的本地仓库,包含所有版本历史。
    1. 示例:Git、Mercurial
    2. 优点:
      1. 更高的容错性:即使中央服务器出现问题,开发者仍然可以从其他人的本地仓库恢复数据。
      2. 无需联网依赖中央服务器即可提交、创建分支。

Git 特点

了解 Git 的具体特点是十分必要的:

  1. 直接记录快照(snapshot),而非差异(delta)比较:其他 VCS(如 SVN、CVS、Perforce)保存的每个版本记录的是文件修改前后的差异,没修改就不记录。而 Git 每次保存版本都直接记录整个仓库的快照,当然没有修改的文件只是保留指向其存储的链接。
  2. 几乎所有操作都是本地的:因为 Git 在本地保留了版本历史,所以不需要像其他 VCS 一样连接服务器获取。
  3. Git 保证完整性:Git 中所有的数据在保存前会进行 SHA-1 校验和(40 位十六进制 hash 值)计算,校验和也是对应数据的引用。
  4. Git 通常只添加数据:Git 常规操作都只是往数据库添加数据,只要存在一次快照提交,就很难导致文件不可恢复。
  5. 三种状态:已修改(modified)、已暂存(staged)、已提交(commited):
    1. 已修改表示文件被修改但没被标记;
    2. 已暂存表示已修改文件被标记,下一次提交时会被保存到 Git 数据库;
    3. 已提交就是已暂存文件已经保存到 Git 数据库了。

工作区、暂存区和 Git 目录

工作区(Working Directory,叫 Working Tree 更好)是位于磁盘上的从 Git 数据库中提取出来的某个版本的内容,我们看见的、修改的文件就是在工作区。

暂存区(Staging Area)是 Git 目录下的一个叫做 index 的文件。

Git 仓库目录(.git Directory)(Repository)是一个隐藏的名为 .git 的文件夹,它保存了项目的元数据和对象数据库。克隆项目时克隆的就是这部分。

Git 底层对象

Git 的底层由以下四种对象构成,所有对象均通过 SHA-1 哈希值唯一标识:

  1. Blob 对象(二进制大对象):存储文件内容(不包含文件名、权限等元数据)。每个文件对应一个 Blob,内容相同则哈希值相同。
  2. Tree(目录结构):记录目录中的文件列表和子目录结构。包含文件名、权限、对应的 Blob 或子 Tree 的哈希值。
  3. Commit(提交):指向一个 Tree(项目快照)、父提交的哈希值、作者、提交信息等。形成链式结构,构成版本历史。
  4. Tag(标签):标记某个特定提交(如版本号 v1.0.0)。

一次提交的生成过程:修改文件 → 生成新 Blob → 更新 Tree → 创建 Commit 指向该 Tree 和父提交

Git 仓库结构

git init 时会创建一个.git 隐藏文件夹(即 Git 仓库,Git Repository),主要有以下内容:

  • objects:所有对象存储在 .git/objects 目录中,按哈希值前两位分目录存储。例如:哈希 a1b2c3... 的对象路径为 .git/objects/a1/b2c3...。对象内容经过压缩(使用 zlib 的 DEFLATE 算法)。
  • refs:存储指向分支、标签和远程仓库等数据的提交对象的指针。.git/refs/heads/ 文件存储指向的提交哈希值。
  • HEAD:.git/HEAD 文件存储当前分支的引用路径(如 ref: refs/heads/main)。(该分支会被提取到工作区供开发者修改)
  • config:项目的配置项。
  • hooks:客户端或服务端的钩子脚本。

分支与 HEAD

分支是一个指向某个提交的可移动指针(如 main 分支指向最新提交)。

HEAD 是一个特殊指针,指向当前所在的分支(或直接指向某个提交,即“分离头指针”状态)。当提交时,HEAD 指向的分支会自动向前移动。

分支就像是是贴在提交上的“便签纸”,HEAD 就是“你当前正在使用的便签纸”。

Git 提交信息约定(语义化提交)

当我们提交暂存区到 git 仓库时,需要写一个信息,是对这次提交的简要说明。

为什么需要约定化的提交信息?约定化的提交信息有利于提高历史可读性从而方便项目协作和管理、方便生成 CHANGELOG 和自动化版本号等。

较流行的提交信息约定有:Angular 和 Conventional Commits 的约定。

这里只介绍 Angular 提交信息约定,它被业界广泛使用。

格式:

<type 类型>(<scope 作用域>): <summary 摘要>    --组成-->   <header 头部>
<空行>
<body 正文>
<空行>
<footer 脚注>

规则:

  1. type(必填项):必须是下列值之一:

    1. feat:新增功能(对应语义化版本中的 MINOR)
    2. fix:修复 Bug(对应语义化版本中的 PATCH)
    3. docs:文档更新(如 API 文档、README)
    4. refactor:代码重构(既不新增功能,也不修复 Bug)
    5. test:测试相关(添加或修改测试代码)
    6. perf:性能优化
    7. ci:CI 配置修改(如 SauceLabs、GitHub Actions)
    8. build:构建系统或外部依赖的改动(如 npm、gulp)
  2. scope(可选项):一般是受影响的 npm 包的名称,也有例外情况:
    1. packaging:影响所有包的 npm 布局(如 package.json 全局修改)。
    2. changelog:更新 CHANGELOG.md。
    3. devtools:浏览器扩展变更。
    4. 空作用域:跨包变更(如全项目测试修复)或无明确范围(如文档拼写错误)。
  3. summary(必填项):
    1. 动词开头,使用现在时态的祈使句(如 add、fix、remove)。
    2. 首字母小写,结尾不加句号。
    3. 长度简洁。
  4. body(除 docs 类型外必填):
    1. 解释为什么要改动,对比旧行为与新行为。
    2. 使用现在时态的祈使句。
  5. footer(可选项):用于标注破坏性变更、弃用声明,以及关联相关的 Issue 或 PR。格式自行查阅 Angular 提交信息约定。
  6. revert commits:
revert: <原提交的 Header>
<空行>
This reverts commit <原提交 SHA>.
<回退原因>

Git 分布式工作模式

现在是时候加入 Git 中心服务器的角色进行讨论了。这会涉及到使用它与其他 developer 进行协作开发的流程或工作模式。

  1. 集中式工作流:

    1. 逻辑:所有开发者围绕一个中央仓库同步代码,类似传统集中式版本控制(如 SVN),但保留了 Git 的本地操作能力。
    2. 流程:
      1. 开发者从中央仓库获取最新代码。
      2. 在本地完成修改后,直接同步到中央仓库。
      3. 多人协作时需频繁同步中央仓库的变更,避免代码冲突。
  2. 功能分支协作模式:
    1. 逻辑:每个新功能或修复在独立分支中开发,完成后通过合并请求(Pull Request/Merge Request)将代码集成到主分支。
    2. 流程:
      1. 开发者从主分支创建独立分支进行开发。
      2. 开发完成后,将分支推送到远程仓库并申请合并。
      3. 团队成员通过代码评审讨论修改,确认后合并到主分支。
  3. 标准化分支模式(Git Flow):
    1. 逻辑:通过严格定义分支角色和生命周期,管理复杂项目的开发、测试和发布流程。
    2. 分支角色:
      1. 主分支:仅存放稳定版本(如正式环境代码)。
      2. 开发分支:集成所有新功能的日常开发主线。
      3. 临时分支:包括功能分支(开发新功能)、发布分支(测试版本)、热修复分支(紧急修复生产问题)。
    3. 流程:
      1. 新功能分支基于开发分支创建,完成后合并回开发分支。
      2. 发布时从开发分支创建测试分支,验证后合并到主分支并标记版本。
      3. 生产问题通过热修复分支快速处理。
  4. 开源协作模式(Forking):
    1. 逻辑:贡献者无权直接修改主仓库,需先复制(Fork)一份个人副本,修改后通过合并请求向主仓库提交代码。
    2. 流程:
      1. 贡献者复制主仓库到个人账号下。
      2. 在个人副本中开发完成后,向主仓库发起合并请求。
      3. 维护者审核代码后决定是否合并。
  5. 持续交付模式(GitHub Flow):
    1. 逻辑:强调主分支随时可发布,通过短周期功能分支快速迭代。
    2. 规则:
      1. 主分支始终保持可部署状态。
      2. 新功能通过小颗粒度分支开发,快速合并。
      3. 自动化测试和代码审查是合并的必要条件。

Git 裸仓库

远程仓库通常是裸仓库(bare repository)。

(1)什么是裸仓库?什么又是普通仓库?

  • 裸仓库(Bare Repository):一个没有工作目录的 Git 仓库,仅包含 Git 的版本控制数据(即 .git 目录的内容)。通常以 .git 结尾。
  • 普通仓库(Non-Bare Repository):包含工作目录(用户可见的文件)和 .git 目录(版本控制数据)。

(2) 为什么远程仓库通常是裸仓库?

  • 协作安全性:裸仓库无法直接修改文件(没有工作目录),避免多人同时操作导致冲突。开发者只能通过推送(push)或拉取(pull)同步代码,确保远程仓库的稳定性。
  • 节省资源:裸仓库无需维护工作目录的文件副本,仅存储 Git 元数据(提交历史、分支、标签等),节省存储空间。
  • 功能纯粹性:远程仓库的职责是作为代码的“中心枢纽”,不需要本地开发功能(如代码编辑、临时构建文件等)。

Git 使用的传输协议

Git - 协议

Git 通过多种传输协议实现仓库的远程通信,不同协议在安全性、效率和适用场景上各有特点。

以下是 Git 支持的主要传输协议及其核心特性:

  1. 本地协议:

    1. 介绍:通过本地文件系统路径直接访问远程仓库(如共享目录、NFS 挂载等),无需网络传输。远程仓库的形式通常是裸仓库(前面已介绍),存储在同一主机的另一目录中。
    2. 地址格式:file:///path/to/repo.git(速度较慢但数据更干净) 或直接使用路径 /path/to/repo.git(硬链接或直接复制,极快)。
    3. 特点:
      1. 最高速度:无需网络传输,适合局域网或本地开发。
      2. 零配置:简单快捷,无需服务器。
      3. 安全性低:依赖文件系统权限,不适合跨团队协作。
    4. 适用场景:个人开发、团队共享存储环境(如内网 NAS)。
  2. HTTP 协议:
    1. 介绍:通过 HTTP(S) 通信,支持智能 HTTP 协议(Smart HTTP,git 1.6.6 版本)和哑 HTTP 协议(Dumb HTTP)。现代 Git 服务(如 GitHub/GitLab)默认使用智能 HTTP 协议。
    2. 地址格式:https://github.com/user/repo.git 或 https://github.com/user/repo.git。
    3. 哑 HTTP 协议:
      1. Git 早期通过 HTTP 传输数据的一种简单实现方式。
      2. 只需部署静态文件,无需服务端 Git 支持,可通过普通静态 Web 服务器托管只读仓库。
      3. 不支持推送,无法动态优化传输。
      4. 数据全量下载,无压缩,耗时长、流量大。
    4. 智能 HTTP 协议:
      1. 运行在标准的 HTTP/S 端口(80/443)上并且可以使用各种 HTTP 验证机制。
      2. 身份验证灵活:支持用户名密码、OAuth、Token(如 GitHub Personal Access Token)。
      3. 数据增量压缩。
      4. 企业防火墙通常允许进入。
      5. 性能中等:比 SSH/Git 协议略慢,但可通过 HTTP/2 优化。
    5. 适用场景:公开/私有仓库托管(如 GitHub、GitLab)、企业级 Git 服务。
  3. SSH 协议:
    1. 介绍:基于 SSH 加密通道传输数据,使用公钥认证。
    2. 地址格式:git@github.com:user/repo.git。
    3. 特点:
      1. 高安全性:加密通信 + 密钥认证,适合敏感代码库。
      2. 免密码推送:配置 SSH 密钥后无需每次输入凭据。
      3. 性能优秀:压缩传输,速度接近 Git 协议。
      4. 权限管理:依赖服务器 SSH 账户权限。
    4. 适用场景:开发者个人推送权限、私有仓库托管。
  4. Git 协议:
    1. 介绍:专用轻量级协议,默认端口 9418,仅支持只读访问。
    2. 地址格式:git://github.com/user/repo.git。
    3. 特点:
      1. 极致速度:无加密开销,适合大规模公开仓库分发(如 Linux 内核)。
      2. 无身份验证:完全匿名访问,无法推送代码。
      3. 防火墙限制:可能被企业网络屏蔽。
    4. 适用场景:开源项目的公共只读镜像(如 GitHub 的 git:// 地址)。

如何对开源项目做出贡献

Git - 对项目做出贡献

(这也是前面提到的开源协作模式)

使用 Git 命令和 Github 前须了解的知识的更多相关文章

  1. github网站介绍、并使用git命令管理github(详细描述)

    本章学习: 1)熟悉github网站 2)通过git命令远程管理github, 3)git命令使用ssh key密钥无需输入账号密码 1.首先我们来熟悉github网站 1.1 注册github 登录 ...

  2. git命令,github

    1.git原理 2.git和svn的区别 SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把 ...

  3. ***Linux下使用git命令及github项目

    在linux下搭建git环境1.创建Github账号,https://github.com2.Linux创建SSH密钥: ssh-keygen  ##一直默认就可以了 3.将公钥加入到Github账户 ...

  4. git命令与github使用

    GitHub 是一个类似 SourceForge 的免费项目管理及分享的服务平台,要想使用 github,用户可以免费注册成为 github 注册用户,之后使用git命令进行操作使用.github 的 ...

  5. 如何使用git命令从github上取得项目

    首先我们要安装git, git官网:https://git-scm.com/点击打开链接 拉取项目步骤详解 新建文件夹,最好取为项目英文名***Project 进入文件夹,空白处右键,选择git Ba ...

  6. 使用Git命令从Github下载代码仓库

    Github作为最大的开源代码仓库,也是作为版本控制工具,简直就是程序员的天堂,是一座挖掘不尽的宝藏.现在讲解一下如何把一个Github上的项目下载到本地,也就是在本地也建立一个项目仓库,以后进行项目 ...

  7. git命令,github网站以及sourceTree用法详解

    1.git下载安装 这里只是windows安装方法: 进入这个网址:http://msysgit.github.com/,点击下载,就会下载下来一个exe文件,双击打开,安装即可 完成安装之后,就可以 ...

  8. 使用git命令从github上clone项目

    首先创建本地仓库(实际上就是创建一个文件夹,放项目代码),然后cd进文件夹, 初始化空的git仓库 注意:这里不初始化也是可以clone的 然后git clone url(url表示项目网址) 然后就 ...

  9. 一条 Git 命令减少了一般存储空间,我的服务器在偷着笑

    元旦不是搭建了一个<Java 程序员进阶之路>的网站嘛,其中用到了 Git 来作为云服务器和 GitHub 远程仓库之间的同步工具. 作为开发者,相信大家都知道 Git 的重要性.Git ...

  10. git命令合集及github的克隆推送

    安装git 初始化仓库 提交相关 撤销相关 远程推送 分支相关 其他 遇到的错误 github的克隆上传 此文章只是对命令的一个统计,起备忘和复习git只是的作用,不建议从没接触过git的同学通过它来 ...

随机推荐

  1. CF926 Div.2

    C. Sasha and the Casino 赌场规则:如果下注 \(y(y > 0)\) 元,如果赢了则除了 \(y\) 元外,额外获得 \(y \times (k - 1)\) 元,否则则 ...

  2. 2023-05 多校联合训练 ZJNU站 正式赛

    Scarlett的三元组 有一个长度为 \(n\) 的序列 \(a_1,a_2,\cdots,a_n\),试问有多少个三元组 \((a_i,a_j,a_k)\) 满足: \(1 \le i \lt j ...

  3. linux 软连接使用

    转载请注明出处: 在Linux系统中,软连接(Symbolic Link)是一种特殊类型的文件链接,类似于Windows系统中的快捷方式.它允许用户通过一个文件路径访问另一个文件或目录,而不需要拥有原 ...

  4. 他又又来了,c#开源sql解析引擎类库【SqlParser.Net 1.0】正式发布,它可以帮助你简单快速高效的解析和处理sql

    背景 hi 大家好,我是三合,在过往的岁月中,我曾经想过要写以下这些工具 写一个通过拦截业务系统所有sql,然后根据这些sql自动分析表与表,字段与字段之间是如何关联的工具,即sql血缘分析工具 想着 ...

  5. 02C++顺序结构(1)

    1.C++程序的样子 2.流 输出流 COUT<< 3.一个实例及解析 4.小结 头文件的解释 头文件是C++程序对其他程序的引用,就是让编译器的预处理器把这个输入输出流的标准文件iost ...

  6. Qt编写物联网管理平台43-告警短信转发

    一.前言 系统在运行过程中,会实时采集设备的数据,当采集到的数据发生报警后,可以将报警信息以短信的形式发送给指定的管理员(可以是多个),这样管理员就算不在现场,也能第一时间知道哪里发生了报警,可以紧急 ...

  7. Qt开发经验小技巧186-190

    关于是使用QList还是QVector的问题,一直是众多Qter的选择问题,主要是这两个玩意提供的的接口函数基本一致,比如插入.删除.取值等. 大多数情况下可以用QList.像append.prepe ...

  8. URL中文转换成类似%E6%96%97%E7%A0%B4(url编码)格式

    要将汉字转换成编码格式拼接成请求,没怎么搞过,一番查找,最终确定使用C# 里的WebUtility using System.Net; var a = WebUtility.UrlEncode(&qu ...

  9. UML之集合类型

    无论何时当我们要使用一个多值对象时,我们必须要清楚两个问题,一是这些值的顺序重要吗?二是允许重复值的存在吗?在编程语言中还会有其他的明确的信息,在UML中,只需明确这两个问题的答案即可确定对应的集合类 ...

  10. Intellij IDEA部署Web项目到tomcat时提示:Error:Cannot build Artifact ':war exploded' because it is included into a circul

    在Idea中使用Maven创建父子工程,第一个Model的那个项目可以很好的运行,在创建一个Model运行时报这个错.原因是tomcat部署了多个Web项目,可能最开始是两个项目的配置文件混用用,最后 ...