« 主页

深入理解 gitrevisions

版权声明:眯眼探云原创,可随意转载,请保留该版权声明及链接:https://tyun.fun/post/15.understand-git-revisions/

git 是个非常强大的版本管理工具,但比较遗憾的是,在国内很多公司只是被当做加强版的 svn 在用,实在可惜。

根据我的经验,对 gitrevisions 的理解是一个非常关键的点,于是决定仔细的讲一讲 git 中这些与 revision 相关的概念,希望能帮助到大家。

Commit

首先必须是 commit,这是理解 git 的基石。来看看官方文档 commit

As a noun: A single point in the Git history; the entire history of a project is represented as a set of interrelated commits. The word “commit” is often used by Git in the same places other revision control systems use the words “revision” or “version”. Also used as a short hand for commit object.

简单翻译一下:每一个 commit 代表的是 git history 中的一个点。整个 git 仓库的历史就是由一系列相互关联的 commit 构成的。commit 对应于其他的版本管理工具中的“版本”。也用于称呼 commit object。

关键就是前两句,一是 commit 本身(与父节点的差异),二是 commit 在历史仓库中的关系。可以想象一下我们堆积木,只能是一个一个往上堆,也就是说每一块积木必须堆在下面一块积木上,而不能浮在空中。commit 也是一样,除了初始的 commit,每个 commit 必须有它的父节点 parent。

Git History

如图有一段 git 历史,有 ABCD 四个 commits。每个 commit 实际代表的是它所在的项目的状态。为了更好的理解,我们必须要将 commit A 拆成两个部分:

  1. 改动 - A 包含的改动
  2. 关系 - A 以前的项目状态,即 B

也就是说,A 所代表的项目状态,是他本身与之前所有的 commit 的总和。

所以,千万不要孤立的看待一个 commit,它代表了它本身,以及之前的所有项目历史

OK,问题来了,当你 checkout 一个 commit 的时候你在干什么?

  • 你在切换到项目的某个历史状态,这个状态包含了这个 commit,以及他的父节点,以及所有的祖先节点。

Branch

那 branch 又是什么呢?还是要先看官方文档 branch:

A “branch” is an active line of development. The most recent commit on a branch is referred to as the tip of that branch. The tip of the branch is referenced by a branch head, which moves forward as additional development is done on the branch. A single Git repository can track an arbitrary number of branches, but your working tree is associated with just one of them (the “current” or “checked out” branch), and HEAD points to that branch.

只翻译前两句:一个分支就是一条进行中(开发中)的线。一个分支的最新的一个 commit 被称作分支的末端。

Git Branch

当我们在某个分支上进行开发的时候,branch 为我们指明的前进的方向。而每一个新的 commit 必须放在 branch 的末端之上。就像是堆积木,你必须将积木堆在最上面的一个积木上面。

哦,原来是这么回事,每个 branch 指明了一个前进的方向,你告诉 git 我在某个 branch 上面有个新的 commit,git 就知道怎么存放这个 commit 了。其实最关键的部分就是:git 知道该选哪个 commit 作为父节点。

问题又来了:当你切换到一个 branch 的时候,你在干什么?

  • 你切换到了这个 branch 的最新的那个 commit 所代表的项目状态。并告诉 git 在添加新的 commit 的时候往哪里添。

看,最关键的还是 commit。

HEAD,refs/**,tags …… 这些又是啥?

这些,都是 commit 的别名啦~

你想啊,每个 commit 真正的唯一标识是一个 SHA1,那玩意儿谁记的住呀?所以呢,有些有特殊意义的 commit,我们就用一些别名来称呼他们。

那接下来就是搞清楚每个别名到底指的是哪个 commit 就好了。

HEAD 指的就是当前 branch 最新的那个 commit。你可以用 HEAD^ 指定 HEAD 的前一个 commit。

tags 标签主要是我们自己某些有意义的 commit 做的一个标记。比如是在哪个 commit 发的版。

refs/** 这些主要是 git 为一些有特定意义的 commit 指定的别名,通常不会用到,知道是怎么回事就行了。

那到底啥是 git revision?

其实就是 commit 啦,别看那一堆花里胡哨的,落到实处,全都是 commit。

你以为你都学会了?

少年,你想多啦~

没有经过长时间的实践,把 commit 的概念深深的印入你的骨髓,那就算不上学会啦~

下一集预告:Play with Commits

私以为,使用 git 来进行版本管理,其实最重要的玩 commits 啦。

Checkout, Cherry-Pick, Rebase, Merge ……

这些都是常用的玩 commits 的工具,要挨个用熟练也是非常不容易,但当你把这些用熟了以后,你才能真正体会到 git 的强大之处。

使用好这些工具,你就能开心的像堆积木一样来搞定 git commit 啦。

enjoy!