# Git 基础:生成版本、撤消操作、版本重置、忽略文件

TIP

从本节内容开始,正式进入 Git 从入门到实践的完整系统学习了,这是所有编程开发者的必备技能。

帮助团队和个人建立完整系统的代码协作管理平台,包括大家经常看到的开源项目是如何进行代码管理 和 协作的,以及自己独立完成发布 和 建立标准的体系等。

本节重点学习 Git 核心基础与实战,内容主要包括以下几方面:

  • 了解 Git 是什么、Git 的安装与配置、如何使用 Git 管理项目
  • 认识 Git 的三大区域及如何生成版本
  • Git 撤消操作,包括撤消提交、撤消暂存、撤消文件修改
  • Git 版本重置的三种方式
  • 添加 Git 忽略文件及文件编写的格式规则
  • 分支的创建、切换、删除、合并操作
  • Git 远程仓库创建、删除、推送、克隆、拉取等操作
  • 单人开发、团队内协作开发、跨团队协作开发或为开源贡献自己的代码

# 一、Git 前世今生

TIP

深入浅出 Git 是什么、什么是版本控制、版本控制的发展史及相关配置信息

# 1、Git 是什么

TIP

Git 是一种分布式版本控制系统,用于管理软件项目的源代码。它是由 Linux 之父 Linus Torvalds**(李纳斯·托沃兹)**开发的,并已经成为了现代软件开发领域中最流行的版本控制系统之一。

为了更好的理解什么是分布式版本控制系统,我们从什么是版本控制开始说,然后再了解版本控制的发展史,在发展史中了解分布式版本控制系统及他的优点。

# 2、什么是版本控制

TIP

版本控制最主要的功能就是追踪文件的变更。它将什么时候、什么人更改了文件的什么内容等信息忠实地了已录下来,然后生成不同的版本。

我们可以在任何时候通过版本回溯到生成此版本时所在的状态。

下面举一个简单的版本控制的例子

比如你正在为公司写一个双十一活动策划方案,那你就会遇到下面这样的情况,从你写活动方案到活动方案正式被确定,中间可能有 n 个版本,如下图:

image-20231205234757423

注:

一开始,你写好了活动策划的第一稿,然后交给老板审核,老板觉得其中有些地方不好,需要删除再修改。但你担心删除这些内容后,万一老板后面又要加上,那怎么办呢?于时你在原有基础上复制了一份,重新命名后保存起来,然后再在现有文档基础上再做修改。

之后,你一直重复上面的流程很多次,你的文档库就变成了上图所示的样子。

在最后一次修改时,老板说,你之前有一稿中写的......这个点还不错,你把那个点加到现在内容中,就可以定稿了。但你记不清那个内容是在哪一稿中,于是你就一个一个打开之前的文档来找,这个查找过程是非常辛苦的,如果之前版本很多的话,那这个过程肯定会让你骂娘。

以上提到我们每修改一次内容,就需要先将原有文档复制一份,然后取个名字保存起来,再在现有的文档上来修改的这种做法,就是最原始的版本控制的方式,我们也称其为手动版本控制。

通过上面例子,我们知道版本控制记录了文件的变化,有了版本就相当于有了后悔药,我们想在某个时刻回到之前的某个版本的状态,直接找到对应版本的文档即可。

如果没有本版控制,我们想要找到之前的内容,那肯定是不可能的,只能重新再写一次。

# 3、版本控制发展史

TIP

本版控制从某种程度上来说,经历了以下四个阶段:

  • 手动版本控制(拷贝+改名)
  • 本地版本控制
  • 集中式版本控制
  • 分布式版本控制

以下关于版本控制的内容匀来自于 Git 官网 - 关于版本控制 (opens new window)

# 3.1、手动版本控制

TIP

手动版本控制就是我们前面提到的通过手动的复制整个文件或文件夹,然后改名加上备注等方式来区分不同的版本。

# 3.2、本地版本控制

TIP

许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。

为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。

local

其中最流行的一种叫做 RCS,现今许多计算机系统上都还看得到它的踪影。 RCS (opens new window) 的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。

注:

本地版本控制系统是没有办法做多个协作开发,如果别人要和你协作开发一个项目,那只能从你电脑上拷贝一份到他的电脑,开发完再传送给你,你再将他的和你的合并。

# 3.3、集中式版本控制系统

TIP

为了让不同的人可以协作开发同一个项目,于时就诞生了集中式版本控制系统。

集中式版本控制系统会有一个单一的集中管理的服务器,所有项目的版本都保存在这个服务器中,所有协作的人都要通过客户端连到这台服务器,取出最新的文件或者提交更新。

centralized

注:

这种做法带来了许多好处,特别是相较于老式的本地 VCS 来说。 现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。

事分两面,有好有坏。 这么做最显而易见的缺点是中央服务器的单点故障。 如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。 如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据——包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。

本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。

# 3.4、分布式版本控制系统

TIP

于是分布式版本控制系统(Distributed Version Control System,简称 DVCS)面世了。 在这类系统中,像 Git、Mercurial 以及 Darcs 等,客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录。

这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。

distributed

注:

更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。

你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。

# 4、Git 的发展史

TIP

同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。

Linux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002 年间)。 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。

到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds 李纳斯·托沃兹)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。 他们对新的系统制订了若干目标:

  • 速度
  • 简单的设计
  • 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
  • 完全分布式
  • 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)

自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统

# 5、为什么要学习 Git

TIP

  • 版本控制必不可少
  • Git 非常流行(很多人,很多公司都在学习,如果不学习,到了公司就没办法胜任)
  • Git 易学易用
  • Git 自身非常强大

# 5、Git 的安装

TIP

我们进到 Git 的官网:https://git-scm.com/ (opens new window) ,在官网右下角点击下载与你电脑相匹配的 Git 版本

image-20231122220402739

image-20231122220659699

下载到本地后,我们只需双击软件,就可以直接进入安装流程。按提示点击下一步,至到软件安装完成即可。

温馨提示:

在安装Git时,进入到下图所示的步骤时,我们可以把Git的默认编辑器修改为VSCode编辑器,这样在我们后面提交代码时,如果发生冲突需要修改代码时,会自动在VSCode编辑器中打开,提示用户做相关修改。

image-20231123000851035

# 6、初次运行 Git 前的配置

TIP

安装完 Git 之后,要做的第一件事就是设置你的用户名和邮箱。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改:

你的疑问:你可能会想,为什么需要设置用户名和邮箱 ?

我们每一次生成的项目版本都会记录一些信息,里面应该包含当前项目的代码,还应该包含是谁提交的,我们应该通过什么方式可以联系到这个提交人。其它人在看这个代码的时候,如果觉得有问题就可以通过这个联系方式联系到我。

所以 Git 也是这么设计的,在提交信息生成版本时,一定要有提交人和提交人的联系方式。

# 6.1、全局配置用户名和邮箱

TIP

  • 使用--global选项,表示设置的用户名和用户邮箱为全局配置。
  • 在电脑的当前用户上使用Git管理的所有项目在提交信息时,都会自动的读取全局配置的用户名和用户邮箱。

温馨提示:

使用--global选项配置用户名和邮箱时,该命令只需要运行一次,他会对当前用户的所有仓库生效。

git config --global user.name 'qxin905'   # 全局配置用户名
git config --global user.email 905786329@qq.com  # 全局配置用户邮箱

使用--global选项配置的用户名和邮箱信息保存在~/.gitconfig文件中(电脑当前用户下的.gitconfig文件中,如C:\Users\EDY\.gitconfig 文件中)。

# 6.2、当前项目单独配置用户名和邮箱

TIP

如果我们想为当前项目单独配置用户名和邮箱,则需要在当前项目目录下运行没有--global选项的命令来配置。

此时 Git 在管理该项目时,会使用当前项目下配置的用户名和邮箱

git config user.name 'qxin'  # 当前项目的用户名
git config user.email '906788@@qq.com'  # 当前项目用户邮箱

当前项目单独配置的信息保存在当前项目.git/config文件中

# 6.3、系统通用配置

TIP

Git安装目录下的/etc/gitconfig文件中,包了含系统上每一个用户及他们仓库的通用配置。

如果在执行 git config 时带上 --system 选项,那么它就会读写该文件中的配置变量。 (由于它是系统配置文件,因此你需要管理员或超级用户权限来修改它。)

git config --system user.name qxin

git config --system user.email 905786329@qq.com

如果你不知道你的 Git 安装目录,可以执行where git来找到

where git

注:

每一个级别会覆盖上一级别的配置,所以

  • .git/config 的配置变量会覆盖 ~/.gitconfig中的配置,
  • ~/.gitconfig的配置变量会覆盖/etc/gitconfig 中的配置变量。

# 7、使用 Git 管理项目

TIP

安装好 Git 后,Git 并不会自动帮我们管理我们电脑上的项目。如果 Git 能自动管理,那 Git 就乱了,因为电脑上并不是所有项目都需要 Git 帮我们管理。

所以,我们需要 Git 帮我们管理那个项目,我们是需要告诉 Git。

我们可以在需要 Git 管理的项目根目录下,执行git init命令,来初始化一个 Git 本地仓库,这样 Git 就会帮我们管理这个项目。

git init # 初始化Git本地仓库

以上命令执行后,会在当前项目的根目录下创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。

注:

.git文件夹默认是隐藏的,按下图所示操作可以让其显示。

image-20231122232442613

以上准备工作做好后,我们就需要学习 Git 是如何帮我们管理我们的项目。

# 二、Git 核心基础 - 三大区域,生成版本

TIP

深入浅出 Git 核心区域(工作区、暂存区、Git 仓库),生成项目版本、文件的三种状态等。

# 1、认识 Git 的三大区域

TIP

Git 的三大区域(工作区、暂存区、Git 仓库)是 Git 的核心,可以帮助我们理解他的工作机制,所以是非常重要的内容。

image-20231122200615462

image-20231206001010781

工作区

  • 项目目录,写代码的地方
  • 在这里可以新增文件、删除文件、修改文件的内容
  • 如果工作区的内容有变动,就可以通过git add命令,将变动的信息添加到存暂区。

暂存区

  • 暂时存放下次将要提交的文件列表信息,但还没有提交到本地仓库生成版本。
  • 通过 git commit命令,可以将暂存区内容提交到本地仓库,生成一个新的版本

Git 仓库(版本库)

  • Git 仓库分为本地仓库和远程仓库
  • Git 仓库中保存着项目的不同版本数据
  • 如果有需要,可以通过git push 别名/远程仓库地址 要推送的分支 命令,将本地仓库中的版本信息推送至远程仓库

# 2、Git 如何生成项目版本

下图演示了生成项目版本的完整流程

image-20231122200856559

工作区

  • 刚开始工作区干干净净的,什么都没有,我们可以在工作区新建项目文件等。
  • 然后通过git add 命令,可以将工作区的变动提交到暂存区。
  • 提交后,工作区与暂存区的内容一致。

暂存区

  • 此时暂时存放下次将要提交的文件列表信息。
  • 通过 git commit命令,可以将暂存区内容提交到本地仓库,生成一个新的版本( V1)。
  • 此时暂存区内容与本地仓库的内容一致了。

Git 仓库(版本库)

  • 此时 Git 的本地仓库保存着项目的第一个版本(如:V1)
  • 如果有需要,可以通过git push 别名/远程仓库地址 要推送的分支 命令,将本地仓库中的版本信息推送至远程仓库
  • 推送后,本地仓库和远程仓库的版本信息和内容保持一致了。

后续操作

后续操作一直重复如下流程:

  • 如果工作区内容有变动,我们就需要通过git add命令将变动内容添加到暂存区,此时工作区与暂存区内容一致。

  • 然后再通过git commit命令将暂存区内容提交到本地仓库,生成一个新的版本(如:V2),此时暂存区与本地仓库保持一致。

  • 最后,如果有需要,可以通过git push命令将本地仓库的版本信息推送到远程仓库。此时本地仓库与远程仓库的信息保持一致。

image-20231122201435807

# 3、实操:生成项目版本

TIP

通过前面的学习,我们了解了如何生成项目版本,本小节我们就动手来实操下。不过本小节我们只涉及到如何生成本地版本,不涉及到远程仓库。

具体如下图

image-20231122201930733

# 3.1、新建项目

TIP

首先新建项目目录文件夹 web,然后在当前目录下执行 git init 命令,初始化 Git 本地仓库。

mkdir web  # 新建文件夹 web
cd .\web\  # 进到 web文件夹
git init  # 初始化Git本地仓库

# 3.2、查看项目文件状态

TIP

在当前项目根目录web下,执行git status命令,来查看当前项目文件状态。

命令执行后,在控制台输出如下内容

image-20231122232719629

因为当前项目为刚创建的,并且内容为空,所以自然从来没有提交过,也没有任何内容。

# 3.3、添加项目内容

TIP

web目录下新建index.html文件,web/index.html文件内容如下

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="header">网站头部开发完成</div>
  </body>
</html>

然后,再在当前项目目录下执行git status命令,在控制台输出如下内容

image-20231122233543885

注:

我们在使用 Git 管理项目时,并不是所有的文件都需要 Git 帮我们管理,所以哪些文件需要 Git 帮我们管理,我们需要告诉 Git。

通过git add命令,将需要 Git 帮我们管理的文件添加到存暂区。只要被git add添加到暂存区的文件,Git 后期就会自动帮我们管理。当内容有变动时,Git 就会提示当前文件被修改,但还没有暂存....

# 3.4、git add 添加文件到暂存区

TIP

在当前目录下,执行 git add index.html命令,将index.html文件提交到暂存区。

git add index.html

# 或  以下命令,表示当前项目下所有被修改的文件都会被提交到暂存区
git add .

以上命令执行后,我们再来执行git status命令来查看下文件的状态,在控制台输出如下内容

image-20231122234505337

注:

从上面截图可以看到,index.html文件被提交到了暂存区,但还没有被提交。如果我们取消暂存,也可以执行git rm --cached index.html命令来取消暂存。

# 3.5、git commit 提交文件到本仓库,生成版本

TIP

我们在当前项目的根目下,执行git commit命令将暂存区的信息提交到本地仓库,生成项目的第一个版本。

执行git commit命令后,会进入到Vim编辑模式,你可以在这里输入本次提交的描述。Vim 模式下编辑文件命令。

# 按下 “i” 键编辑即可  (实际:i  o   a  s 都可以)

# 从编辑模式切换到命令模式,需要先按下 esc键,然后再执行以下键,对文件做保存等功能
# 不保存强制退出
:q!
# 保存
:w
# 保存并退出
:wq

如果我们在安装时将VSCode设置为 Git 的默认编辑,如下图:

image-20231123001147413

当执行git commit命令后,会在VSCode中打开如下图所示文件,让我们对本次提交添加相关描述。

image-20231123001841166

添加相关描述后,我们需要保存当前文件,并关闭掉他。关掉后,命令行会显示如下信息,表示本次提交成功。

image-20231123001935494

以上方式提交相对比较麻烦,我们还可以执行以下命令,在提交的同时添加描述,效果和之前是一样的,这种方式更简单。

git commit -m '提交描述写在这里'

# 3.6、git log 查看 Git 版本演变(提交历史)

TIP

在当前项目目录下,执行git log命令,查看 Git 的提交历史记录,控制台输出如下内容

image-20231123002428293

注:

HEAD为一个指针,上图表示当前在 master 分支下的6a9d58e版本,每次提交HEAD指针都会指向当前分支的当前提交。

如果我们想简化打印的提交历史记录,可以在命令后添加--oneline选项

git log --oneline  # 以列表形式查看历史版本记录

以上命令执行,在控制台打印历史记录如下图:

image-20231123002859406

# 3.7、后续操作

TIP

后续我们可以重复之前的操作

  • 在工作区开发我们的项目(比如:新增、修改、删除文件等操作)
  • 然后使用git add命令将变动内容提交到暂存区
  • 再使用git commit命令,将暂存区内容提交到本地仓库库,生成一个新的版本

# 4、总结:版本生成的整个流程

TIP

在用 Git 管理我们的项目前,我们需要先在当前项目的根目录下执行git init来初始化一个本地仓库。

然后就可以在工作区开始开发我们的项目。开发到一定阶段时,我们就需要为当前项目生成对应的版本。

# 4.1、生成第一个版本 V1

TIP

通过git add来将工作区变动提交到暂存区,然后通过git commit命令将暂存区内容提交到本地仓库,生成第一个版本 V1

此时 HEAD 指针默认指向 master 分支,master 分支指向 V1 版本

image-20231123195353985

# 4.2、生成第二个版本 V2

TIP

修改工作区内容,然后通过git add命令和git commit命令来生成第二个版本 V2。

此时 HEAD 指针默认指向 master 分支,master 分支指向 V2 版本

image-20231123195239712

# 4.3、生成第三个版本 V3

TIP

修改工作区内容,然后通过git add命令和git commit命令来生成第二个版本 V3。

此时 HEAD 指针默认指向 master 分支,master 分支指向 V3 版本

image-20231123195100715

# 5、文件的三种状态

TIP

Git管理的项目,项目文件可能处于以下 3 种状态之一:

  • 已提交(committed)
  • 已修改(modified)
  • 已暂存(staged)

详细资料查阅官网:Git 是什么 - 三种状态 (opens new window)

前面提到的 web 项目,经过git addgit commit命令后,提交到了本地仓库生成了第一个项目版本,我们简称 V1。此时工作区、暂存区、本地仓库的内容一致了。

接下来,我们在工作区继续开发,将index.html的内容修改如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="header">网站头部开发完成</div>
    <div id="main">网站主体开发完成</div>
  </body>
</html>

然后执行git status命令,查看当前文件状态,此时控制台中文件被标记为红色,表示已修改状态

image-20231123010238005

接着执行git add .命令,将文件提交到暂存区,然后再执行git status命令,此时控制台文件颜色为绿色,表示已暂存状态

image-20231123010309069

最后执行git commit -m '主体开发完成' 命令,将暂存区文件提交到本地仓库。然后执行git status命令,此时不会列出任何文件。说明所有文件都已被提交,为提交状态。

image-20231206191232018

总结:

  • 已修改(modified):表示上次提交后,重新修改了的文件,但还没提交到暂存。执行git status查看文件状态时,文件名被标红
  • 已暂存(staged):表示对一个已修改的文件提交到了暂存区,但还没有提交。执行git status查看文件状态时,文件名被标绿
  • 已提交(committed):表示文件已提交到本地仓库。执行git status查看文件状态时,不会列出任何文件。

# 6、总结:Git 核心基础操作

TIP

重点掌握 Git 核心基础:Git 的三个区域,如何生成项目版本,文件的三种状态

# 6.1、Git 三在区域

TIP

  • 工作区:写代码,修改代码的地址
  • 暂存区:暂存下次要提交的文件列表信息,但还没有提交
  • Git 仓库:最终用来存储项目版本数据的地方

# 6.2、如何生成项目版本

  • git status 用来查看项目文件状态
  • git add 命令,用来将工作区代码的变动,提交到暂存区,使用 git add 后,工作区和暂存区的内容是一致的
git add <file> <file>  # 提交指定的文件到暂存区

git add . # 将工作区所有变动提交到暂存区
  • git commit 命令,用来将暂存区的内容提交到本地仓库,git commit 后暂存区和本地版本库的内容是一致的
git commit   # 提交,最终在编辑器中输入提交的描述
git commit -m '提交描述'  # 在提交的同时,添加本次提交描述
  • git log 查看提交历史记录
git log   # 打印详细的提交历史记录
git log --oneline # 以列表形式,打印提交的历史记录(简化版)

# 6.3、文件的三种状态

TIP

被 Git 管理的项目,项目文件可能处于以下 3 种状态之一

  • 已修改(modified):表示上次提交后,重新修改了的文件,但还没提交到暂存区
  • 已暂存(staged):表示对一个已修改的文件提交到了暂存区,但还没有提交
  • 已提交(committed):表示文件已提交到本地仓库

# 三、Git 核心基础 - 撤消操作

TIP

本小节我们学习如何撤消某些操作。主要有以下三种场景:

  • 撤消上一次提交
  • 撤消暂存的文件
  • 撤消对文件的修改

关于撤消操作更详细内容,可以参考 Git 官方文档 - 撤消操作 (opens new window)

# 1、撤消上一次提交

TIP

有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。

此时,可以运行带有 --amend 选项的提交命令来重新提交

git commit --amend   # 撤消上一次提交

这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令), 那么快照会保持不变,而你所修改的只是提交信息。

文本编辑器启动后,可以看到之前的提交信息。 编辑后保存会覆盖原来的提交信息。

注:

有时候,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作。

  • 重新执行git add命令将修改内容添加到暂存区
  • 然后再重新提交,但提交时不希望生成新的版本
git commit -m 'V1-网站头部'   # 生成一个版本V1
git add .   # 将修改的内容提交到暂存区

#提交生成一个新的版本V2,该版本会替换之前的那个版本,所以最终用 git log --oneline只能看到最后一次生成的版本V2
git commit -m 'V1-网站头部导航开发完成' --amend

最终你只会有一个提交——第二次提交将代替第一次提交的结果。如下图:

image-20231123171856615

温馨提示:

当你在修补最后的提交时,与其说是修复旧提交,倒不如说是完全用一个 新的提交 替换旧的提交, 理解这一点非常重要。从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。

修补提交最明显的价值是可以稍微改进你最后的提交,而不会让“啊,忘了添加一个文件”或者 “小修补,修正笔误”这种提交信息弄乱你的仓库历史。

但我们通过 git reflog 命令,还是能看到所有版本

image-20231123172148333

# 2、撤消暂存的文件

TIP

你已经修改了两个文件并且想要将它们作为两次独立的修改提交, 但是却意外地输入 git add * 暂存了它们两个。

如何只取消暂存两个中的一个呢? git status 命令提示了你:

image-20231123172641096

在 “Changes to be committed” 文字正下方,提示使用 git restore --staged <file>… 来取消暂存。 所以,我们可以使用以下命令来取消暂存的文件

git restore --staged login.html   # 取消login.html文件的暂存

git restore --staged .  # 取消暂存区所有文件的暂存

以下为操作示意图

image-20231123173402559

注意:

git restore --staged <file> 命令只会将文件从暂存区移动到工作区,并会不会影响工作区该文件的内容。

比如文件提交到暂存区时,文件内容为:'a',后面将文件内容修改为'ab',然后执行git restore --staged <file>将文件从暂存取移除,此时工作区该文件内容任为'ab',并不会被修改为 'a'

# 3、取消对文件的修改

TIP

如果你在上一次git add后 ,对文件login.html内容做了修改,但现在你想去掉这些修改,回到上一次git add时的样式。那你就需要撤消对login.html内容的修改。

在你执行 git status命令时,该命令给了你如下提示,教你如何撤消修改。(前提是该文件至少被提交过一次)

image-20231123180848553

Changes not staged for commit文字正下方,提示使用got restore <file>...来撤消对工作区文件的修改。

所以,我们可以使用以下命令,来撤消对工作区文件的修改,使文件与暂存区文件内容保持一致。

git restore .  # 撤消对工作工所有文件的修改

image-20231123181423074

# 4、总结

TIP

使用以下命令实现撤消提交操作。本质上是重新提交生成一个新版本,替换(覆盖)之前的版本

git commit --amend
git commit -m '提交描述' -amend

使用以下命令实现将文件从暂存区撤消。撤消操作并不会影响工作区该文件的内容

git restore --staged <file>   # 将文件从暂存取撤消
git restore --staged .  # 撤消暂存取的所有文件

使用以下命令撤消对工作区文件的修改,使文件内容与暂存区内容保持一次

git restore <file>   # 撤消对工作区某个文件的修改
git restore .  # 撤消对工作区所有文件的修改

# 四、Git 核心基础 - 版本重置

TIP

Git 版本重置分为以下三种情况

  • 只重置本地仓库
  • 重置本地仓库和暂存区
  • 重置本地仓库、暂存区和工作区

在学习版本重置前,我们可先跳转到到 总结:版本生成的整个流程 (opens new window)版块,回顾下前面学习的版本生成的整个流程。

接下来,我们新建一个项目,让 Git 帮我们管理,然后生成 V1、V2、V3、V4 4 个版本。

  • 新建web文件夹作为项目的根目录,然后执行git init初始化本地仓库。
  • web文件夹下新建index.html文件,并添加如下内容
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div class="header">网站头部开发完成</div>
  </body>
</html>
  • 执行git add将内容添加到暂存区,执行git commit -m 'V1-头部完成'将暂存区内容提交到本地仓库生成第一个版本 V1
  • 修改index.html内容如下,执行git addgit commit -m 'V2-banner完成'生成第二个版本 V2
<body>
  <div class="header">网站头部开发完成</div>
  <div class="banner">banner区开发完成</div>
</body>
  • 修改index.html内容如下,执行git addgit commit -m 'V3-menu完成'生成第三个版本 V3
<body>
  <div class="header">网站头部开发完成</div>
  <div class="banner">banner区开发完成</div>
  <div class="menu">菜单区开发完成</div>
</body>
  • 修改index.html内容如下,执行git addgit commit -m 'V4-主体完成'生成第四个版本 V4
<div class="header">网站头部开发完成</div>
<div class="banner">banner区开发完成</div>
<div class="menu">菜单区开发完成</div>
<div class="main">主体区开发完成</div>

以上每一步执行的命令如下图:

image-20231123204102855

最终 HEAD 指针指向 master 分支,master 分支指向 V4 版本。

上面操作后,三个区域内容如下:

image-20231123231015593

接下来,我们在上面项目的基础上来演示版本重置。

# 1、重置本地仓库 (--soft)

TIP

  • 重置本地仓库,本质就是将 HEAD 指针指向当前所在分支,同时将当前分支指向你要移动到的当前分支的某个版本。
  • 在上面项目基础上,如果我们想要重置本地仓库到 V2 版本,就可以执行以下命令,相当于把 V3 和 V4 版本给“丢弃”掉。
git reset --soft 版本号    # 重置本地仓库
  • 以上命令执行后,本地仓库中HEAD指针向master分支,master分支指向V2。不过此时暂存区和工作区的内容是不会发生任何变动的。因为上面这个命令只是重置本地仓库。
  • 当我们使用git log --oneline命令来查看历史版本记录时,当前重置版本之后的版本是看不到,相当于之前的版本被弃用了。

操作记录如下图:

image-20231123225528501

操作后,三个区域内容如下:

image-20231123230922324

注意:

使用git reflog命令,是可以看到所有历史记录,所以上面提到的的”弃用",并不是真的被删除没有了,而是在通过git log --oneline查看历史记录时,查看不到。

如果我们在回到 V2 版本后,想在现有代码基础上重新生成一个新的版本,就可以直接执行以下命令

git commit -m 'v3-menu和主体开发完'

image-20231123230136997

上面操作后,三个区域内容如下:

image-20231123231106761

# 2、重置本地仓库与暂存区 (--mixed)

TIP

接下来,我们在上面操作的基础上,执行以下命令,重置本地仓库与暂存区到 V1 版本

git reset --mixed 版本号   # 重置本地仓库和暂存区

操作记录如下:

image-20231123231643302

以上操作后,此时本地仓库和暂存区内容是一致,为 V1 版本内容,但工作内容为 V3 版本内容,因为git reset --mixed 版本号命令,只会重置本地仓库和暂存区,并不会重置工作区。

当前三个区域的内容如下图

image-20231123232131127

# 3、重置本地库、暂存区、工作区(--hard)

接下来,我们在上面操作的基础上,执行以下命令,重置本地仓库与暂存区和工作区到 V1 版本

注意:

--hard 会重置工作区内容,所以在重置前如果工作区内容有没有提交的,重置后则会造成内容丢失。内容一旦丢失,是没有办法找回的。

所以使用--hard 命令时,要特别小心。

git reset --hard 版本号

操作记录如下:

image-20231123233700649

以上操作后,此时本地仓库和暂存区、工作区内容是一致,为 V1 版本内容。

当前三个区域的内容如下图:

image-20231123233803310

# 4、git reflog 命令

TIP

在上面操作的基础,接下来,我们执行git reflog命令,是可以查看到所有的版本历史记录,包括我们之前认为被 “丢弃” 的版本。

image-20231123234019222

我们如果想再次回到之前的 V4 版本,并且重置本地仓库、暂存区和工作区,可以执行以下操

git reset --hard V4版本号

操作记录如下:

image-20231123234246614

当前三个区域内容如下图:

image-20231123231015593

通过前面的操作,其实我们可以发现,Git 的任何操作几乎都不会造成内容丢失,我们都可以通过历史记录回到之前的某个版本。

# 5、总结

本小节,我们学习进行版本重置的三个命令

命令 说明
git reset --soft 版本号 仅重置本地仓库
git reset --mixed 版本号 重置本地仓库、暂存区 (默认行为)
git reset --hard 版本号 重置本地仓库,暂存区、工作区

--hard 很危险,会覆盖正在开发的代码

git reset --soft 版本号   #  只重置本地仓库
git reset --mixed 版本号  #  重置本地仓库和暂存区
git reset 版本号  # 重置本地仓库和暂存区,默认行为
git reset --hard 版本号 #  重置本地仓库、暂存获和工作区

区分以下两个查看历史版本记录的命令

git log --oneline # 查看所有历史记录(不包含重置的版本)

git reflog --oneline # 查看的有历史记录(包含重置的版本)

# 五、Git 核心基础 - Git 忽略文件

TIP

一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。

在这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件的模式。

# 1、.gitignore 文件

我们来看一个.gitignore文件的例子:

*.tmp
text.*

注:

  • 第一行的*.tmp是告诉 Git 忽略所有以.tmp结尾的文件,即 Git 不用管理这些文件
  • 第二行的text.*是告诉 Git 忽略所有以text.开头的文件,即 Git 不用管理这些文件

# 2、.gitignore 文件格式规范

文件.gitignore的格式规范如下:

  • 所有空行或者以 # 开头的行都会被 Git 忽略。 #为.gitignore文件的注释
# 注释
  • 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。

注:

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。

  • 星号(*)匹配零个或多个任意字符;
  • [abc] 匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);
  • 问号(?)只匹配一个任意字符;
  • 如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。
  • 使用两个星号** 表示匹配任意中间目录,比如 a/**/z 可以匹配 a/za/b/za/b/c/z 等。
# 忽略所有以text.开头的文件,不需Git管理
text.*

# Git 忽略所有以 .o 或 .a 结尾的文件
*.[oa]

# Git忽略以 a.tmp 或b.tmp等 .tmp前面只有一个字符的tmp文件
?.tmp

# 只忽略 doc的直接子目录下的任意pdf文件,比如:doc/a.b.pdf,但不能忽略doc/a/b/c.pdf
doc/*/*.pdf

# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件   如 doc/a/b.pdf  doc/a/b/c.pdf
doc/**/*.pdf
  • 匹配模式可以以(/)开头防止递归。
# 只忽略当前目录下的 demo.txt 文件,而不忽略 case/demo.txt
/demo.txt

# 忽略当前项目中所有 demo.txt文件
demo.txt
  • 匹配模式可以以(/)结尾指定目录。
# 忽略 任何目录下名为 node_modules目录下的所有文件 (git管理的是文件不是目录,所以该文件下要有内容,否则会自动忽略)
node_modules/
  • 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。
test.*   # 忽略所有以text.开头的文件,不需Git管理

!text.html  # 不忽略text.html文件,让Git管理
上次更新时间: 12/8/2023, 1:11:55 AM

大厂最新技术学习分享群

大厂最新技术学习分享群

微信扫一扫进群,获取资料

X