Git的学习之旅~

快要投实习了,抓紧复习一下Git,忘得差不多了,和新学一样QAQ
如有错误,还希望各位大佬批评指正
Git学习网站,可以进行实操学习
还是挺好van的
在这里插入图片描述

废话少说,直接开始

基础篇

Git Commit(提交)

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

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

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

关于提交记录太深入的东西咱们就不再继续探讨了,现在你可以把提交记录看作是项目的快照。提交记录非常轻量,可以快速地在这些提交记录之间切换!

命令

git commit

(补充说明~箭头指向的是它的父节点)
提交之前
在这里插入图片描述
提交之后,可以看到成功创建了一个新的提交记录
在这里插入图片描述

Git Branch(分支)

Git 的分支也非常轻量。它们只是简单地指向某个提交纪录 —— 仅此而已。所以许多 Git 爱好者传颂:
早建分支!多用分支!
这是因为即使创建再多的分支也不会造成储存或内存上的开销,并且按逻辑分解工作到不同的分支要比维护那些特别臃肿的分支简单多了。

在将分支和提交记录结合起来后,我们会看到两者如何协作。现在只要记住使用分支其实就相当于在说:“我想基于这个提交以及它所有的父提交进行新的工作。”

git branch 分支名称

创建分支,这里值得注意的是,main后面跟了一个“ * ”
那个星号代表的意思是当前所在的哪一条支路上也就是我用commit之类的命令,会作用在哪条线上。这里显而易见作用在main上。
在这里插入图片描述
这里就是没有切换到新分支,导致新分支停留在原地
在这里插入图片描述
肯定有小伙伴要问了,这么切换分支?
现在咱们告诉 Git 我们想要切换到新的分支上

git checkout <想要切换到的分支名称>

注意:在 Git 2.23 版本中,引入了一个名为 git switch 的新命令,最终会取代 git checkout,因为 checkout 作为单个命令有点超载(它承载了很多独立的功能)。 可以点击这里好好研究一下。

有的小伙伴就要问了,我既然建了分支就要直接用它,我建完了还得切,有没有更快的办法
当然有!建完直接切换美滋滋~

git checkout -b <新分支名称>

测试代码如下

git branch bugFix //创建bugFix分支
git checkout bugFix //切换到bugFix分支,让“*”从main转移到bugFix上,完成切换功能
git commit //可以观察到,bugFix分支提交了一次

在这里插入图片描述

Git merge(合并)

分支就是为了到最后合并到主线上,所以合并是必不可少的,将两个分支合并到一起。就是说我们新建一个分支,在其上开发某个新功能,开发完成后再合并回主线。
咱们先来看一下第一种方法 ——git merge 。在 Git 中合并两个分支时会产生一个特殊的提交记录,它有两个父节点。翻译成自然语言相当于:“我要把这两个父节点本身及它们所有的祖先都包含进来。”
命令如下

git merge <填入被合并的分支,合并到当前带有“*”的主线中>

准备了两个分支,每个分支上各有一个独有的提交。这意味着没有一个分支包含了我们修改的所有内容。咱们通过合并这两个分支来解决这个问题。
我们要把 bugFix 合并到 main(也就是带有“ * ”的主线中) 里 git merge bugFix
在这里插入图片描述
当然也可以从main合并到bugFix分支中,前提是bugFix要带有“ * ”作为主线
也就是先切换到bugFix分支作为主线,再把分支main合并到主线bugFix上就大功告成了
在这里插入图片描述

创建新分支 bugFix

用 git checkout bugFix 命令切换到该分支

git commit提交一次

用 git checkout main 切换回 main

git commit再提交一次

用 git merge 把 bugFix 合并到 main

在这里插入图片描述

Git Rebase(复制合并分支)
第二种合并分支的方法是 git rebase。Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。

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

命令

git rebase <想要继承的目标节点>
先git checkout bugFix 切换到分支为主线
再git rebase main 将bugFix(当前节点)继承C2的main(目标)节点内容
此时完成了bugFix主线的合并以及更新,但main分支尚且没有得到更新,下一步就是对main进行更新

在这里插入图片描述
注意,提交记录 C3 依然存在(树上那个半透明的节点),而 C3’ 是我们 Rebase 到 main 分支上的 C3 的副本。此时的问题是main分支还没有更新,下一步就是要对main分支进行更新
相当于我把C3这个节点复制一份,继承C2节点,再更新一下main分支就行

先git checkout main 切换到主分支上
再git rebase bugFix 更新到bugFix 由于bugFix 继承自main,
所以 Git 只是简单的把 main 分支的引用向前移动了一下而已。
这就完成了main分支的更新操作

在这里插入图片描述

高级篇

HEAD(指向提交记录)
我们首先看一下 “HEAD”。 HEAD 是一个对当前检出记录的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。
HEAD 总是指向当前分支上最近一次提交记录。大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的。
HEAD 通常情况下是指向分支名的(如 bugFix)。在你提交时,改变了 bugFix 的状态,这一变化通过 HEAD 变得可见。

补充:单独把HEAD和main主线分开并且回溯一个节点的命令
git checkout HEAD^

直接用checkout命令,可以指向节点C1,也可以直接指向main分支来间接指向C1在这里插入图片描述

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

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

比较令人欣慰的是,Git 对哈希的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。因此我可以仅输入fed2 而不是上面的一长串字符。
使用相对引用的话,你就可以从一个易于记忆的地方(比如 bugFix 分支或 HEAD)开始计算。
相对引用非常给力,这里我介绍两个简单的用法:

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

达到回溯的目的
如图为切换到main的上一个父节点,假设我想把head指向切换到C0呢?使用指令

git checkout main^^

在这里插入图片描述
在这里插入图片描述
相对引用2(~)
由上文可知,移动一次用一个相对引用^挺麻烦的,那么我移动多次就得多个符号,很烦
这里就引出了相对引用的另一个用法(~)来进行多次的移动处理
命令如下

 ~<想要后退的步数>
 例如~<4>就是一次性后退4步

强制修改分支位置 git branch -f 分支名 目标节点
你现在是相对引用的专家了,现在用它来做点实际事情。
我使用相对引用最多的就是移动分支。可以直接使用 -f 选项让分支指向另一个提交。例如:

git branch -f main HEAD~3
或者
git branch -f main C1 强制移动main分支指向C1节点
补充HEAD单独回退一步
git checkout HEAD^

上面的命令会将 main 分支强制指向 HEAD 的第 3 级父提交。
可以看到,主分支bugFix保持不动,main作为分支完成了回溯。
在这里插入图片描述

撤销变更
在 Git 里撤销变更的方法很多。和提交一样,撤销变更由底层部分(暂存区的独立文件或者片段)和上层部分(变更到底是通过哪种方式被撤销的)组成。我们这个应用主要关注的是后者。
主要有两种方法用来撤销变更 —— 一是 git reset,还有就是 git revert。接下来咱们逐个进行讲解。
命令:

git reset HEAD~<回溯步数>

在这里插入图片描述
以上进针对本地代码库的回溯,公共的远程分支上用这个是不行的,此时引申出了新命令
撤销更改并分享给别人,我们需要使用 git revert。
另一种远程分支撤销的办法,注意,这里是撤销之后并分享给别人
假设我C2节点的内容我觉得不好,想丢掉,这个时候就把C1的内容复制一份出来,在C2的节点上再引申出一个C1节点的复制品C2 ’ 来覆盖掉之前的想撤销掉的C2节点
效果如图

git revert HEAD

在这里插入图片描述

移动提交记录

Git Cherry-pick
一般用于我知道要复制哪些节点,直接复制的情况

git cherry-pick <提交号,想要复制的节点,可以多个,用空格分开>

直接把目标节点复制一份抓过来放到当前主分支上~
在这里插入图片描述

在这里插入图片描述

交互式的 rebase

前面的cherry-pick用于我知道复制哪个节点,那么有时候我不知道复制哪些节点,就用rebase

当你知道你所需要的提交记录(并且还知道这些提交记录的哈希值)时, 用 cherry-pick 再好不过了 —— 没有比这更简单的方式了。
但是如果你不清楚你想要的提交记录的哈希值呢? 幸好 Git 帮你想到了这一点, 我们可以利用交互式的 rebase —— 如果你想从一系列的提交记录中找到想要的记录, 这就是最好的方法了

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

如果你在命令后增加了这个选项, Git 会打开一个 UI 界面并列出将要被复制到目标分支的备选提交记录,它还会显示每个提交记录的哈希值和提交说明,提交说明有助于你理解这个提交进行了哪些更改。
在实际使用时,所谓的 UI 窗口一般会在文本编辑器 —— 如 Vim —— 中打开一个文件。 考虑到课程的初衷,我弄了一个对话框来模拟这些操作。
当 rebase UI界面打开时, 你能做3件事:
调整提交记录的顺序(通过鼠标拖放来完成)
删除你不想要的提交(通过切换 pick 的状态来完成,关闭就意味着你不想要这个提交记录)
合并提交。 遗憾的是由于某种逻辑的原因,我们的课程不支持此功能,因此我不会详细介绍这个操作。简而言之,它允许你把多个提交记录合并成一个。
可以完成类似的功能
在这里插入图片描述
类似于图形化调整节点顺序
在这里插入图片描述

杂项

本地栈式提交
来看一个在开发中经常会遇到的情况:我正在解决某个特别棘手的 Bug,为了便于调试而在代码中添加了一些调试命令并向控制台打印了一些信息。
这些调试和打印语句都在它们各自的提交记录里。最后我终于找到了造成这个 Bug 的根本原因,解决掉以后觉得沾沾自喜!
最后就差把 bugFix 分支里的工作合并回 main 分支了。你可以选择通过 fast-forward 快速合并到 main 分支上,但这样的话 main 分支就会包含我这些调试语句了。你肯定不想这样,应该还有更好的方式……

实际我们只要让 Git 复制解决问题的那一个提交记录就可以了。跟之前我们在“整理提交记录”中学到的一样,我们可以使用,说人话就是,用之前的复制节点命令,把本地修好Bug并且已经删除掉调试语句的内容复制一份给主线就行

git rebase -i
git cherry-pick

来达到目的。

Git Tags(标签)
分支很容易被人为移动,并且当有新的提交时,它也会移动。分支很容易被改变,大部分分支还只是临时的,并且还一直在变。
你可能会问了:有没有什么可以永远指向某个提交记录的标识呢,比如软件发布新的大版本,或者是修正一些重要的 Bug 或是增加了某些新特性,有没有比分支更好的可以永远指向这些提交的方法呢?
Git 的 tag 就是干这个用的,它们可以(在某种程度上 —— 因为标签可以被删除后重新在另外一个位置创建同名的标签)永久地将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。它们并不会随着新的提交而移动。你也不能切换到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。
命令

git tag 版本号 被版本号标记的目标节点

在这里插入图片描述

Git Describe
由于标签在代码库中起着“锚点”的作用,Git 还为此专门设计了一个命令用来描述离你最近的锚点(也就是标签),它就是 git describe

在这里插入代码片git describe 的​​语法是:

git describe <ref>

<ref> 可以是任何能被 Git 识别成提交记录的引用,如果你没有指定的话,Git 会以你目前所检出的位置(HEAD)。

它输出的结果是这样的:

<tag>_<numCommits>_g<hash>

tag 表示的是离 ref 最近的标签, numCommits 是表示这个 ref 与 tag 相差有多少个提交记录, hash 表示的是你所给定的 ref 所表示的提交记录哈希值的前几位。

当 ref 提交记录上有某个标签时,则只输出标签名称

远程分支

创建远程仓库
学习远程仓库的操作 —— 我们需要一个配置这种环境的命令, 它就是 git clone。 从技术上来讲,git clone 命令在真实的环境下的作用是在本地创建一个远程仓库的拷贝(比如从 github.com)。
命令

git clone

在这里插入图片描述

远程分支
在这里插入图片描述
在这里插入图片描述
Git Fetch
Git 远程仓库相当的操作实际可以归纳为两点:向远程仓库传输数据以及从远程仓库获取数据。既然我们能与远程仓库同步,那么就可以分享任何能被 Git 管理的更新(因此可以分享代码、文件、想法、情书等等)。
本节课我们将学习如何从远程仓库获取数据 —— 命令如其名,它就是
git fetch
在这里插入图片描述
git fetch 做了些什么?

git fetch 完成了仅有的但是很重要的两步:
1.从远程仓库下载本地仓库中缺失的提交记录
2.更新远程分支指针(如 o/main)
git fetch 实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。

注意,这里看起来是把本地节点覆盖了,但实际上不是这样的,仅仅是把它下载下来了。理解这一点很重要,因为许多开发人员误以为执行了 git fetch 以后,他们本地仓库就与远程仓库同步了。它可能已经将进行这一操作所需的所有数据都下载了下来,但是并没有修改你本地的文件。(也可以说这里只是单纯的下载操作)

Git Pull
如果想协同开发,就需要把别人的代码拿过来,最少也要两步

git fetch	下载别人的节点
git merge o/main	合并分支

这就很麻烦了,所以有了git pull作为上面两个命令的缩写
就可以完成合并,把别人的代码合并进来

模拟团队合作
这意味着,我们需要“假装”你的同事、朋友、合作伙伴更新了远程仓库,有可能是某个特定的分支,或是几个提交记录。

Git Push

git push

将本地的记录推送到远程仓库

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

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

这个时候再push就没法提交了
git push 失败是因为你最新提交的 C3 基于远程分支中的 C1。而远程仓库中该分支已经更新到 C2 了,所以 Git 拒绝了你的推送请求。

最直接的解决方式就是先从远程仓库fetch最新代码,再用rebase把之前提交失败的C3代码复制一份形成C3 ’ 继承在C2之下
在这里插入图片描述当然有没有简单一点的,不用fetch在rebase的命令?
当然 —— 前面已经介绍过 git pull 就是 fetch 和 merge 的简写,类似的 git pull --rebase 就是 fetch 和 rebase 的简写!

暂时就写到这吧,后面学到哪记到哪

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值