Git从原理到实践的全面指南 | 概念篇

Git是一个非常强大的代码管理工具,它不仅可以让你方便地提交、推送、拉取代码,还可以让你灵活地处理各种复杂的分支、合并、冲突等问题。说到使用,相信大家都会,无非就是commit、push、pull 。但是如果要说熟练掌握Git的使用,对代码管理做到得心应手却不是那么容易。现在我们就先从基本的概念开始,系统地学习Git的原理和操作。

前言

?首先要知道Git 是如何保存数据的?

Git 保存的不是文件的变化或者差异,而是一系列不同时刻的 快照,在进行提交操作时,Git 会保存一个提交对象(commit object)。下面会说到这个object,它被保存在.git隐藏文件中。

三种状态

Git 有三种状态,后面经常会用到这些概念,所以需要理解并记住。一般来说,你的文件会处于处于三种状态其中之一: 已提交(committed)已修改(modified)已暂存(staged)

  • 已修改表示修改了文件,但还没保存到数据库中。
  • 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
  • 已提交表示数据已经安全地保存在本地数据库中。

这会让我们的 Git 项目拥有三个阶段:工作区、暂存区以及 Git 目录

image-20230622175332240

工作区

这是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。

暂存区

它是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 按照 Git 的术语叫做“索引”,不过一般说法还是叫“暂存区”。

Git 仓库目录

这是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。

基本的 Git 工作流程

✂git的工作流程一般为:

  1. 工作区中修改文件。
  2. 将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区
  3. 提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。

如果 Git 目录中保存着特定版本的文件,就属于 已提交 状态。 如果文件已修改并放入暂存区,就属于 已暂存 状态。 如果自上次检出后,作了修改但还没有放到暂存区域,就是 已修改 状态。

commit

Git commit 是将暂存区里的改动提交到本地的版本库。每次使用 git commit 命令我们都会在本地版本库生成一个 40 位的哈希值,这个哈希值也叫 commit-id。

在Git中,commit可以看作是你对代码所做的一次保存。每一次提交都会记录你对代码所做的更改,包括添加、删除和修改的文件。这些提交被保存在Git的数据库中,构成了代码版本控制系统的历史记录。

这个历史记录?允许你在代码中查看和恢复以前的更改,以及在代码版本之间进行比较。简单来说,commit就是记录你对代码所做的更改,并将这些更改保存在Git数据库中的一个过程。

branch分支

Git的分支是指代码版本的一种分支,允许你在不影响主代码版本的情况下进行更改和试验。

假设你在一个项目上工作,你可以使用分支来创建一个独立的代码版本,在这个版本中你可以进行试验和更改,而不会影响到主版本。

如果你的更改最终被证明是有用的,你可以将它们合并回主版本中。这就是分支的作用,它可以让你在不破坏主版本的情况下,进行试验和更改。

Git 创建新分支实际上是它为你创建了一个可以移动的新的指针。它指向当前所在的提交对象。

image.png

?当有多个分支时,Git 又是怎么知道当前在哪一个分支上呢?

很简单,它有一个名为 HEAD 的特殊指针。 它会指向当前所在的本地分支

HEAD

HEAD 是一个指向你正在工作中的本地分支的指针,可以将 HEAD 想象为当前分支的别名。在 Git 中,每次提交,Git 都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在 Git 里,这个分支叫主分支,即 master 分支。HEAD 严格来说不是指向提交,而是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当前分支。

如果你切换到了其他分支,HEAD 就会指向那个分支。如果你提交了新的修改,master 分支也会随之移动,而 HEAD 指向的分支也会随之移动。

我们可以把git看作是一辆车?,而HEAD就像是车头。车头总是指向车身的前方,告诉我们它们所在的方向。同样,HEAD也指向我们当前所在的代码版本。

三者的关系

?commit,branch和HEAD之间到底是什么关系呢?

假设你正在写一篇文章,你可以把文章的每一个版本看作是一个提交(commit)。

当你需要进行修改时,你可以创建一个新的版本,类似于在文章上打草稿。你可以在这个新的版本上进行修改,而不会影响原先的版本。这个新的版本就像是一个分支,指向你正在编辑的版本。

当你完成修改时,你可以提交新的版本,就像是把你的修改写进正式的文章中。这个提交(commit)将成为一个新的版本,你的分支将指向这个新的版本。

HEAD的作用就像是你在写文章时的光标?。它指向你正在编辑的版本,告诉你哪一个版本是当前正在被修改的。当你创建新的版本时,HEAD也会跟随移动到新的版本上,指向新的版本,这样你就可以在这个新的版本上进行修改了。

master和origin

推送代码的命令是git push origin master,那这里面的origin 和 master代表了什么呢?

“master ”的含义?

Git 的默认 branch(俗称主 branch / 主分支)。它和其它 branch 的区别在于:

  1. 新建的仓库中的第一个 commit 会被 master 自动指向;
  2. git clone 时,会自动 checkoutmaster

Git 的 master 分支并不是一个特殊分支。 它就跟其它分支完全没有区别。 之所以几乎每一个仓库都有 master 分支,是因为 git init 命令默认创建它,并且大多数人都懒得去改动它。

“origin”的含义?

“origin” 指远程仓库,指向的是当你运行 git clone 时默认的远程仓库名字

可以运行 git remote 命令,查看你已经配置的远程仓库服务器

git remote

# 会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL
git remote -v

他们没有特别的含义,只是使用的比较广泛的名字。查看.git/config可以看到它们的含义

image-20230622131045900

.git隐藏文件夹

选取一个文件夹,打开后执行git init,即创建一个新的git仓库。可以在文件夹下看到一个.git文件(要打开隐藏文件才能看见)

.git文件说明

.git文件包含了几乎所有 Git 存储和操作的东西。 如若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可。

新初始化的 .git 目录的典型结构如下

$ ls -F1
config description  HEAD   
hooks/  info/ objects/  refs/ 

image-20230622140034065

文件跟踪

在git仓库中,你工作目录下的每一个文件都不外乎这两种状态:已跟踪未跟踪

  • 已跟踪文件:就是 Git 已经知道的文件。

    已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后, 它们的状态可能是未修改,已修改或已放入暂存区

  • 未跟踪文件:工作目录中除已跟踪文件外的其它所有文件

    未跟踪文件,它们既不存在于上次快照的记录中,也没有被放入暂存区。

初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态,因为 Git 刚刚检出了它们, 而你尚未编辑过它们。

编辑过某些文件之后,由于自上次提交后你对它们做了修改,Git 将它们标记为已修改文件。 在工作时,你可以选择性地将这些修改过的文件放入暂存区,然后提交所有已暂存的修改,如此反复。

image-20230622143828738

使用git status可以查看文件状态

1)比较干净的工作目录

image-20230622145048020

2)存在未跟踪的文件

可以看到Untracked files文件,即存在未跟踪的文件,意味着 Git 在之前的快照(提交)中没有这些文件。根据提示可以看到使用 “git add“能让文件变为被跟踪的状态

image-20230622145116728

3)跟踪文件

现在根据提示操作git add README.md

现在README.md文件出现在 Changes to be committed 这行下面,说明是已暂存状态

image-20230622145645119

4)暂存已修改文件

工作目录中有一个已被跟踪的文件demo1.txt,修改了这个文件后,会看到下面内容

可以看到demo1.txt文件出现在了Changes not staged for commit 这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。

image-20230622154127723

要暂存这次更新,需要运行 git add 命令。

这是个多功能命令:

  • 可以用它开始跟踪新文件,
  • 或者把已跟踪的文件放到暂存区,
  • 还能用于合并时把有冲突的文件标记为已解决状态等。

将这个命令理解为“精确地将内容添加到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。

现在运行这个命令 git add demo1.txt可以看到现在两个文件都已暂存,下次提交时就会一并记录到仓库。

image-20230622154427338

取消暂存

可以看到在 “Changes to be committed” 文字正下方,提示使用 git restore --staged <file>… 来取消暂存。 所以,我们可以这样来取消暂存某个文件,比如 demo1.txt 文件:

 git restore --staged demo1.txt

5)暂存非暂存同时出现

现在我们准备提交了,但是突然发现漏写了东西,所以对demo1.txt文件又进行了一点改动,这个时候还可以直接提交吗?不妨在运行git status看看。

可以看到demo1.txt文件同时出现在了暂存区和非暂存区,这是为什么呢?

因为Git 只不过暂存了你运行 git add 命令时的版本。 如果你现在提交,demo1.txt 的版本是你最后一次运行 git add 命令时的那个版本,而不是你运行 git commit 时,在工作目录中的当前版本。 所以,运行了 git add 之后又作了修订的文件,需要重新运行 git add 把最新版本重新暂存起来

image-20230622155012175

如果觉得每次都要先git add比较麻烦,可以在提交的时候给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤

# 这很方便,但是有时这个选项会将不需要的文件添加到提交中。
git commit -a

更简单的查看

从上面git status 命令输出到的结果是比较详细的,如果想简洁点查看可以使用命令

git status -s

输出中有两栏,左栏指明了暂存区的状态,右栏指明了工作区的状态。

image-20230622155805756

  • ?? :新添加的未跟踪文件

  • A :新添加到暂存区中的文件

  • M :修改过的文件

例如,上面的状态报告显示:

  • README.md是新添加到暂存区中的文件。
  • demo1.txt文件已修改,暂存后又作了修改,因此该文件的修改中既有已暂存的部分,又有未暂存的部分。
  • demo3.txt是新添加的未跟踪文件

总结

目前为止,git中的重要概念我们都了解,下篇我们会接着说git在实战中的基础用法和高级用法以及常见问题的解决方案。

参考资料

Git原理详解及实用指南


?【点赞】【关注】不迷路,更多前端干货等你解锁

往期推荐

最全的CSS阴影总结【建议收藏】

CSS之详解2D转换

10分钟学会css原生变量

彻底搞懂css中的尺寸单位

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MY5NiPsz' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片