良心总结!Git 各指令的本质,真是通俗易懂啊

news2024/11/28 19:02:32

1前言

作为当前世界上最强大的代码管理工具Git相信大家都很熟悉,但据我所知有很大一批人停留在clone、commit、pull、push...的阶段,是不是对rebase心里没底只敢用merge?碰见版本回退就抓瞎?别问我怎么知道的,问就是:“我曾经就是这样啊~~”。针对这些问题,今天我就将这几年对Git的认知和理解分享出来,尽可能的从本质去讲解Git,帮助你一步一步去了解Git的底层原理,相信读完本篇文章你便可以换种姿态,更加风骚得使用Git各种指令。

 
 

2目录

  1. 基本概念

  • 1.1 Git的优势

  • 1.2 文件状态

  • 1.3 commit 节点

  • 1.4 HEAD

  • 1.5 远程仓库

  1. 分支

  • 2.1 什么是分支?

  1. 命令详解

  • 3.1 提交相关

  • 3.2 分支相关

  • 3.3 合并相关

  • 3.4 回退相关

  • 3.5 远程相关

31. 基本概念

1.1 Git的优势

Git是一个分布式代码管理工具,在讨论分布式之前避免不了提及一下什么是中央式代码管理仓库

  • 中央式:所有的代码保存在中央服务器,所以提交必须依赖网络,并且每次提交都会带入到中央仓库,如果是协同开发可能频繁触发代码合并,进而增加提交的成本和代价。最典型的就是svn

  • 分布式:可以在本地提交,不需要依赖网络,并且会将每次提交自动备份到本地。每个开发者都可以把远程仓库clone一份到本地,并会把提交历史一并拿过来。代表就是Git

Git相比于svn有什么优势呢?打个比方:"巴拉巴拉写了一大堆代码,突然发现写的有问题,我想回到一个小时之前",对于这种情况Git的优势就很明显了,因为commit的成本比较小并且本地会保存所有的提交记录,随时随刻可以进行回退。在这并不是说svn的不能完成这种操作,只是Git的回退会显得更加的优雅。Git相比于中央式工具还有很多优点,就不一一列举了,感兴趣的可自行了解。

1.2 文件状态

在Git中文件大概分为三种状态:已修改(modified)、已暂存(staged)、已提交(committed)

  • 修改:Git可以感知到工作目录中哪些文件被修改了,然后把修改的文件加入到modified区域

  • 暂存:通过add命令将工作目录中修改的文件提交到暂存区,等候被commit

  • 提交:将暂存区文件commit至Git目录中永久保存

1.3 commit节点

为了便于表述,本篇文章我会通过节点代称commit提交

在Git中每次提交都会生成一个节点,而每个节点都会有一个哈希值作为唯一标示,多次提交会形成一个线性节点链(不考虑merge的情况),如图1-1

节点上方是通过 SHA1计算的哈希值

C2节点包含C1提交内容,同样C3节点包含C1、C2提交内容

1.4 HEAD

HEAD是Git中非常重要的一个概念,你可以称它为指针或者引用,它可以指向任意一个节点,并且指向的节点始终为当前工作目录,换句话说就是当前工作目录(也就是你所看到的代码)就是HEAD指向的节点。

还以图1-1举例,如果HEAD指向C2那工作目录对应的就是C2节点。具体如何移动HEAD指向后面会讲到,此处不要纠结。

同时HEAD也可以指向一个分支,间接指向分支所指向的节点

1.5 远程仓库

虽然Git会把代码以及历史保存在本地,但最终还是要提交到服务器上的远程仓库。通过clone命令可以把远程仓库的代码下载到本地,同时也会将提交历史分支HEAD等状态一并同步到本地,但这些状态并不会实时更新,需要手动从远程仓库去拉取,至于何时拉、怎么拉后面章节会讲到。

通过远程仓库为中介,你可以和你的同事进行协同开发,开发完新功能后可以申请提交至远程仓库,同时也可以从远程仓库拉取你同事的代码。

注意点

因为你和你的同事都会以远程仓库的代码为基准,所以要时刻保证远程仓库的代码质量,切记不要将未经检验测试的代码提交至远程仓库

42. 分支

2.1 什么是分支?

分支也是Git中相当重要的一个概念,当一个分支指向一个节点时,当前节点的内容即是该分支的内容,它的概念和HEAD非常接近同样也可以视为指针引用,不同的是分支可以存在多个,而HEAD只有一个。通常会根据功能版本建立不同的分支

那分支有什么用呢?

  • 举个例子:你们的 App 经历了千辛万苦终于发布了v1.0版本,由于需求紧急v1.0上线之后便马不停蹄的开始v1.1,正当你开发的兴起时,QA同学说用户反馈了一些bug,需要修复然后重新发版,修复v1.0肯定要基于v1.0的代码,可是你已经开发了一部分v1.1了,此时怎么搞?

面对上面的问题通过引入分支概念便可优雅的解决,如图2-1

  • 先看左边示意图,假设C2节点既是v1.0版本代码,上线后在C2的基础上新建一个分支ft-1.0

  • 再看右边示意图,在v1.0上线后可在master分支开发v1.1内容,收到QA同学反馈后提交v1.1代码生成节点C3,随后切换到ft-1.0分支做bug修复,修复完成后提交代码生成节点C4,然后再切换到master分支并合并ft-1.0分支,到此我们就解决了上面提出的问题

除此之外利用分支还可以做很多事情,比如现在有一个需求不确定要不要上线,但是得先做,此时可以单独创建一个分支开发该功能,等到啥时候需要上线直接合并到主分支即可。分支适用的场景很多就不一一列举了。

注意点

当在某个节点创建一个分支后,并不会把该节点对应的代码复制一份出来,只是将新分支指向该节点,因此可以很大程度减少空间上的开销。一定要记着不管是HEAD还是分支它们都只是引用而已,量级非常轻

53. 命令详解

3.1 提交相关

前面我们提到过,想要对代码进行提交必须得先加入到暂存区,Git中是通过命令 add 实现

添加某个文件到暂存区:

git add 文件路径
复制代码

添加所有文件到暂存区:

git add .
复制代码

同时Git也提供了撤销工作区暂存区命令

撤销工作区改动:

git checkout -- 文件名
复制代码

清空暂存区:

git reset HEAD 文件名
复制代码

提交:

将改动文件加入到暂存区后就可以进行提交了,提交后会生成一个新的提交节点,具体命令如下:

git commit -m "该节点的描述信息"
复制代码

3.2 分支相关

创建分支

创建一个分支后该分支会与HEAD指向同一节点,说通俗点就是HEAD指向哪创建的新分支就指向哪,命令如下:

git branch 分支名
复制代码

切换分支

当切换分支后,默认情况下HEAD会指向当前分支,即HEAD间接指向当前分支指向的节点

git checkout 分支名
复制代码

同时也可以创建一个分支后立即切换,命令如下:

git checkout -b 分支名
复制代码

删除分支

为了保证仓库分支的简洁,当某个分支完成了它的使命后应该被删除。比如前面所说的单独开一个分支完成某个功能,当这个功能被合并到主分支后应该将这个分支及时删除。

删除命令如下:

git branch -d 分支名
复制代码

3.3 合并相关

关于合并的命令是最难掌握同时也是最重要的。我们常用的合并命令大概有三个mergerebasecherry-pick

merge

merge是最常用的合并命令,它可以将某个分支或者某个节点的代码合并至当前分支。具体命令如下:

git merge 分支名/节点哈希值
复制代码

如果需要合并的分支完全领先于当前分支,如图3-1所示

由于分支ft-1完全领先分支ft-2ft-1完全包含ft-2,所以ft-2执行了“git merge ft-1”后会触发fast forward(快速合并),此时两个分支指向同一节点,这是最理想的状态。但是实际开发中我们往往碰到是是下面这种情况:如图3-2(左)

这种情况就不能直接合了,当ft-2执行了“git merge ft-1”后Git会将节点C3C4合并随后生成一个新节点C5,最后将ft-2指向C5 如图3-2(右)

注意点:

如果C3C4同时修改了同一个文件中的同一句代码,这个时候合并会出错,因为Git不知道该以哪个节点为标准,所以这个时候需要我们自己手动合并代码

rebase

rebase也是一种合并指令,命令行如下:

git rebase 分支名/节点哈希值
复制代码

merge不同的是rebase合并看起来不会产生新的节点(实际上是会产生的,只是做了一次复制),而是将需要合并的节点直接累加 如图3-3

当左边示意图的ft-1.0执行了git rebase master后会将C4节点复制一份到C3后面,也就是C4'C4C4'相对应,但是哈希值却不一样。

rebase相比于merge提交历史更加线性、干净,使并行的开发流程看起来像串行,更符合我们的直觉。既然rebase这么好用是不是可以抛弃merge了?其实也不是了,下面我罗列一些mergerebase的优缺点:

merge优缺点:

  • 优点:每个节点都是严格按照时间排列。当合并发生冲突时,只需要解决两个分支所指向的节点的冲突即可

  • 缺点:合并两个分支时大概率会生成新的节点并分叉,久而久之提交历史会变成一团乱麻

rebase优缺点:

  • 优点:会使提交历史看起来更加线性、干净

  • 缺点:虽然提交看起来像是线性的,但并不是真正的按时间排序,比如图3-3中,不管C4早于或者晚于C3提交它最终都会放在C3后面。并且当合并发生冲突时,理论上来讲有几个节点rebase到目标分支就可能处理几次冲突

对于网络上一些只用rebase的观点,作者表示不太认同,如果不同分支的合并使用rebase可能需要重复解决冲突,这样就得不偿失了。但如果是本地推到远程并对应的是同一条分支可以优先考虑rebase。所以我的观点是 根据不同场景合理搭配使用mergerebase,如果觉得都行那优先使用rebase

cherry-pick

cherry-pick的合并不同于mergerebase,它可以选择某几个节点进行合并,如图3-4

命令行:

git cherry-pick 节点哈希值
复制代码

假设当前分支是master,执行了git cherry-pick C3(哈希值),C4(哈希值)命令后会直接将C3C4节点抓过来放在后面,对应C3'C4'

3.4 回退相关

分离HEAD

在默认情况下HEAD是指向分支的,但也可以将HEAD从分支上取下来直接指向某个节点,此过程就是分离HEAD,具体命令如下:

git checkout 节点哈希值
//也可以直接脱离分支指向当前节点
git checkout --detach
复制代码

由于哈希值是一串很长很长的乱码,在实际操作中使用哈希值分离HEAD很麻烦,所以Git也提供了HEAD基于某一特殊位置(分支/HEAD)直接指向前一个前N个节点的命令,也即相对引用,如下:

//HEAD分离并指向前一个节点
git checkout 分支名/HEAD^
复制代码
//HEAD分离并指向前N个节点
git checkout 分支名~N
复制代码

HEAD分离出来指向节点有什么用呢?举个例子:如果开发过程发现之前的提交有问题,此时可以将HEAD指向对应的节点,修改完毕后再提交,此时你肯定不希望再生成一个新的节点,而你只需在提交时加上--amend即可,具体命令如下:

git commit --amend
复制代码

回退

回退场景在平时开发中还是比较常见的,比如你巴拉巴拉写了一大堆代码然后提交,后面发现写的有问题,于是你想将代码回到前一个提交,这种场景可以通过reset解决,具体命令如下:

//回退N个提交
git reset HEAD~N
复制代码

reset相对引用很像,区别是reset会使分支HEAD一并回退。

3.5 远程相关

当我们接触一个新项目时,第一件事情肯定是要把它的代码拿下来,在Git中可以通过clone从远程仓库复制一份代码到本地,具体命令如下:

git clone 仓库地址
复制代码

前面的章节我也有提到过,clone不仅仅是复制代码,它还会把远程仓库的引用(分支/HEAD)一并取下保存在本地,如图3-5所示:

其中origin/masterorigin/ft-1为远程仓库的分支,而远程的这些引用状态是不会实时更新到本地的,比如远程仓库origin/master分支增加了一次提交,此时本地是感知不到的,所以本地的origin/master分支依旧指向C4节点。我们可以通过fetch命令来手动更新远程仓库状态

小提示:

并不是存在服务器上的才能称作是远程仓库,你也可以clone本地仓库作为远程,当然实际开发中我们不可能把本地仓库当作公有仓库,说这个只是单纯的帮助你更清晰的理解分布式

fetch

说的通俗一点,fetch命令就是一次下载操作,它会将远程新增加的节点以及引用(分支/HEAD)的状态下载到本地,具体命令如下:

git fetch 远程仓库地址/分支名
复制代码

pull

pull命令可以从远程仓库的某个引用拉取代码,具体命令如下:

git pull 远程分支名
复制代码

其实pull的本质就是fetch+merge,首先更新远程仓库所有状态到本地,随后再进行合并。合并完成后本地分支会指向最新节点

另外pull命令也可以通过rebase进行合并,具体命令如下:

git pull --rebase 远程分支名
复制代码

push

push命令可以将本地提交推送至远程,具体命令如下:

git push 远程分支名
复制代码

如果直接push可能会失败,因为可能存在冲突,所以在push之前往往会先pull一下,如果存在冲突本地解决。push成功后本地的远程分支引用会更新,与本地分支指向同一节点

6综上所述

  • 不管是HEAD还是分支,它们都只是引用而已,引用+节点是 Git 构成分布式的关键

  • merge相比于rebase有更明确的时间历史,而rebase会使提交更加线性应当优先使用

  • 通过移动HEAD可以查看每个提交对应的代码

  • clonefetch都会将远程仓库的所有提交引用保存在本地一份

  • pull的本质其实就是fetch+merge,也可以加入--rebase通过rebase方式合并

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/88125.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是成熟的自动化运维平台?

本文首发于知乎,由嘉为蓝鲸原创。 商业转载请联系作者获得授权,非商业转载请注明出处。 当企业遇到运维管理对象的急速增长,业务需求频繁变更等传统运维场景问题时,依靠手工运维已经远远满足不了需求,因此我们需要搭建…

2022,itbird的年终总结报告

最近公司要求个人在做年终总结了,趁着这个机会,也想对自己的2022年进行一下回顾总结,最重要的是,对2023的目标,可以有一个指引。 就从工作和生活两方面来讲吧。 1.工作 1.1 行业的状态 本人从事的是android开发工作…

Cuda个别库函数的兼容性 - shuffle\数学库\原子

兼容性针对的是不同的Cuda版本和设备计算能力(compute capability) shuffle 在C\C扩展一节 新版本函数见Cuda12.0 文档 __shfl_sync, __shfl_up_sync, __shfl_down_sync, and __shfl_xor_sync exchange a variable between threads within a warp. Supported by devices of …

信创入围认证详解

信创是一个统称概念,实际是把现有与信息技术相关的行业结合在一起,命名为“信息技术应用创新产业”,简称“信创”。一般来说,信创包括基础硬件、基础软件、应用软件、信息安全四大板块。其中,基础硬件主要包括&#xf…

让最近爆火的ChatGPT来谈谈,作为一个技术人该如何写好一篇技术博文

ChatGPT 是由 OpenAI 训练的一个大型语言模型。专门设计用于回答用户提出的问题,我可以提供有价值的信息,并帮助用户解决问题 下面的回答均来自ChatGPT CharGPT如何写好一篇技术博文?写技术博文需要具备那些能力就用java实现冒泡排序来写一篇…

C语言画贝塞尔曲线的函数

程序截图 简单说明 这个函数就是 void drawBezierCurve(COLORREF color, const unsigned int len, ...) color 是贝塞尔曲线的颜色,len 是画出贝塞尔曲线所需要的点的个数,最少 1 个,不要乱传。之后的参数传的就是画出贝塞尔曲线要的点&am…

大数据时代,数据实时同步解决方案的思考—最全的数据同步总结

F、 客户端开发,在maven中引入canal的依赖 com.alibaba.otter canal.client 1.0.21 代码示例: package com.example; import com.alibaba.otter.canal.client.CanalConnector; import com.alibaba.otter.canal.client.CanalConnectors; import c…

[附源码]Nodejs计算机毕业设计基于Web美食网站设计Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置: Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分…

C++ Reference: Standard C++ Library reference: Containers: map: map: begin

C官网参考链接&#xff1a;https://cplusplus.com/reference/map/map/begin/ 公有成员函数 <map> std::map::begin C98 iterator begin(); const_iterator begin() const; C11 iterator begin() noexcept; const_iterator begin() const noexcept;返回指向开始的iterato…

[附源码]Python计算机毕业设计甘肃草地植物数字化标本库管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

图拉普拉斯矩阵

正定矩阵 在线性代数里&#xff0c;正定矩阵 (positive definite matrix) 有时会简称为正定阵。 广义定义&#xff1a;设M是n阶方阵&#xff0c;如果对任何非零向量z&#xff0c;都有z⃗TMz⃗>0\vec{z}^TM\vec{z}>0zTMz>0&#xff0c;则称M为正定矩阵。 狭义定义&…

CSS之display:grid的用法和动态:before content内容

CSS之display:grid的用法和动态:before content内容1. display:grid的用法2.动态:before content内容3.完整代码&#xff1a;项目诉求&#xff1a; 突然有个需求&#xff0c;就是 指定行列&#xff0c;并呈现N字型展示数据&#xff0c;如下所示&#xff1a; 有纠结是用display:…

[附源码]Python计算机毕业设计高校创新学分申报管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

来看!这才是久经沙场得 SQL 优化经验

跟着 SQL 优化得经验之谈&#xff0c;面试真的可以侃侃而谈。 那么面对复杂的关系数据&#xff0c;我们如何来优化&#xff0c;SQL如何玩转更优&#xff1f; 先抛出了4个关于优化方面的问题&#xff1a; 1.返回表中0.014%的数据应不应该走索引&#xff1f; 2.什么样的列必须…

股票买卖接口如何实现委托下单的功能?

股票买卖接口如何实现委托下单的功能&#xff1f;一般来说&#xff0c;股票买卖接口都是相关的人士已经设计好&#xff0c;并且是程序形式呈现出来的&#xff0c;和券商系统链接起来&#xff0c;这样就可以实现交易了&#xff0c;下面给分享关于股票买卖接口是如何执行委托下单…

计算机系统实验-DataLab

一.实验题目及要求 在给定规则限制下完成bits.c中的函数。其中最主要的规则如下&#xff1a; 整数规则 不能使用for while if等只能使用! ˜ & ˆ | << >>运算符只能使用int只能使用0-0xFF的常数使用运算符数不超过限制(Max ops)不能使用全局变量或调用函数…

将简单工厂模式改造应用到项目中,而不是纸上谈兵

10月26日晚补充&#xff1a;经过掘友的提醒&#xff0c;我才发现之前我这篇所写的策略模式&#xff0c;其本身更偏向于工厂模式&#xff0c;我起初以为是掘友分不清工厂模式和策略模式&#xff0c;实际上是我自己把自己绕进去&#xff0c;看不清工厂模式和策略模式的区别。 因…

网闸的工作原理

网闸GAP由固态读写开关和存储人质系统组成&#xff0c;其中固态开关的转换效率达到了纳秒级&#xff0c;存储介质通常采用scsi硬盘&#xff0c;因此GAP的性能得到了保证。 GAP连接在两个独立的网络系统中间&#xff0c;内网与外网永远不同时连接&#xff0c;在同一时刻只有一个…

鱼传科技:函数计算,只要用上就会觉得香

深圳鱼传科技有限公司是专注以精准营销和互联网生态产品运营为核心的综合互联网营销推广服务商。通过整合全网优质媒体资源&#xff0c;并结合智能数据模型和 AI 标签算法&#xff0c;向企业提供包括流量矩阵搭建运营、媒介流量采买、投放模型设计、产品营销策划、数据监控分析…

面试官:如何解决 Redis 数据倾斜、热点等问题

Redis 作为一门主流技术&#xff0c;应用场景非常多&#xff0c;很多大中小厂面试都列为重点考察内容 前几天有小伙伴学习时&#xff0c;遇到下面几个问题&#xff0c;来咨询小编 考虑到这些问题比较高频&#xff0c;工作中经常会遇到&#xff0c;这里写篇文章系统讲解下 问…