Git Learning 学习笔记

1. 前言

最近接触了 Git 后就被它强大的功能吸引了,正好在 GitHub 上发现了一个很不错的在线学习网站:LearningGitBranching,将其通关后,写下了通关的所有答案和笔记心得。

2. 基础篇

2.1 Git Commit

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

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

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

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


原状态:
在这里插入图片描述
当前有两次提交记录C0C1(这里C0C1是该次提交的hash值,用于唯一地标识该次提交),并且当前处于主要分支master*号标识当前分支),头指针指向C1

本关任务:

  • 在当前分支中提交两次修改

这里只需要连续使用两次git commit即可完成提交修改
输入:

  • git commit提交一次修改,新增结点C2
  • git commit提交第二次修改,新增结点C3
    在这里插入图片描述

2.2 Git Branch

Git 的分支也非常轻量。它们只是简单地指向某个提交纪录 —— 仅此而已。所以许多 Git 爱好者传颂:

早建分支!多用分支!

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

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


原状态:
在这里插入图片描述
当前有两次提交记录C0C1,并且当前处于主要分支master,头指针指向C1,然后任务是:

  • 创建一个新的名为bugFix的分支
  • 将当前分支切换到bugFix分支

这里我们分两步完成:

  • 创建分支git branch bugFix
    在这里插入图片描述
  • 切换分支git checkout bugFix
    在这里插入图片描述

当然,这里还有一个更加简洁的方法:
git checkout -b bugFix
可以新建分支并直接切换到该bugFix分支

2.3 Git Merge

太好了! 我们已经知道如何提交以及如何使用分支了。接下来咱们看看如何将两个分支合并到一起。就是说我们新建一个分支,在其上开发某个新功能,开发完成后再合并回主线。

咱们先来看一下第一种方法 —— git merge。在 Git 中合并两个分支时会产生一个特殊的提交记录,它有两个父结点。翻译成自然语言相当于:“我要把这两个父结点本身及它们所有的祖先都包含进来。”


原状态:
在这里插入图片描述
当前有两次提交记录C0C1,并且当前处于主要分支master,头指针指向C1,然后任务是:

  • 创建新分支 bugFix
  • git checkout bugFix 命令切换到该分支
  • 提交一次
  • git checkout master 切换回 master
  • 再提交一次
  • git mergebugFix 合并到 master

这关也同样十分简单:

  • 创建新分支 git branch bugFix
  • git checkout bugFix 命令切换到该分支
  • git commit提交一次
  • git checkout master 切换回 master
  • git commit再提交一次
  • git merge bugFixbugFix 合并到 master

注意:这里git merge bugFix 是把该分支bugFix合并到当前分支(master)
对于前两步也同样可以使用git checkout -b bugFix一步完成。
在这里插入图片描述

2.4 Git Rebase

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

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


原状态:
在这里插入图片描述
当前有两次提交记录C0C1,并且当前处于主要分支master,头指针指向C1,然后任务是:

  • 新建并切换到 bugFix 分支
  • 提交一次
  • 切换回 master 分支再提交一次
  • 再次切换到 bugFix 分支,rebasemaster

这关不难,但是理解git rebase的用法稍微复杂点:

  • git checkout -b bugFix新建并切换到 bugFix 分支
  • git commit提交一次

在这里插入图片描述

  • git checkout master切换回 master 分支,然后git commit再提交一次

在这里插入图片描述

  • git checkout bugFix再次切换到 bugFix 分支,然后使用git rebase master 使其连接到master分支后。移动以后会使得两个分支的功能看起来像是按顺序开发,但实际上它们是并行开发的。

在这里插入图片描述

注意:提交记录 C2 依然存在(树上那个半透明的结点),而 C3’ 是我们 Rebase 到 master 分支上的 C2 的副本。
同时 master 还未更新,这时候应该使用 git checkout master然后git rebase bugFix:

由于 bugFix 继承自 master,所以 Git 只是简单的把 master 分支的引用向前移动了一下而已,即同一分支的rebase 只是将原分支更新到该分支位置。

在这里插入图片描述
此外,git base bugFix的意思是,将该bugFix分支rebase到当前分支(master),也就是该bugFix分支作为master的基(父结点),类似于git merge bugFix 把该分支bugFix合并到当前分支(master)

3. 高级篇

3.1 分离HEAD

在接触 Git 更高级功能之前,我们有必要先学习在你项目的提交树上前后移动的几种方法。

一旦熟悉了如何在 Git 提交树上移动,你驾驭其它命令的能力也将水涨船高!

我们首先看一下 “HEAD”。 HEAD 是一个对当前检出记录的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。

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

HEAD 通常情况下是指向分支名的(如 master),HEAD 的指向随着master提交向前移动。

分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。
比如:
HEAD -> master -> C1

HEAD 指向 master, master 指向 C1
在这里插入图片描述

使用git checkout C1分离后变成了:

HEAD -> C1
在这里插入图片描述

(实际这些命令并不是真的在查看 HEAD 指向,看下一屏就了解了。如果想看 HEAD 指向,可以通过 cat .git/HEAD 查看, 如果 HEAD 指向的是一个引用,还可以用 git symbolic-ref HEAD 查看它的指向。但是该程序不支持这两个命令)


原状态:
在这里插入图片描述

如图,当前任务是:

  • bugFix 分支中分离出 HEAD 并让其指向一个提交记录。

这关只需要一步就能搞定了,关键是理解如何分离HEAD,以及分离后的情况:

  • 使用git checkout C4即可将HEAD指针指向C4(注意原本是指向master
  • 或者使用另一个方法:git checkout C3 进入 bugFix 分支之前的位置,然后git rebase bugFix将当前master分支 rebasebugFix下(该方法稍许麻烦,但可以更加深入理解rebase

在这里插入图片描述

3.2 相对引用(一)

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

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

比较令人欣慰的是,Git 对哈希的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。因此我可以仅输入fed2 而不是上面的一长串字符。

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

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

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

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

本关任务是:

  • 切换到 bugFix 的父结点。这会进入分离 HEAD 状态。

在这里插入图片描述

解决方案:

  • 使用git checkout bugFix切换到 bugFix分支所在处C4,(同时HEAD也会切换到 C4 处),然后使用git checkout HEAD^回退到C3

在这里插入图片描述

你甚至可以直接使用git checkout C3,但是这不是本关卡想要看到的方法。

3.3 相对引用(二)

~操作符

如果你想在提交树中向上移动很多步的话,敲那么多 ^ 貌似也挺烦人的,Git 当然也考虑到了这一点,于是又引入了操作符 ~

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

另一个重点就是:强制修改分支位置

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

git branch -f master HEAD~3

上面的命令会将 master 分支强制指向 HEAD 的第 3 级父提交。

相对引用为我们提供了一种简洁的引用提交记录的方式, 而 -f 则容许我们将分支强制移动到那个位置。


原状态:
在这里插入图片描述

这里可以看到,masterbugFix两个分支处于不同位置,同时HEAD亦处于master的父结点所在处,并且还有一个回退过的结点C6。本关任务是:

  • 移动 HEAD,masterbugFix 到目标所示的位置。

在这里插入图片描述

解决方案如下:

  • git branch -f master C6使得master移动到C6位置

在这里插入图片描述

  • git branch -f bugFix HEAD~2使得bugFix移动到HEAD的二级父结点C0

在这里插入图片描述

  • git checkout C1使得HEAD结点移动到C1

在这里插入图片描述

3.4 撤销变更

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

主要有两种方法用来撤销变更 —— 一是 git reset,还有就是 git revert。接下来咱们逐个进行讲解。

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

虽然在你的本地分支中使用 git reset 很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的哦!

  • git revert 通过把当前分支在我们要撤销的提交记录后面增加一个新提交,使得新提交记录引入了更改,这些更改刚好是用来撤销原先的提交的,revert 之后就可以把你的更改推送到远程仓库与别人分享啦。

原状态:
在这里插入图片描述
当前分支位local。其中,pushed是远程分支

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值