您有一篇git 原理,请注意查收(一)

简介: 您有一篇git 原理,请注意查收(一)

把人生一分为二,前半生不犹豫,后半生不后悔。——溥仪

大家好,我是柒八九

前言

作为一个新时代的开发者,想必大家在工作中,有一样东西是和大家形影不离的。那就是git。(当然,这里也有个例,如果大家项目还停留在svn阶段,就算我刚才的话唐突了)。

无论大家平时是喜欢在命令行中手搓git命令,还是利用git可视化工具(SourceTree)进行代码管理。终究都逃不过,add/commit/merge/push等命令的支配。所以,今天我们来聊聊,在进行这些命令的时候,在最底层到底发生了啥。

还有一点,也算是一个认知提升吧。需要和大家唠叨一下,以后遇到比较棘手的问题,可以往这方面来靠拢

所有软件的底层实现都是操作和管理数据

无论是我们平时用到的桌面程序,亦或是在命令行中进行敲敲打打处理一些特定的操作,还有就是我们熟悉的编程开发中,无论是前端的开发过程中,使用原生也好,各种框架也罢,最后的根结都是数据的罗列和排布;还是后端就更明显了,有SQL的操作,那就更是再玩弄数据。 之所以我们看到的现象有些不同,无非就是数据的表现形式和处理方式的不同。可以说,在编程界,--万物皆数据

这里简单举一个例子,日历大家都见过哇。

如果,给我们一个需求,要让我们实现一个飞书日历或者google 日历的开发任务,我们是不是一时感觉到无法下手。

那我们往万物皆数据这个定论上靠,那是不是每一个日程(无论是简单日程还是重复日程),它们本质上就是在每个小格子上展示。无非就是有的日程在单个格子上,有的日程是跨格子。 而针对这种情况,是不是就是在当前视图中,我们需要维护一个数组,而这个数组中的项就是每个格子的示例。(针对月视图/周视图/日视图的数据,其实都是一套,只不过在框架内部为我们提供了各自的展示逻辑)

这是一个开源的日历库(FullCalendar)。

image.png

而下面的events就是我们在日历上显示的日程信息。

image.png

好了,天不早了,干点正事哇。


我们能所学到的知识点

  1. 前置知识点
  2. git init
  3. 新增一个文件
  4. git commit
  5. 新增修改
  6. 创建分支
  7. 分支切换
  8. 分支合并
  9. 远程提交

1. 前置知识点

前置知识点,只是做一个概念的介绍,不会做深度解释。因为,这些概念在下面文章中会有出现,为了让行文更加的顺畅,所以将本该在文内的概念解释放到前面来。如果大家对这些概念熟悉,可以直接忽略


同时,由于阅读我文章的群体有很多,所以有些知识点可能我视之若珍宝,尔视只如草芥,弃之如敝履。以下知识点,请酌情使用

什么是git

Git是一种用于源代码管理的工具。它是一个免费且开源的版本控制系统,用于高效地处理从小型到非常大型的项目。Git用于跟踪源代码的更改,使多个开发人员能够共同在非线性开发中合作。Git是由Linus Torvalds2005年为Linux内核的开发而创建的。

集中式管理

在使用Git之前在维护代码之前,团队合作的模式如下:

  • 开发人员过去会将他们的代码提交到中央服务器,而没有自己的副本。
  • 对源代码所做的任何更改对其他开发人员来说都是未知的
  • 没有任何开发人员之间的沟通。

image.png

它的典型代表为SVN

分布式管理

  • 每个开发人员都在其本地系统上拥有完整的代码副本
  • 对源代码所做的任何更改都可以被其他人跟踪
  • 开发人员之间有定期的沟通。

image.png


毋庸置疑,git是这方面的王者。

git基础概念

  • workspace:是本地项目的工作目录,属于本地代码发生更新但尚未执行 git add 命令时的状态working tree的状态也随之更新
  • index:是索引文件,它是连接working treecommit的桥梁,每当我们使用git add命令来登记后,index file的内容就会改变,此时index file就和working tree同步了。
  • 它还有一个家喻户晓的名字 -暂存区
  • local repository:是本地仓库,当我们使用git commit命令提交最新代码时,代码才真正进入git仓库。
  • git commit -m “xxx” 就是index 里的内容提交到本地仓库中
  • remote repository:是远程仓库,当我们使用git push命令时就会将本地仓库的代码上传至远程仓库,完成整个代码的上传工作

image.png


git init --bare VS git init

git init --baregit init 是两种不同的Git初始化命令,它们用于创建不同类型的Git仓库。

下面是它们之间的主要区别:

  1. 仓库类型:
  • git init: 这个命令用于创建一个标准的Git工作目录仓库。它会在当前目录下创建一个.git子目录,其中包含Git的版本控制文件和历史记录(这是我们这篇文章的重点)。这种类型的仓库通常用于开发和维护代码。
  • git init --bare: 这个命令用于创建一个"裸"(bare)仓库,它不包含工作目录。这意味着它只包含Git版本控制的文件和历史记录,没有实际的项目文件。"裸"仓库通常用作中央版本库,用于协作和共享代码。
  1. 默认分支:
  • git init 默认创建一个带有master分支的工作目录仓库。
  • git init --bare 默认不创建分支,因为裸仓库不包含工作目录。我们需要手动创建和设置分支。

一般情况下,如果我们需要创建一个新的Git仓库用于开发和维护代码,我们应该使用 git init。如果我们需要创建一个中央版本库用于团队协作和共享代码,我们可以考虑使用 git init --bare


Hook

钩子(Hooks)是一种通用概念,通常用于在特定事件发生时触发自定义代码。虽然不是编程语言本身的一部分,但编程语言和开发工具通常提供一些机制来支持编写和使用钩子。

下面我们简单介绍几种大家比较常见的利用Hook概念的技术。

名称 描述 示例语法
Git Hooks Git 允许在代码仓库的特定事件上运行自定义脚本。事件包括提交、推送、合并等。 使用 Bash 脚本编写,如 pre-commitpost-commit 等。
JavaScript Hooks JavaScript 用于前端和后端开发,事件处理程序在特定事件发生时执行自定义 JavaScript 代码。 前端中,事件处理程序如事件监听器。后端中,使用 EventEmitter 模块。
React Lifecycle Hooks React 用于构建用户界面,包括生命周期方法,允许在组件的不同生命周期阶段运行自定义代码。 生命周期方法如 componentDidMountcomponentWillUnmount
当然,还有甚嚣尘上的针对函数组件的React Hook
GitHub Webhooks GitHub 提供 Webhooks,是 HTTP 回调,用于在存储库的特定事件上触发自定义操作。 开发者编写 Webhook 处理程序响应事件,配置 Webhook URL。
Jenkins Pipeline Hooks Jenkins 是一个持续集成工具,允许创建自定义流水线脚本。使用钩子定义流水线的阶段和操作。 钩子嵌入到 Jenkinsfile 中以定义流水线。

Git Hook

Git Hook是一种非常强大的Git自定义脚本系统,它允许我们在Git版本控制过程的不同阶段执行自定义操作。这些操作可以是自动化测试、代码格式化、验证提交消息格式、预防性错误检查等等。Git hooks是一种强大的自定义工具,可以提高代码质量和协作效率。

  1. Git Hook的种类: Git提供了多种不同类型的Hook,每种类型对应着Git操作的不同阶段。以下是一些常见的Git挂钩类型:
  • pre-commit:在执行实际提交之前运行,用于执行预提交检查
  • pre-push:在执行实际推送之前运行,用于验证推送到远程仓库的内容
  • pre-receive:在接收端执行,通常用于验证推送到远程仓库的提交
  • post-receive:在接收端执行,通常用于通知或自动化部署
  1. Hook的位置: 每个Git存储库都有一个.git/hooks目录,其中包含用于存储各种Hook脚本的文件。当我们在存储库中运行git init时,Git会为我们创建示例Hook文件,我们可以根据需要编辑或替换它们。这些示例文件以.sample为扩展名。
  2. 编写Git Hook: 要编写Git Hook,我们只需创建一个可执行的脚本文件并将其放入.git/hooks目录中。脚本的名称必须与hook类型相匹配(例如,pre-commit)。在脚本中,我们可以执行任何自定义操作,例如检查代码、验证提交消息、运行测试等。

git diff

git diff命令后通常需要跟两个参数,参数1是要比较的旧代码,参数2是要比较的新代码。如果只写一个参数,表示默认跟 workspace 中的代码作比较。

git diff 显示的结果为第二个参数所指的代码在第一个参数所指代码基础上的修改

  • git diff:查看 workspaceindex 的差别
  • git diff --cached:查看 indexlocal repositorty 的差别
  • git diff HEAD:查看 workspacelocal repository 的差别

HEAD 指向的是 local repository 中的代码最新提交版本

  • git diff HEAD^ 是比较 workspace 与最新commit的前一次commit的差异,与git diff HEAD的是不同的
  • git diff HEAD~2 是比较 workspace 与上2次commit的差异,相当于 git diff HEAD~2 HEAD~0,注意两个HEAD的位置,diff显示的结果表示 参数2(HEAD0) 相对于参数1(HEAD2)的修改

git 别名

在Git中,别名(Git Aliases)是一种机制,允许我们为常用的Git命令或命令序列创建简短的自定义命令。别名使我们可以用更短、更易记的名称来执行常用的Git操作,提高工作效率。

1. 创建别名: 我们可以使用git config命令来创建Git别名。

git config --global alias.<alias-name> <git-command-or-sequence>
  • <alias-name>:自定义别名的名称,我们可以选择任何喜欢的名称。
  • <git-command-or-sequence>:要与别名关联的Git命令或命令序列。

2. 例子: 以下是一些Git别名的例子:

git config --global alias.co checkout        # 创建 'co' 别名来代替 'checkout'
git config --global alias.br branch          # 创建 'br' 别名来代替 'branch'
git config --global alias.ci commit          # 创建 'ci' 别名来代替 'commit'
git config --global alias.st status          # 创建 'st' 别名来代替 'status'
git config --global alias.unstage 'reset HEAD --'  # 创建 'unstage' 别名来取消暂存

3. 使用别名: 创建别名后,我们可以在命令行中使用它们。例如,使用上面的例子,我们可以这样执行命令:

git co my-branch     # 等同于 'git checkout my-branch'
git br -a            # 等同于 'git branch -a'
git ci -m "Message"  # 等同于 'git commit -m "Message"'
git st               # 等同于 'git status'
git unstage file.txt # 等同于 'git reset HEAD -- file.txt'

从基本层面上说,Git只是一堆通过文件名相互关联的文本文件

还有一点需要提前声明,如果大家也在自己的电脑中进行实验,下面文章中出现的各种hash值,都是和内容有关系。所以,大家要和自己的内容对号入座,不要和本文中的hash值比较。

2. git init

为了演示方便,我们在本地的合适的文件夹中新建了一个dot_git的项目。

mkdir dot_git

与此同时通过git init来初始化项目。

image.png

现在让我们来看看.git文件夹中有什么内容。

我们使用erd来查看文件结构。

erd -y inverted .git

文档结构如下

image.png

看起来它创建了一堆文件和文件夹。让我们挑几个重要的来解释一下:

  • hooks包含了在Git执行任何操作之前/之后可以运行的脚本。
  • HEAD指向的是local repository中的代码最新提交版本
  • 根据我们设置的“默认”分支是什么(git config --global init.defaultBranch <分支名称>),它将是refs/heads/master(默认),refs/heads/main,或者我们设置的其他分支名称。
  • image.png
  • 它指向了refs/heads文件夹,并指向一个叫做master的文件,这个文件在我们进行第一次提交之前是不存在的。
  • 这个master文件只会在我们进行第一次提交后出现
  • config是一个文本文件,它包含了当前仓库的Git配置
  • 如果我们查看它,我们会看到一些关于我们的仓库的基本设置,比如是否bare、文件模式等。
  • image.png
  • objects包含了Git对象,也就是关于仓库中文件、提交等的数据。(这个狠最重要,狠重要)
  • refs,存储引用(指针)的地方。
  • refs/heads包含分支的指针
  • refs/tags包含标签的指针
相关文章
|
6月前
|
存储 开发工具 git
Git的基本操作和原理
Git的基本操作和原理
|
3月前
|
存储 开发工具 数据库
Git的工作原理是什么
【8月更文挑战第24天】Git的工作原理是什么
48 0
|
5月前
|
前端开发 持续交付 开发工具
详细介绍Git的基本原理、在前端开发中的应用以及如何使用Git来优化团队协作
【6月更文挑战第14天】Git是前端开发中的必备工具,它通过分布式版本控制管理代码历史,支持分支、合并和冲突解决,促进团队协作。在前端开发中,Git用于代码追踪、版本控制、代码审查和持续集成部署,优化团队协作。制定分支策略、编写清晰提交信息、定期合并清理分支以及使用Git钩子和自动化工具能进一步提升效率。理解并善用Git,能有效提升前端项目的质量和开发效率。
77 3
|
6月前
|
运维 测试技术 开发工具
Git 的原理与使用(下)(二)
新特性或新功能开发完成后,开发人员需合到 develop 分支。
56 2
|
6月前
|
Java 网络安全 开发工具
Git 的原理与使用(中)(三)
别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。
44 1
|
6月前
|
存储 安全 开发工具
Git 的原理与使用(中)(二)
Fast Forward 模式(ff模式) 通常合并分支时,如果可以,Git 会采用 Fast forward 模式。
39 1
|
6月前
|
安全 Java 开发工具
Git 的原理与使用(中)(一)
分支是Git的杀手级功能之一。
49 1
|
6月前
|
存储 算法 开发工具
Git 的原理与使用(上) (二)
如果直接将某个文件拷贝到 .git 文件的同级目录gitcode下,此时这个文件是不会被Git管理的。
51 1
|
6月前
|
Linux 开发工具 git
Git 的原理与使用(下)(一)
在完成origin/dev分支合并到origin/master分支的操作后,origin/dev分支对于我们来说就没用了,那么dev分支就可以被删除掉。
60 0
|
6月前
|
Unix Linux 开发工具
Git 的原理与使用(上) (一)
Git是一个分布式版本控制系统,它被广泛用于协作开发和管理软件项目。开发人员可以通过Git来跟踪文件的变化、协调工作、并管理项目的不同版本。
37 0