专栏首页前端与Java学习Git学习01-Learn Git Branching(在线学习工具)
原创

Git学习01-Learn Git Branching(在线学习工具)

Learn Git Branching(最好用的Git在线学习工具)

网址https://learngitbranching.js.org/?locale=zh_CN

介绍:这个网站可以让我们通过游戏过关的方式来学习Git,通过动画让我们明白整个执行过程,边学边玩可以说非常有趣了。下面我将每个关卡的一些命令做一些总结帮助记忆和学习Git(要理解清楚是需要通过自己跟着提示进行命令操作练习才行)。

主要命令关卡
远程命令关卡

1.基础篇(Git 主要命令)

1.1 Git Commit(提交)

创建一个新的提交记录

1.2 Git Branch(分支)

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

git branch newImage:创建一个名为newImage的分支,newImage的指向是当前的提交记录。

git checkout newImage:切换到我们创建的newImage分支上

git checkout -b 分支名:创建一个新分支同时切换到这个新分支上

1.3 分支与合并

如何将两个分支合并到一起?(下面两种方法的区别具体可以通过网址上的动画演示过程去体会)

第一种方法:git merge

比如我们创建了一个新的分支并且提交了一次git checkout -b bugFix;git commit这时候我们再切换到主分支再次进行一次提交git checkout master;git commit然后我们如何将masterbugFix两个分支合并呢?可以使用git merge bugFix

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

Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰(比如我们将一个新创建的分支bugFix合并到master主分支上只要用git rebase master即可)。

2.高级篇(Git 的超棒特性)

2.1分离HEAD

什么是HEAD?(以下三个解释也是可以通过该网址的动画演示过程去体会其意思

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

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

HEAD -> master -> C1 (HEAD 指向 master, master 指向 C1)

执行了git checkout C1后就会变成HEAD -> C1

2.2 相对引用(^与~)

该网址中提到通过指定提交记录哈希值的方式在 Git 中移动不太方便。在实际应用时,并没有像本程序中这么漂亮的可视化提交树供你参考,所以你就不得不用git log来查查看提交记录的哈希值。并且哈希值在真实的 Git 世界中也会更长,例如提交记录的哈希值可能是fed2da64c0efc5293610bdd892f82a58e8cbc5d8,令人欣慰的是,Git 对哈希的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。因此我可以仅输入fed2而不是上面的一长串字符。

正如我前面所说,通过哈希值指定提交记录很不方便,所以 Git 引入了相对引用。(使用相对引用的话,你就可以从一个易于记忆的地方(比如bugFix分支或HEAD)开始计算)

这里介绍了两个简单的用法:

  • 使用^向上移动1个提交记录
  • 使用~数字向上移动多个提交记录,如~3

示例:比如现在切换到master的父节点我们就可以使用git checkout master^,如果想切换到第二个父节点就可以使用git checkout master^^,当然也可以将HEAD作为参照物,比如git checkout HEAD^

使用~操作符与上不同是当我们需要向上移动很多步的时候就不用敲那么多的^,可以用~数字来代替,比如移动到当前master的第三个父节点就可以使用git checkout HEAD~3

在这里教程中还提到了强制修改分支位置使用git branch -f 分支名 HEAD~3,这个命令会将该分支强制指向 HEAD 的第 3 级父提交。

2.3 撤销变更

在 Git 里撤销变更的方法很多。和提交一样,撤销变更由底层部分(暂存区的独立文件或者片段)和上层部分(变更到底是通过哪种方式被撤销的)组成。我们这个应用主要关注的是后者。

这里教程中又提到了两种方法来撤销变更:

  • 第一种使用git reset
  • 第二种使用git revert

这里主要也需要通过网站中的动画过程演示来帮助我们理解和记忆

示例:我们先来看第一种Reset,当我们使用git reset HEAD~1,就会把分支记录回退1个提交记录来实现撤销改动,原来指向的提交记录就跟从来没有提交过一样(在reset后,C2所做的变更还在,但是处于未加入暂存区状态)。然后说到Revert,虽然我们在本地分支使用 git reset 很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的。为了撤销更改并分享给别人,我们需要使用git revert

3.移动提交记录(自由修改提交树)

3.1 git cherry-pick(git cherry-pick <提交号>

如果你想将一些提交复制到当前所在的位置(HEAD)下面的话, cherry-pick 是最直接的方式了。

当我们想将一个分支上的工作复制到当前所在分支上,或许你会想到之前的rebase,但是这里我们可以看看cherry-pick的效果,通过git cherry-pick C2 C4 这里就是将C2 C4两个提交记录抓到当前分支下。

3.2 交互式的 rebase

当我们知道所需要提交的记录(并且知道这些提交记录的哈希值)时,用cherry-pick再好不过了,但是如果我们不清楚这些,我们此时也可以用交互式的rebase--如果你想从一系列的提交记录中找到想要的记录,这就是最好的方法。交互式 rebase 指的是使用带参数--interactive的 rebase 命令, 简写为-i,如果你在命令后增加了这个选项, Git 会打开一个 UI 界面并列出将要被复制到目标分支的备选提交记录,它还会显示每个提交记录的哈希值和提交说明,提交说明有助于你理解这个提交进行了哪些更改。

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

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

4.杂项(Git 技术、技巧与贴士大集合)

4.1本地栈式提交

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

那我们如何做到只提交一个记录呢?

很简单,我们只需要将分支切换到master主分支,再通过git rebase -i或者git cherry-pick 选择我们要提交的记录就能够很容易的来达到目的。

4.2提交的技巧

你之前在 newImage 分支上进行了一次提交,然后又基于它创建了 caption 分支,然后又提交了一次。此时你想对的某个以前的提交记录进行一些小小的调整。比如设计师想修改一下 newImage 中图片的分辨率,尽管那个提交记录并不是最新的了。

我们可以通过下面的方法来克服困难:

  • 先用 git rebase -i 将提交重新排序,然后把我们想要修改的提交记录挪到最前
  • 然后用 git commit --amend 来进行一些小修改
  • 接着再用 git rebase -i 来将他们调回原来的顺序
  • 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!

当然完成这个任务的方法不止上面提到的一种(很容易我们就想到了之前的 cherry-pick 也是可以做到的)

4.3 Git Tags

相信通过前面课程的学习你已经发现了:分支很容易被人为移动,并且当有新的提交时,它也会移动。分支很容易被改变,大部分分支还只是临时的,并且还一直在变。你可能会问了:有没有什么可以永远指向某个提交记录的标识呢,比如软件发布新的大版本,或者是修正一些重要的 Bug 或是增加了某些新特性,有没有比分支更好的可以永远指向这些提交的方法呢?

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

我们只需要用git tag v1 提交记录git tag v1 C1表示这是我们1.0版本,我们将这个标签命名为v1,并且明确地让它指向提交记录C1,如果你不指定提交记录,Git 会用HEAD所指向的位置。

4.4 Git Describe

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

Git Describe 能帮你在提交历史中移动了多次以后找到方向;当你用 git bisect(一个查找产生 Bug 的提交记录的指令)找到某个提交记录时,或者是当你坐在你那刚刚度假回来的同事的电脑前时, 可能会用到这个命令。

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

这里主要通过该网址的动画演示过程去理解

5.远程仓库

5.1 Git Clone

直到现在, 教程都聚焦于本地仓库的操作(branch、merge、rebase 等等)。但我们现在需要学习远程仓库的操作 —— 我们需要一个配置这种环境的命令, 它就是git clone。 从技术上来讲,git clone命令在真实的环境下的作用是在本地创建一个远程仓库的拷贝(比如从 github.com)。

5.2 远程分支 o/master

当我们git clone后发现一个一个名为o/master的分支, 这种类型的分支就叫远程分支。由于远程分支的特性导致其拥有一些特殊属性。你可能想问这些远程分支的前面的 o/ 是什么意思呢?好吧, 远程分支有一个命名规范 —— 它们的格式是:

  • <remote name>/<branch name>

因此,如果你看到一个名为 o/master 的分支,那么这个分支就叫 master,远程仓库的名称就是 o

大多数的开发人员会将它们主要的远程仓库命名为 origin,并不是 o。这是因为当你用 git clone 某个仓库时,Git 已经帮你把远程仓库的名称设置为 origin 了。不过 origin 对于我们的 UI 来说太长了,因此不得不使用简写 o :) 但是要记住, 当你使用真正的 Git 时, 你的远程仓库默认为 origin!

5.3 Git Fetch

Git 远程仓库相当的操作实际可以归纳为两点:向远程仓库传输数据以及从远程仓库获取数据。

如何从远程仓库获取数据 —— 命令如其名,它就是git fetch

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

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

git fetch 实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。git fetch并不会改变你本地仓库的状态。它不会更新你的master分支,也不会修改你磁盘上的文件。所以, 你可以将git fetch的理解为单纯的下载操作。

5.4 Git Pull

Git帮我们将 git fetch git merge 合到了一起,让我们直接用一步git pull 就能实现从远程仓库拉取并且合并分支。

5.5 Git Push

上传自己分享内容与下载他人的分享刚好相反,那与 git pull 相反的命令是什么呢?git push

git push 负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。一旦 git push 完成, 你的朋友们就可以从这个远程仓库下载你分享的成果了!

5.6 解决远程库提交历史的偏离

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

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

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

如何解决问题呢?

我们可以通过先git fetch 下载代码,再通过git rebase o/master或者git merge o/master进行合并,合并之后再进行推送git push,可能有人觉得写得命令太长,之前介绍过git pullfetchmerge的简写,类似的git pull --rebase 就是fetchrebase的简写了。

好了总结到此处,主要还是要自己跟着页面中的教程提示以及动画过程演示去理解操作才能运用的熟练哦!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

相关文章

  • Git学习02-Git本地仓库和Github远程仓库操作

    安装最新版git可以去Git的官网,从Git官网直接下载安装程序,然后按默认选项安装即可。

    帅的一麻皮
  • Vue使用组件递归实现评论盖楼功能笔记

    当评论数据中有parent的时候意味着有回复用户信息,因此需要引入Floor组件进行递归渲染这些数据,因为我们无法预知它一共有多少层

    帅的一麻皮
  • 跨域无法设置cookie的问题

    我想实现的功能就是:在登录页面输值进行登录之后可以把用户的信息存入到cookie中,判断用户是否在登录状态。

    帅的一麻皮
  • 如何使用github给大佬递茶

    最近也是闲到没事干(误),开始给开源项目打小黑工贡献代码,当个dalao手底下的端茶党。但是看来端茶党也不是那么容易做的或许只是傻翠他智商太低跟不上,在打小黑工...

    idealclover
  • Git Pro深入浅出(一)

    什么是“版本控制”?版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。 版本控制系统(VCS)应用而生。有了它你就可以将某个文...

    奋飛
  • 7.1 Git 工具 - 选择修订版本

    现在,你已经学习了管理或者维护 Git 仓库、实现代码控制所需的大多数日常命令和工作流程。 你已经尝试了跟踪和提交文件的基本操作,并且发挥了暂存区和轻量级的分...

    shaonbean
  • 小姐姐用动画图解Git命令,一看就懂!

    无论是开发、运维,还是测试,大家都知道Git在日常工作中的地位。所以,也是大家的必学、必备技能之一。之前公众号也发过很多git相关的文章:

    民工哥
  • Git基础知识(六)

    因为是主线上的bug,所以先切回到主线上去,不过本地的主线可能有点旧了,所以把本地的master分支删掉,然后和远端同步一下之后再从远端把master分支检出

    zx钟
  • 如何高效的在服务器和本地进行上传和下载文件

    昨天, 师弟告诉我可以在xshell中使用sz进行下载, 想要上传的话用rz就行了. 然后我竟然没有听过. 学习最好的方法就是写一篇博客, 比如这篇.

    邓飞
  • 如何删除错误提交的 git 大文件

    早上小伙伴告诉我,他无法拉下代码,我没有在意。在我开始写代码的时候,发现我的 C 盘炸了。因为我的磁盘是苏菲只有 256G 放了代码就没空间了,于是我查找到了原...

    林德熙

扫码关注云+社区

领取腾讯云代金券