这篇笔记旨在理解几个核心的git基本概念,如果对git了解较少,可以先看git基本教程。
这里推荐一个:廖雪峰-Git教程 (opens new window)
本文内容稍显陈旧,可以参考这篇:
深入理解Git - 一切皆commit - J.晒太阳的猫 - 博客园 (opens new window)
# commit(提交) 与 branch(分支)
# 版本号
commit是git管理的基本单位,在有多个分支的情况下,这些commit就构成了一颗commit树。
每个提交会有一个版本号(commit id
),类似3628164fb26d48395383f8f31179f24e0882e1e0
,即这个提交的命名,是用十六进制表示的一个SHA1计算出来的一个非常大的数字。
实际使用中,不必要写全这串字符,使用前面一部分,如前8位,git能唯一识别出来某个提交就可以了。
文中的提交
二字,就是指一次commit
,也就是一个版本,可以用版本
二字代替,习惯使用提交这个说法了。
# 分支
从形式上看,分支(branch)就是从树的叶子节点到跟节点的一条线(可能有分叉),那git中是如何表示这条线的呢?或者换个问法,git中的分支名,究竟是表示什么呢。
其实分支名,如dev
表示的只是dev这个分支上最新的那次提交,或者说,dev
这三个字母,这个字符串,就是dev分支上最新的那个提交的别名,或者理解为那个最新提交的一个引用。
git中“并没有”分支,只有
commit
; 分支只是对某个特定commit
的引用
如下图所示,dev
只是 commit-6 的一个引用,如果在 commit-6 的基础上,做了一次新的提交,则dev指向这次新的提交。每个提交(除了第一次提交)都会有一个或者两个父节点提交,如图中的 commit-4 ,就是一次合并提交,拥有两个父节点。
# HEAD
git中用 HEAD
表示当前分支的最新的那个提交,即如果在dev分支,则 HEAD
表示(指向)的就是dev,也就是指向commit-6。HEAD^
表示 HEAD
的前一个提交,即 commit-5; HEAD^^
表示 HEAD
的前两个提交,前100个可以写成 HEAD~100
,相应的,前一个也可以写成 HEAD~1
。
# 本地仓库 和 远程仓库
常见的GIT 工作区
、 暂存区
、 本地仓库
和 远程仓库
的示意图。
看这幅图会理解git只有两个仓库,本地仓库
和 远程仓库
;但如果理解为三个仓库,才能更好地理解有些git命令或操作是什么回事。哪三个仓库?
本地工作仓库
、 本地远程仓库
、 远程仓库
名字是随便取的,重点在于便于理解。看下面这幅图。
这其中多了一个Local Remote repository
, 即上面提到的本地远程仓库
,这个仓库就是远程仓库在本地的一个拷贝,目的是为了和远程仓库保持一致。
常听到关于pull
命令的解释就是,pull 是 fetch 和 merge 的结合,完成的实际上是先fetch,再merge。 如果没有本地远程仓库
这个概念,其实不是特别好理解这句话。
git fetch
做的其实是把远程仓库
的更新全部拉取到本地远程仓库
(注意,是全部,不只是当前分支)。而这里的merge,完整的写出来应该是这样(假设在dev分支):
/* pull */
git pull origin dev
/* fetch + merge */
git fetch
git merge origin/dev
这里的origin/dev
指的就是本地远程仓库
中的dev分支,它刚刚通过fetch命令,从真正的远端仓库拉取到了最新的数据,然而,你自己的dev分支并没有更新,需要将本地远程仓库
中的dev分支(名字是origin/dev
)merge到本地的dev分支。 pull就是完成的上面两步。 所以pull之后,本地的dev就直接更新了,所以才感受不到origin/dev的存在。
理解了 本地远程仓库
,可以方便地完成一些操作。如,现在正在 dev 分支,需要合并远端最新的 master 分支的代码,如何做?
之前的作法可能是这样:
git checkout master // 切换到 master 分支
git pull origin master // 拉取远端代码到 master 分支
git checkout dev // 切换回 dev 分支
git merge master // 合并 master 分支
而实际上,不需要切换分支,这样就可以:
git fetch // 更新本地远端仓库
git merge origin/master // 从 本地远端仓库 合并 master 分支
需要注意的是,这里必须先使用 git fetch
命令,直接使用 origin/master
并不会让本地远端仓库自动去远端拉取最新的代码。
END