learn git branching学习整理2

介绍

learn git branching是一个非常好的git学习网站,它与传统的文字讲解相比较起来有一个非常大的亮点----图形化的git提交树可以实时的反馈并告诉你当前所做的git操作在对于代码管理来说实际意味着什么,这是一个非常好的反馈机制,相比较于直接用命令行来学习git,你会更加了解当前正在做什么。
learn git branching还内置了一套自己的git算法,其大部分命令和真实的git命令没有区别,并且它会以闯关的形式进行git教学,如果能够顺利的通过所有关卡,那么初学者对于git的理解也就差不多了。

链接: https://learngitbranching.js.org/?locale=zh_CN.

我在刚开始接触并通过learn git branching学习git的时候正是被上面的那些优点所吸引,产生了想要快速通关的想法,但是在中途的时候我发现,每一个独立的每一个小关卡虽然简单,但是其实之后的一个关卡的通过其实都要依赖一些之前所用到过的git命令,如果对于之前的命令不加记忆,你很快就会玩不下去,于是我就开始记录通关命令,再后来转念一想由于工作的原因需要用到git,但是公司的电脑只能访问为数不多的知识查询网站(其中就不包括learn git branching)所以干脆还是把每一关的通关记录做成博客,方便以后需要用到的时候随时查看。

另外,我发现learn git branching虽然强大,但是有些git相关的知识他也是不包含的,比如git在真实的环境中,本地电脑下是有三个工作区的(workspace、缓冲区和本地仓库),这一点在教程中都没有体现出来(以后统称learn git branching为教程),另外,由于是git教学的一个网站,它的很多命令也是网站作者自己实现的,所以并不是所有的git命令都可以在该网站上使用验证,所以在这篇博客完成后我会按照教程关卡的顺序在真实环境下详细验证一些我觉得理解起来比较模糊的命令。如果有必要的话,应该会把验证过程也上传到博客。

第十七关:两个父节点

选择提交父记录
操作符^与~符一样,后面也可以跟一个数字。
但是该操作符后面的数字与~后面的不同,并不是用来指定向上返回几代,而是指定合并提交记录的某个夫提交。还记得前面提到过的一个合并提交有两个父提交吧,所以遇到这样的节点时该选择哪条路径就不是很清晰了。
Git默认选择合并提交的“第一个”父提交,在操作符^后跟一个数字可以改变这一默认行为。
废话不多说,举个例子。

基础命令:

这里有一个合并提交记录。如果不加数字修改符直接检出main^,会回到第一个父提交记录。(在我们的图示中,第一个父提交记录是指合并提交记录正上方的那个提交记录)

命令演示

初始条件
在这里插入图片描述
git checkout main^
在这里插入图片描述
这正是我们都已经习惯的方法。
现在来试试另一个父提交:
在这里插入图片描述
git checkout main^2
在这里插入图片描述
看见了吧?我们回到了另外一个父提交上。

组合使用:

使用^和~可以自由地在提交树中移动,非常给力:
在这里插入图片描述
git checkout HEAD~;git checkout HEAD^2;git checkout HEAD~2
在这里插入图片描述
备注:
HEAD~后面如果没有标注数字就表示向前移动一位,等同于HEAD^

更上一层楼:

更厉害地是,这些操作符还支持链式操作!试一下这个:
在这里插入图片描述
git checkout HEAD~^2~2
在这里插入图片描述
备注:
其实就是把上一个例子中HEAD后面的符号全部串起来变成一个命令了,实现的效果是一样的。

通关条件

初始条件:
在这里插入图片描述

通关目标:
在这里插入图片描述

通关命令

我的命令(3步):
git checkout HEAD~^2~ //一步到位指向C2
git checkout -b bugWork //在HEAD指向的地方创建bugWork分支并指向它
git checkout main //当前分支切换为main
标准答案(1步):
git branch bugWork main^^2~ //高端

第十八关:纠缠不清的分支(关于本地git的最后一关)

哇塞大神!这关我们要来点不同的!
现在我们的main分支是比one、two、和three要多几个提交。出于某种原因,我们需要把main分支上最近的几次提交做不同的调整后,分别添加到各个分支上。
one需要重新排序并删除C5,two仅需要重拍排序,而three只需要提交一次。

通关条件

初始条件:
在这里插入图片描述

通关目标:
在这里插入图片描述

通关命令

git checkout one
git cherry-pick c4 c3 c2
git checkout two
git cherry-pick c5 c4 c3 c2
git branch -f three c2

备注

cherry-pick 可以挑选多个提交记录,并且按顺序添加到当前分支下

远程仓库

第十九关:git clone

远程仓库并不复杂,在如今的云计算盛行的世界很容易把远程仓库想象成一个富有魔力的东西,但实际上它们只是你的仓库在另一台计算机上的拷贝。你可以通过因特网与这台计算机通信—也就是增加或是获取提交记录
话虽如此,远程仓库却有一系列强大的特性
① 首先也是最重要的点,远程仓库是一个强大的备份。本地仓库也有恢复文件到指定版本的能力,但所有的信息都是保存在本地的。有了远程仓库以后,即使丢失了本地所有数据,你仍可以通过远程仓库拿回你丢失的数据。
② 还有就是,远程让代码社交化了!既然你的项目被托管到别的地方了,你的朋友可以更容易地为你的项目做贡献(或者拉取最新的变更)
现在用网站来对远程仓库进行可视化操作变得越发流行了(像GitHub或Phabricator),但远程仓库永远是这些工具的顶梁柱,因此理解其概念非常重要!

我们创建远程仓库的命令:

直到现在,教程都聚焦于本地仓库的操作(branch、merge、rebase等等)。但我们现在需要学习远程仓库的操作—我们需要一个配置这种环境的命令,它就是git clone。从技术上讲,git clone命令在真实的环境下的作用是在本地创建一个远程仓库的拷贝(比如从github.com)。但在我们的教程中使用这个命令会有一些不同—它会在远程创建一个你本地仓库的副本。显然这个真实命令的意思刚好相反,但是它帮咱们把本地仓库和远程仓库关联到了一起,在教程中就凑合着用吧。

基础命令

咱们慢慢来,先看看远程仓库(在图示中)的样子。

命令演示

在这里插入图片描述
git clone

在这里插入图片描述

备注

教程中的git clone和真实世界中的git clone是反过来的。真实世界中的git clone是拉取远端代码到本地,教程中的git clone是在远端创建一个本地镜像。

第二十关:远程分支

既然你已经看过git clone命令了,咋们深入地看一下发生了什么。
你可能注意到的第一个事就是在我们的本地仓库多了一个名为o/main的分支,这种类型的分支就叫远程分支。由于远程分支的特性导致其拥有一些特殊属性。
远程分支反映了远程仓库(在你上次和它通信时)的状态。这会有助于你理解本地的工作与公共工作的差别—这是你与别人分享工作成果前至关重要的一步。
远程分支有一个特别的属性,在你检出时自动进入分离HEAD状态。Git这么做是出于不能直接在这些分支上进行操作的原因,你必须在别的地方完成你的工作,(更新了远程分支之后)再用远程分享你的工作成果。

为什么有o/ ?
你可能想问这些远程分支前面的o/是什么意思吧?好吧,远程分支有一个命名规范—它们的格式是:
<remote name>/<branch name>
因此,如果你看到一个名为o/main的分支,那么这个分支就叫main,远程仓库的名称就是o.
大多数的开发人员会将他们主要的远程仓库命名为origin,并不是o.这是因为当你用git clone某个仓库时,git已经帮你把远程仓库的名称设置为origin了。
不过origin对于我们的UI来说太长了,因此不得不使用简写o 但是要记住,当你真正使用Git时,你的远程仓库默认为origin!
说了这么多,让我们看看实例。

基础命令:

如果检出远程分支会怎么样呢?

命令演示

在这里插入图片描述
git checkout o/main;git commit
在这里插入图片描述
正如你所见,Git变成了分离HEAD状态,当添加新的提交时o/main也不会更新。这是因为o/main只有在远程仓库中相应的分支更新了以后才会更新。

通关条件

初始条件:
在这里插入图片描述

通关目标:
在这里插入图片描述

通关命令

git commit
git checkout o/main
git commit

第二十一关:Git Fetch

Git 远程仓库相当的操作实际可以归纳为两点:向远程仓库传输数据以及从远程仓库获取数据。既然我们能与远程仓库同步,那么就可以分享任何能被Git管理的更新(因此可以分享代码、文件、想法、情书等等)。
本节课我们将学习如何从远程仓库获取数据—命令如其名,它就是git fetch.
你会看到当我们从远程仓库获取数据时,远程分支也会更新以反映最新的远程仓库。在上一节课程中我们已经提及过这一点了。
基础命令:
在解释git fetch前,我们先看看实例。这里我们有一个远程仓库,它有两个我们本地仓库中没有的提交。

基础命令

在解释git fetch前,我们先看看实例。这里我们有一个远程仓库,它有两个我们本地仓库中没有的提交。

命令演示

在这里插入图片描述
git fetch
在这里插入图片描述

git fetch做了些什么

git fetch完成了仅有但是很重要的两步:
① 从远程仓库下载本地仓库中缺失的提交记录
② 更新远程分支指针(如o/main)
git fetch实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。
如果你还记得上一节课程中我们说过的,远程分支反映了远程仓库在你最后一次与它通信时的状态,git fetch就是你与远程仓库通信的方式了!希望我说的够明白了,你已经了解git fetch与远程分支之间的关系了吧。
git fetch通常通过互联网(使用http://或git://协议)与远程仓库通信。

git fetch不会做的事

git fetch并不会改变你本地仓库的状态。它不会更新你的main分支,也不会修改你磁盘上的文件。
理解这一点很重要,因为许多开发人员误以为执行了git fetch以后,他们本地仓库就与远程仓库同步了。它可能已经将进行这一操作所需的所有数据都下载了下来,但是并没有修改你本地的文件。我们在后面的课程中将会讲解能完成该操作的命令。
所以,你可以将git fetch理解为单纯的下载操作。

通关条件

初始条件:
在这里插入图片描述

通关目标:
在这里插入图片描述

通关命令

git fetch

备注

git fetch把远端的所有记录同步到o/main和o/bugFix分支上了,但是没有更新main分支和bugFix分支

第二十二关:Git pull

既然我们已经知道了如何用git fetch获取远程的数据,现在我们学习如何将这些变化更新到我们的工作当中。
其实有很多方法的—当远程分支中有新的提交时,你可以像合并本地分支那样来合并远程分支。也就是说你可以执行以下命令:
① git cherry-pick o/main
② git rebase o/main
③ git merge o/main
④ 等等
实际上,由于先抓取更新再合并到本地分支这个流程很常用,因此Git提供了一个专门的命令来完成这两个操作。它就是我们要讲的git pull

基础命令:

我们先来看看fetch、merge依次执行的效果:

命令演示

在这里插入图片描述
git fetch;git merge o/main
在这里插入图片描述
我们用fetch下载了c3,然后通过git merge o/main合并了这一提交记录。现在我们的main分支包含了远程仓库中的更新(在本例中远程仓库名为origin)

如果使用git pull呢?

在这里插入图片描述
git pull
在这里插入图片描述
同样的结果!这清楚地说明了git pull就是git fetch和git merge的缩写!

第二十三关:模拟团队合作

这里有一件棘手的事—为了接下来的课程,我们需要先教你如何制造远程仓库的变更。
这意味着,我们需要“假装”你的同事、朋友、合作伙伴更新了远程仓库,有可能是某个特定的分支,或是几个提交记录。
为了做到这点,我们引入一个自造命令git fakeTeamwork!它的名称已经说明了一切,先看演示…

基础命令:

fakeTeamwork默认操作就是在远程仓库的main分支上做一次提交。
在这里插入图片描述
git fakeTeamwork
在这里插入图片描述
完成了—远程仓库增加了一个新提交,我们还没有下载它,因为我们还没有执行git fetch.

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

在这里插入图片描述
git fakeTeamwork foo 3
在这里插入图片描述
通过一个命令,我们就模拟队友推送了3个提交记录到远程仓库的foo分支。

通关条件

初始条件:
在这里插入图片描述

通关目标:
在这里插入图片描述

通关命令

git clone
git fakeTeamwork main 2
git fetch
git commit
git merge o/main

第二十四关:git push

OK,我们已经学过了如何从远程仓库获取更新并合并到本地的分支当中。这非常棒。。。但是我如何与大家分享我的成果呢?
嗯,上传自己分享内容与下载他人的分享刚好相反,那与git pull相反的命令是什么呢?git push!
git push负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。一旦git push完成,你的朋友们就可以从这个远程仓库下载你分享的成果了!
你可以将git push想象成你发布成果的命令。它有许多应用技巧,稍后我们会了解到,但是咱们还是先从基础的开始吧……
注意—git push不带任何参数时的行为与Git的一个名为push.default的配置有关。它的默认值取决于你正使用的Git的版本,但是在教程中我们使用的是upstream。这没什么太大的影响,但是在你的项目中进行推送之前,最好检查一下这个配置。

基础命令:

这里我们准备了一些远程仓库中没有的提交记录,咱们开始先上传吧!

命令演示

在这里插入图片描述
git push
在这里插入图片描述
过去了,远程仓库接受了c2,远程仓库中的main分支也被更新到指向c2了,我们的远程分支(o/main)也同样被更新了。所有的分支都同步了!

通关条件

初始条件:
在这里插入图片描述

通关目标:
在这里插入图片描述

通关命令

git commit
git commit
git push

第二十五关:偏离的工作

现在我们已经知道了如何从其他地方pull提交记录,以及如何push我们自己的变更。看起来似乎没什么难度,但是为何还会让人们如此困惑呢?
困难来自于远程库提交历史的偏离。在讨论这个问题的细节前,我们先来看一个例子……

假设你周一克隆了一个仓库,然后开始研发某个新功能。到周五时,你新功能开发测试完毕,可以发布了。但是—天啊!你的同事这周写了一堆代码,还改了许多你的功能中使用的API,这些变动会导致你新开发的功能变得不可用。但是他们已经将那些提交推送到远程仓库了,因此你的工作就变成了基于项目旧版的代码,与远程仓库最新的代码不匹配了。
这种情况下,git push就不知道该如何操作了。如果你执行git push ,Git应该让远程仓库回到星期一那天的状态吗?还是直接在新代码的基础上添加你的代码,亦或由于你的提交已经过时而直接忽略你的提交?
因为这情况(历史偏离)有许多的不确定性,Git是不会允许你push变更的。实际上它会强制你先合并远程最新的代码,然后才能分享你的工作。

基础命令:

命令演示

来看一下实际的案例:
在这里插入图片描述
git push
在这里插入图片描述
看见了吧?什么都没变,因为命令失败了!git push失败是因为你最新提交的c3基于远程分支中的c1。而远程仓库中该分支已经更新到c2了,所以Git拒绝了你的推送请求。

那该如何解决这个问题呢?很简单,你需要做的就是使你的工作基于最新的远程分支。
有许多方法做到这一点,不过最直接的方法就是通过rebase调整你的工作。咱们继续,看看怎么rebase!
初始条件:
在这里插入图片描述
如果我们在Push之前做rebase呢?
git fetch;git rebase o/main;git push
在这里插入图片描述
我们用git fetch更新了本地仓库中的远程分支,然后用rebase将我们的工作移动到最新的提交记录下,最后再用git push推送到远程仓库。

还有其它的方法可以在远程仓库变更这种工作吗?当然有,我们还可以使用merge,尽管git merge不会移动你的工作(它会创建新的合并提交),但是它会告诉git你已经合并了远程仓库的所有变更。这是因为远程分支现在是你本地分支的祖先,也就是说你的提交已经包含了远程分支的所有变化。
看下演示。。。
初始条件:
在这里插入图片描述
git fetch;git merge o/main;git push
在这里插入图片描述
我们用git fetch更新了本地仓库中的远程分支,然后合并了新变更到我们的本地分支(为了包含远程仓库的变更),最后我们用git push把工作推送到远程仓库。

很好!但是要敲那么多命令,有没有更简单一点的?
当然—前面已经介绍过git pull就是fetch和merge的简写,类似的git pull –rebase就是fetch和rebase的简写!
让我们看看简写命令是如何工作的。
初始条件:
在这里插入图片描述
git pull –rebase;git push
在这里插入图片描述
换用常规的pull:
初始条件
在这里插入图片描述
git pull;git push
在这里插入图片描述

通关条件

初始条件:
在这里插入图片描述

通关目标:
在这里插入图片描述

通关命令

git clone
git fakeTeamwork
git commit
git fetch
git rebase o/main
git push

第二十六关:锁定的main–远程服务器拒绝!(Remote Rejected)

如果你是在一个大的合作团队中工作,很可能是main被锁定了,需要一些pull request流程来合并修改。如果你直接提交(commit)到本地main,然后试图推送(push)修改,你将会收到这样类似的信息:
~[远程服务器拒绝]main->main(TF402455:不允许推送(push)这个分支;你必须使用pull request来更新这个分支。)

为什么会被拒绝?

远程服务器拒绝直接推送(push)提交到main,因为策略配置要求pull requests来提交更新。
你应该按照流程,新建一个分支,推送(push)这个分支并申请pull request,但是你忘记并直接提交给了main.现在你卡住并且无法推送你的更新。

解决办法

新建一个分支feature,推送到远程服务器。然后reset你的main分支和远程服务器保持一致,否则下次你pull并且他人的提交和你冲突的时候就会有问题。

通关条件:

初始条件:
在这里插入图片描述

通关目标:
在这里插入图片描述

通关命令:

我的命令
git branch -f main c1 //把当前main分支切换回提交记录c1和remote保持一致
git checkout -b feature //创建一个新分支feature
git branch -f geature c2 //把新的分支切换到最新的提交记录c2上
git push //推送修改

标准答案:
git reset –hard o/main //和我的命令第一句效果相同,不过这个命令我不记得我有学过
git checkout -b feature c2 //创建分支并把这个分支放到c2上(一步顶两步)
git push origin feature //这应该是专业的推送分支方法

备注

这个练习的意思应该是:在一个大型的合作团队工作中,main分支是不允许推送任何提交的,所以才会导致刚开始的错误:
~[远程服务器拒绝]main->main(TF402455:不允许推送(push)这个分支;你必须使用pull request来更新这个分支。)
所以解决的办法就是把本地main分支上的提交回退掉,创造一个新的feature分支,并把你的提交放在新分支上,后续的合入main分支流程,则应该是由团队管理员审核通过后完成。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值