版本控制
什么是版本控制
版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。 除了项目源代码,你可以对任何类型的文件进行版本控制。
为什么要版本控制
有了它你就可以将某个文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态,你可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。
本地版本控制系统
许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。
为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。
集中化的版本控制系统
接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作? 于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。
集中化的版本控制系统都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。
这么做虽然解决了本地版本控制系统无法让在不同系统上的开发者协同工作的诟病,但也还是存在下面的问题:
- 单点故障: 中央服务器宕机,则其他人无法使用;如果中心数据库磁盘损坏又没有进行备份,你将丢失所有数据。本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。
- 必须联网才能工作: 受网络状况、带宽影响。
分布式版本控制系统
于是分布式版本控制系统(Distributed Version Control System,简称 DVCS)面世了。 Git 就是一个典型的分布式版本控制系统。
这类系统,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
分布式版本控制系统可以不用联网就可以工作,因为每个人的电脑上都是完整的版本库,当你修改了某个文件后,你只需要将自己的修改推送给别人就可以了。但是,在实际使用分布式版本控制系统的时候,很少会直接进行推送修改,而是使用一台充当"中央服务器"的东西。这个服务器的作用仅仅是用来方便"交换"大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
分布式版本控制系统的优势不单是不必联网这么简单,后面我们还会看到 Git 极其强大的分支管理等功能。
认识 Git
Git是一个开源的分布式版本控制系统(Distributed Version Control System,简称DVCS),它可以有效、高速地处理从很小到非常大的项目版本管理。以下是对Git的详细介绍:
一、Git的核心功能
- 版本控制:Git能够追踪项目从开始到结束的整个过程,对编程人员而言,版本控制技术是团队协作开发的桥梁,有助于多人协作同步进行大型项目开发。版本控制系统的核心任务是查阅项目历史操作记录,实现协同开发。
- 团队协作:通过Git,团队成员可以方便地共享代码、查看历史提交记录、比较不同版本之间的差异,并协同进行项目开发。
二、Git的特点
- 分布式:Git采用分布式版本控制,每个开发者都可以在本地拥有一个完整的代码仓库,包含项目的全部历史记录和分支信息。这意味着开发者可以在离线状态下工作,并且多个开发者可以同时进行不同的开发工作。
- 快速高效:Git优化了存储和传输过程,使用了快速的算法,能够高效地处理大型项目和大量数据。同时,Git的操作命令也非常快速,使开发者能够快速进行版本控制操作。
- 分支管理:Git的分支管理功能非常强大,可以轻松创建、合并和删除分支。这使得团队协作更加灵活和高效,每个分支都可以独立进行开发,不影响其他分支的代码。
- 完整性保证:Git使用哈希值来标识版本,每一次提交的代码都会计算一个唯一的哈希值,保证了版本的完整性和可追溯性。
- 多种协议支持:Git支持多种协议和方式进行代码的传输和交换,包括HTTP、SSH等,团队成员可以方便地通过这些协议进行代码共享和协作开发。
- 缓存机制:Git引入了缓存机制,将文件的变化在内存中暂存,只有在需要提交时才会写入磁盘,这大大提高了文件的读写效率。
- 灵活的工作流程:Git提供了灵活的工作流程,可以根据团队的需求配置不同的工作流程,适应不同的开发模式和项目需求。
三、Git的基本使用
- 下载安装 :可以从Git的官方下载地址下载并安装Git。
- 基本配置:安装完成后,需要进行一些全局设置,如用户名和邮箱。这些配置信息将用于记录每次提交的作者信息。
- 创建本地仓库 :在本地初始化一个Git仓库,或从远程仓库克隆一个仓库。初始化仓库后,会在当前目录中看到一个
.git
文件夹,这表示Git仓库已成功创建。 - 文件操作 :使用Git进行文件操作时,通常需要先将文件添加到暂存区(使用
git add
命令),然后提交到仓库中(使用git commit
命令)。此外,还可以使用git status
查看文件状态,使用git log
查看提交历史记录等。 - 分支管理 :使用
git branch
命令可以查看、创建和删除分支。使用git checkout
命令可以切换分支。Git的分支机制非常强大,支持快速创建、切换和合并分支。 - 远程仓库操作 :Git支持远程仓库的操作,包括将本地仓库推送到远程仓库(使用
git push
命令),以及从远程仓库拉取代码(使用git pull
命令)等。
四、Git的应用场景
Git广泛应用于各种规模的软件开发项目中,特别是在团队协作开发、代码版本控制、代码审查、持续集成等方面发挥着重要作用。通过Git,团队成员可以高效地管理和跟踪代码的修改历史,确保代码的质量和稳定性。
[Git 简史](#Git 简史)
Linux 内核项目组当时使用分布式版本控制系统 BitKeeper 来管理和维护代码。但是,后来开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统,而且对新的版本控制系统做了很多改进。
[Git 与其他版本管理系统的主要区别](#Git 与其他版本管理系统的主要区别)
Git 在保存和对待各种信息的时候与其它版本控制系统有很大差异,尽管操作起来的命令形式非常相近,理解这些差异将有助于防止你使用中的困惑。
下面我们主要说一个关于 Git 与其他版本管理系统的主要差别:对待数据的方式。
Git 采用的是直接记录快照的方式,而非差异比较。我后面会详细介绍这两种方式的差别。
大部分版本控制系统(CVS、Subversion、Perforce、Bazaar 等等)都是以文件变更列表的方式存储信息,这类系统将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异。
具体原理如下图所示,理解起来其实很简单,每当我们提交更新一个文件之后,系统都会记录这个文件做了哪些更新,以增量符号 Δ(Delta)表示。
我们怎样才能得到一个文件的最终版本呢?
很简单,高中数学的基本知识,我们只需要将这些原文件和这些增加进行相加就行了。
这种方式有什么问题呢?
比如我们的增量特别特别多的话,如果我们要得到最终的文件是不是会耗费时间和性能。
Git 不按照以上方式对待或保存数据。 反之,Git 更像是把数据看作是对小型文件系统的一组快照。 每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个 快照流。
[Git 的三种状态](#Git 的三种状态)
Git 有三种状态,你的文件可能处于其中之一:
- 已提交(committed):数据已经安全的保存在本地数据库中。
- 已修改(modified):已修改表示修改了文件,但还没保存到数据库中。
- 已暂存(staged):表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
由此引入 Git 项目的三个工作区域的概念:Git 仓库(.git directory) 、工作目录(Working Directory) 以及 暂存区域(Staging Area) 。
基本的 Git 工作流程如下:
- 在工作目录中修改文件。
- 暂存文件,将文件的快照放入暂存区域。
- 提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。
[Git 使用快速入门](#Git 使用快速入门)
[获取 Git 仓库](#获取 Git 仓库)
有两种取得 Git 项目仓库的方法。
- 在现有目录中初始化仓库: 进入项目目录运行
git init
命令,该命令将创建一个名为.git
的子目录。 - 从一个服务器克隆一个现有的 Git 仓库:
git clone [url]
自定义本地仓库的名字:git clone [url] directoryname
记录每次更新到仓库
- 检测当前文件状态 :
git status
- 提出更改(把它们添加到暂存区 ):
git add filename
(针对特定文件)、git add *
(所有文件)、git add *.txt
(支持通配符,所有 .txt 文件) - 忽略文件 :
.gitignore
文件 - 提交更新:
git commit -m "代码提交信息"
(每次准备提交前,先用git status
看下,是不是都已暂存起来了, 然后再运行提交命令git commit
) - 跳过使用暂存区域更新的方式 :
git commit -a -m "代码提交信息"
。git commit
加上-a
选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过git add
步骤。 - 移除文件 :
git rm filename
(从暂存区域移除,然后提交) - 对文件重命名 :
git mv README.md README
(这个命令相当于mv README.md README
、git rm README.md
、git add README
这三条命令的集合)
推送改动到远程仓库
将本地的改动推送到远程仓库是Git版本控制中的一个常见操作。以下是详细的步骤:
前提条件
- 已安装Git:确保你的计算机上已经安装了Git。
- 已配置Git:全局配置了用户名和邮箱,以便在提交时能够记录作者信息。
- 已克隆远程仓库 :通过
git clone
命令克隆了远程仓库到本地,或者已经在本地初始化了Git仓库并添加了远程仓库的URL。
步骤
-
查看当前分支 :
使用
git branch
命令查看当前所在的分支。通常,你会在一个特定的功能分支或主分支(如main
或master
)上进行开发。 -
添加改动到暂存区 :
使用
git add
命令将改动(新文件、修改过的文件、删除的文件)添加到暂存区。你可以添加单个文件、多个文件或整个目录。例如:git add . # 添加当前目录下的所有改动
-
提交改动 :
使用
git commit
命令将暂存区的改动提交到本地仓库。你需要提供一个提交信息来描述这次改动的内容。例如:git commit -m "描述改动的提交信息"
-
推送改动到远程仓库 :
使用
git push
命令将本地仓库的改动推送到远程仓库。你需要指定远程仓库的名称(通常是origin
)和你要推送的分支名称。例如:git push origin main # 将main分支的改动推送到远程仓库
如果你正在一个非主分支(如功能分支)上工作,并且希望将这个分支也推送到远程仓库(如果它还不存在的话),你可以这样做:
git push -u origin feature-branch # -u选项表示设置上游分支,以便以后可以直接使用git push推送
-
验证推送 :
推送完成后,你可以登录到远程仓库的Web界面(如GitHub、GitLab等),查看是否成功推送了改动。