Git 学习笔记

 

Git 仓库中的提交记录保存的是你的目录下所有文件的快照,就像是把整个目录复制,然后再粘贴一样,但比复制粘贴优雅许多!

Git 希望提交记录尽可能地轻量,因此在你每次进行提交时,它并不会盲目地复制整个目录。条件允许的情况下,它会将当前版本与仓库中的上一个版本进行对比,并把所有的差异打包到一起作为一个提交记录。

Git 还保存了提交的历史记录。这也是为什么大多数提交记录的上面都有 parent 节点的原因 —— 我们会在图示中用箭头来表示这种关系。对于项目组的成员来说,维护提交历史对大家都有好处。

前言:

 学习网站如下:(网站包含不常用的10% Git 操作)Learn Git Branchingicon-default.png?t=N6B9https://learngitbranching.js.org/?locale=zh_CN

请开始你的学习吧!


 

基础篇

 一个(小型)Git 代码库。当前有两个提交记录 —— 初始提交 C0 和其后可能包含某些有用修改的提交 C1

1.Git commit

git commit  创建一个新的提交记录。

操作修改了代码库,并把这些修改保存成了一个提交记录 C2C2 的 parent 节点是 C1, parent 节点是当前提交中变更的基础


2.Git branch

即使创建再多的分支也不会造成储存或内存上的开销,并且按逻辑分解工作到不同的分支要比维护那些特别臃肿的分支简单多了。

 


 

3.分支与合并 - 1️⃣Git merge

例1: 

 例2:

 main 继承自 bugFix,Git 什么都不用做,只是简单地把 bugFix 移动到 main 所指向的那个提交记录。

2️⃣Git Rebase

Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。

Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。

⭕注意:把 bugFix 分支里的工作直接移到 main 分支上。移动以后会使得两个分支的功能看起来像是按顺序开发,但实际上它们是并行开发的。 

现在 bugFix 分支上的工作在 main 的最顶端,同时我们也得到了一个更线性的提交序列。

⭕提交记录 C3 依然存在(树上那个半透明的节点),而 C3' 是我们 Rebase 到 main 分支上的 C3 的副本。

由于 bugFix 继承自 main,所以 Git 只是简单的把 main 分支的引用向前移动了一下而已。


高级篇 

1.HEAD 

HEAD 是一个对当前所在分支的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。

HEAD 总是指向当前分支上最近一次提交记录。大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的。

HEAD 通常情况下是指向分支名的

如果想看 HEAD 指向,可以通过 cat .git/HEAD 查看, 如果 HEAD 指向的是一个引用,还可以用 git symbolic-ref HEAD 查看它的指向。 

分离的 HEAD

分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。在命令执行之前的状态如下所示:

HEAD -> main -> C1

HEAD 指向 main, main 指向 C1

 


2.相对应用

通过指定提交记录哈希值的方式在 Git 中移动不太方便。在实际应用时,并没有像本程序中这么漂亮的可视化提交树供你参考,所以你就不得不用 git log 来查查看提交记录的哈希值。

并且哈希值在真实的 Git 世界中也会更长(译者注:基于 SHA-1,共 40 位)。例如前一关的介绍中的提交记录的哈希值可能是 fed2da64c0efc5293610bdd892f82a58e8cbc5d8。舌头都快打结了吧...

但Git 对哈希的处理很智能。只需要提供能够唯一标识提交记录的前几个字符即可。

通过哈希值指定提交记录很不方便,所以 Git 引入了相对引用。这个就很厉害了!

使用相对引用的话,你就可以从一个易于记忆的地方(比如 bugFix 分支或 HEAD)开始计算。

相对引用非常给力,这里我介绍两个简单的用法:

  • 使用 ^ 向上移动 1 个提交记录
  • 使用 ~<num> 向上移动多个提交记录,如 ~3

(1)操作符 (^)

把这个符号加在引用名称的后面,表示让 Git 寻找指定提交记录的 parent 提交。

  • main^ 相当于“main 的 parent 节点”。
  • main^^ 是 main 的第二个 parent 节点

例1: 

例2:

(2)“~”操作符

在提交树中向上移动很多步的话,敲那么多 ^ 貌似也挺烦人的,于是又引入了操作符 ~。 

该操作符后面可以跟一个数字(可选,不跟数字时与 ^ 相同,向上移动一次),指定向上移动多少次。

⭕使用相对引用最多的就是移动分支。可以直接使用 -f 选项让分支指向另一个提交。例如:

  • git branch -f main HEAD~3
  • 会将 main 分支强制指向 HEAD 的第 3 级 parent 提交。

 -f 则容许将分支强制移动到那个位置


3.撤销变更 reset,revert

撤销变更由底层部分(暂存区的独立文件或者片段)和上层部分(变更到底是通过哪种方式被撤销的)组成。

git reset 通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。git reset 向上移动分支,原来指向的提交记录就跟从来没有提交过一样。

⭕注意: 

git reset 很方便,但是这种“改写历史”的方法对使用的远程分支是无效的哦!

为了撤销更改并分享给别人,我们需要使用 git revert

4.整理提交记录  Git Cherry-pick

git cherry-pick <提交号>...

将一些提交复制到当前所在的位置(HEAD)下面


5.交互式的 rebase

知道所需要的提交记录(并且还知道这些提交记录的哈希值)时,用 cherry-pick

不清楚想要的提交记录的哈希值——交互式的 rebase

交互式 rebase 指的是使用带参数  --interactive 的 rebase 命令, 简写为 -i。

如果在命令后增加了这个选项, Git 会打开一个 UI 界面并列出将要被复制到目标分支的备选提交记录,它还会显示每个提交记录的哈希值和提交说明,提交说明有助于你理解这个提交进行了哪些更改。

当 rebase UI界面打开时, 能做3件事:

  • 调整提交记录的顺序(通过鼠标拖放来完成)
  • 删除你不想要的提交(通过切换 pick 的状态来完成,关闭就意味着你不想要这个提交记录)
  • 合并提交。 遗憾的是由于某种逻辑的原因,我们的课程不支持此功能,因此我不会详细介绍这个操作。简而言之,它允许你把多个提交记录合并成一个。

 


6.Git Tags

可以(在某种程度上 —— 因为标签可以被删除后重新在另外一个位置创建同名的标签)永久地将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。

它们并不会随着新的提交而移动。你也不能切换到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。

远程篇

1.远程仓库-Git clone

远程仓库却有一系列强大的特性

  • 首先也是最重要的的点, 远程仓库是一个强大的备份。本地仓库也有恢复文件到指定版本的能力, 但所有的信息都是保存在本地的。有了远程仓库以后,即使丢失了本地所有数据, 你仍可以通过远程仓库拿回你丢失的数据。

  • 还有就是, 远程让代码社交化了! 既然你的项目被托管到别的地方了, 你的朋友可以更容易地为你的项目做贡献(或者拉取最新的变更)

Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。

git clone 命令在真实的环境下的作用是在本地创建一个远程仓库的拷贝(比如从 github.com)。 

⭕本地仓库多了一个名为 o/main 的分支, 这种类型的分支就叫远程分支。由于远程分支的特性导致其拥有一些特殊属性:

远程分支 反映了 远程仓库(在你上次和它通信时)的状态。这会有助于你理解本地的工作与公共工作的差别 —— 这是你与别人分享工作成果前至关重要的一步.

在你切换到远程分支时,自动进入分离 HEAD 状态。Git 这么做是出于不能直接在这些分支上进行操作的原因, 你必须在别的地方完成你的工作, (更新了远程分支之后)再用远程分享你的工作成果。

o/ 是什么意思?

命名规范  :

  • <remote name>/<branch name>

例:

 o/main 的分支:这个分支就叫 main,远程仓库的名称就是 o

大多数的开发人员会将它们主要的远程仓库命名为 origin,并不是 o。这是因为当你用 git clone 某个仓库时,Git 已经帮你把远程仓库的名称设置为 origin 了 

⭕Git 变成了分离 HEAD 状态,当添加新的提交时 o/main 也不会更新。这是因为 o/main 只有在远程仓库中相应的分支更新了以后才会更新。 

 


2.Git Fetch

Git 远程仓库相当的操作实际可以归纳为两点:

  1. 向远程仓库传输数据
  2. 从远程仓库获取数据

 Git Fetch: 当我们从远程仓库获取数据时, 远程分支也会更新以反映最新的远程仓库

C2,C3 被下载到了本地仓库,同时远程分支 o/main 也被更新 

1️⃣那么 git fetch 做了些什么? 

git fetch 完成了仅有的但是很重要的两步:

  • 从远程仓库下载本地仓库中缺失的提交记录
  • 更新远程分支指针(如 o/main)

git fetch 实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。

远程分支反映了远程仓库在最后一次与它通信时的状态,git fetch 就是你与远程仓库通信的方式了 。

git fetch 通常通过互联网(使用 http:// 或 git:// 协议) 与远程仓库通信。

2️⃣git fetch 不会做的事

git fetch 并不会改变你本地仓库的状态。它不会更新你的 main 分支,也不会修改你磁盘上的文件。 

⭕许多开发人员误以为执行了 git fetch 以后,他们本地仓库就与远程仓库同步了。它可能已经将进行这一操作所需的所有数据都下载了下来,但是并没有修改你本地的文件。


3.Git Pull 

当远程分支中有新的提交时,你可以像合并本地分支那样来合并远程分支。也就是说就是你可以执行以下命令:

  • git cherry-pick o/main
  • git rebase o/main
  • git merge o/main
  • 等等

因此由于先抓取更新再合并到本地分支这个流程很常用,因此 Git 提供了 Git Pull 这一个专门的命令来完成这两个操作

用 fetch 下载了 C3, 然后通过 git merge o/main 合并了这一提交记录。现在 main 分支包含了远程仓库中的更新(在本例中远程仓库名为 origin) 

 

 


4.模拟团队合作 

我们引入一个自造命令 git fakeTeamwork “假装”你的同事、朋友、合作伙伴更新了远程仓库,有可能是某个特定的分支,或是几个提交记录。

fakeTeamwork 默认操作就是在远程仓库的 main 分支上做一次提交。 

还可以指定提交的分支或是数量,只需要在命令后加上它们就可以了。

通过一个命令,我们就模拟队友推送了 3 个提交记录到远程仓库的 foo 分支。

 


 

5. Git  Push

git push 负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。

⭕注意 :  git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。它的默认值取决于你正使用的 Git 的版本,但是在教程中我们使用的是 upstream

 

6.偏离的工作

假设你周一克隆了一个仓库,然后开始研发某个新功能。到周五时,你新功能开发测试完毕,可以发布了。但是 —— 天啊!你的同事这周写了一堆代码,还改了许多你的功能中使用的 API,这些变动会导致你新开发的功能变得不可用。但是他们已经将那些提交推送到远程仓库了,因此你的工作就变成了基于项目旧版的代码,与远程仓库最新的代码不匹配了。

这种情况下, git push 就不知道该如何操作了。如果你执行 git push,Git 应该让远程仓库回到星期一那天的状态吗?还是直接在新代码的基础上添加你的代码,亦或由于你的提交已经过时而直接忽略你的提交?

因为这情况(历史偏离)有许多的不确定性,Git 是不会允许你 push 变更的。实际上它会强制你先合并远程最新的代码,然后才能分享你的工作。

 

 什么都没有变,因为命令失败了!git push 失败是因为你最新提交的 C3 基于远程分支中的 C1。而远程仓库中该分支已经更新到 C2 了,所以 Git 拒绝了你的推送请求。

解决办法:需要做的就是使你的工作基于最新的远程分支。

最直接的方法就是通过 rebase 调整你的工作。

1️⃣push 之前做 rebase 

用 git fetch 更新了本地仓库中的远程分支,然后用 rebase 将我们的工作移动到最新的提交记录下,最后再用 git push 推送到远程仓库。 

 git pull --rebase 就是 fetch 和 rebase 的简写


2️⃣merge 替换 rebase 

git merge 不会移动工作(它会创建新的合并提交),但是它会告诉 Git 你已经合并了远程仓库的所有变更。这是因为远程分支现在是你本地分支的祖先,也就是说你的提交已经包含了远程分支的所有变化 

用 git fetch 更新了本地仓库中的远程分支,然后合并了新变更到我们的本地分支(为了包含远程仓库的变更),最后我们用 git push 把工作推送到远程仓库 

 git pull 就是 fetch 和 merge 的简写,类似的 git pull --rebase 就是 fetch 和 rebase 的简写!

7.远程服务器拒绝!(Remote Rejected)

 

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

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

相关文章

华为盘古大模型:能源领域的颠覆性突破

近日&#xff0c;华为盘古大模型在能源领域横空出世&#xff0c;引发了广泛关注和期待。作为一项具有颠覆性影响的技术创新&#xff0c;华为盘古大模型在能源行业中展现出巨大的潜力和前景。其优质的计算能力和智能优化算法&#xff0c;将为能源产业带来翻天覆地的变革。 盘古大…

一篇文章搞定数据同步工具SeaTunnel

文章目录 前言第 1 章 Seatunnel 概述第 2 章 Seatunnel 安装和使用第 3 章 SeaTunnel 基本原理第 4章应用案例后记 前言 SeaTunnel安装包及代码&#xff1a; 链接: https://pan.baidu.com/s/1JvgAZpqoOPJ0ecfxUbLo4Q 提取码: pur8 –来自百度网盘超级会员v4的分享 第 1 章 …

成为一名数字IC后端工程师需要掌握哪些技能?(内附学习视频)

众所周知&#xff0c;数字后端设计是IC设计中必不可少的一个环节&#xff0c;数字后端工程师是将门级网表转换成标准的GDS文件&#xff0c;又称为设计实现或物理设计。正所谓前端保证功能正确&#xff0c;后端保证芯片的实现正确。 数字后端工程师是做什么的&#xff1f; 数字…

多线程(JavaEE初阶系列3)

目录 前言&#xff1a; 1.中断一个线程 2.等待一个线程-join() 2.1join()无参调用的使用 2.2join()有参调用的使用 3.线程的状态 3.1观察线程的所有状态 4.多线程带来的风险—线程安全 4.1观察线程不安全 4.2该问题出现的原因 4.3线程不安全问题的解决 4.3.1synchro…

解决JMeter+Grafana+influxdb 配置出现transaction无数据情形

问题描述 JMeterGrafanainfluxdb 配置时&#xff0c;Darren洋发现jmeter中明明已经配置好了事务条件以及接口实例信息&#xff0c;但就是在grafana的头部导航栏中的transaction按钮下来没有相应事务数据信息&#xff0c;经过相关资料查询&#xff0c;Darren洋发现执行以下两个步…

搭建基于Nginx+Keepalived的高可用web集群并实现监控告警

目录 搭建相关服务器DNS服务器配置WEB服务器配置配置静态IP编译安装nginx 负载均衡器配置lb1lb2高可用配置 NFS服务器配置配置静态IP安装软件包新建共享目录web服务器挂载 监控服务器配置安装node-exporter编写prometheus.yml安装alertmanager和钉钉插件获取机器人webhook编写a…

Python实战之数据挖掘详解

一、Python数据挖掘 1.1 数据挖掘是什么&#xff1f; 数据挖掘是从大量的、不完全的、有噪声的、模糊的、随机的实际应用数据中&#xff0c;通过算法&#xff0c;找出其中的规律、知识、信息的过程。Python作为一门广泛应用的编程语言&#xff0c;拥有丰富的数据挖掘库&#…

Nginx配置解析

server {listen 80;server_name example.com;location / {proxy_pass http://backend;}location / 是 Nginx 的一个匹配规则&#xff0c;用于匹配所有请求路径。proxy_pass 指令则用于将匹配到的请求转发给指定的后端服务器。下面是关于 location / 和 proxy_pass 的详细介绍&a…

解决嵌入式中QTableWidget双击出现空白QTableWidgetItem输入

目录 所说BUG现象解决方式1方式2全部内容 效果 今天突然想起在上个公司解决的一个BUG 嵌入式中QTableWidget一般只能看数据不能编辑&#xff0c;或者是选择 所以双击出现空白QTableWidgetItem是不允许的 所说BUG现象 解决 在空白的单元格中&#xff0c;添加不可编辑的QTableWid…

数字孪生:未来科技的新前沿

数字孪生作为一项新兴的研究方向&#xff0c;正逐渐成为科技界的焦点。它是将现实世界中的实体、系统或过程通过数字化手段进行建模、仿真和分析&#xff0c;形成与实体相对应的数字化副本。数字孪生的发展为我们带来了无限的想象空间&#xff0c;以及解决现实问题的新途径。 在…

Zabbix监控安装grafana并配置图形操作

第三阶段基础 时 间&#xff1a;2023年7月20日 参加人&#xff1a;全班人员 内 容&#xff1a; Zabbix监控安装grafana 目录 安装并配置grafana 一、安装Grafana 二、下载安装插件 三、配置grafana 四、Web访问并配置&#xff1a; 安装并配置grafana 一、安装Graf…

【团队协作开发】将Gitee项目导入到本地IDEA中出现根目录不完整的问题解决(已解决)

前言&#xff1a;在团队协作开发过程中&#xff0c;通常我们的Gitee完整项目中会包含很多内容&#xff1a;后端代码、前端代码、项目结构图、项目文档等一系列资产。 将Gitee项目导入到本地IDEA中&#xff0c;通常会出现根目录不完整的问题。这是因为项目里面包含了后端代码、前…

基于Java+SpringBoot+vue前后端分离甘肃非物质文化网站设计实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

DAY51:动态规划(十五)买卖股票最佳时机Ⅲ+买卖股票最佳时期Ⅳ

文章目录 123.买卖股票最佳时机Ⅲ&#xff08;注意初始化&#xff09;思路DP数组含义递推公式初始化遍历顺序最开始的写法&#xff1a;初始化全部写成0debug测试&#xff1a;解答错误&#xff0c;第0天实际上是对应prices[0]和dp[0] 完整版总结 188.买卖股票最佳时机Ⅳ思路DP数…

09.计算机网络——套接字编程

文章目录 网络字节序socket编程socket 常见APIsockaddr结构 UDP编程创建socket绑定socketsendto发送数据recvform接收数据关闭socket TCP编程创建socket绑定socketlisten监听套接字accept服务端接收连接套接字connect客户端连接套接字send发送数据recv接收数据关闭socket 工具n…

【flink】ColumnarRowData

列式存储 在调试flink读取parquet文件时&#xff0c;读出来的数据是ColumnarRowData&#xff0c;由于parquet是列式存储的文件格式&#xff0c;所以需要用一种列式存储的表示方式&#xff0c;ColumnarRowData就是用来表示列式存储的一行数据&#xff0c;它包含多个数组的数据结…

从电商指标洞察到运营归因,只需几句话?AI 数智助理准备好了!

Lily 是名入职不久的电商运营助理&#xff0c;最近她想要根据 2022 年的客单价情况&#xff0c;分析品牌 A 在不同电商渠道的用户行为和表现&#xff0c;并提供一些有价值的洞察和建议给客户。然而在向技术人员提报表需求后&#xff0c;技术人员以需求排满为借口拒绝了。 Lily …

5分钟,结合 LangChain 搭建自己的生成式智能问答系统

伴随大语言模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;的涌现&#xff0c;人们发现生成式人工智能在非常多领域具有重要意义&#xff0c;如图像生成&#xff0c;书写文稿&#xff0c;信息搜索等。随着 LLM 场景的多样化&#xff0c;大家希望 LLM 能在垂直…

记一次容器环境下出现 Address not available

作者&#xff1a;郑明泉、余凯 困惑的源地址 pod 创建后一段时间一直是正常运行&#xff0c;突然有一天发现没有新的连接创建了&#xff0c;业务上是通过 pod A 访问 svc B 的 svc name 的方式&#xff0c;进入 pod 手动去 wget 一下&#xff0c;发现报错了 Address not avai…

jar 更新 jar包内的 class,以及如何修改class

一、提取Jar 内文件 #提取jar内的配置文件jar -xvf a.jar META-INF\plugin.xml-已解压: META-INF/plugin.xml#提取jar内的class文件&#xff0c; 提示&#xff1a;反编译为java文件&#xff0c;修改后再使用javac xxx.java编译为class&#xff0c;jar -xvf a.jar io.config.**…