这篇笔记旨在理解几个核心的 git 基本概念,如果对 git 了解较少,可以先看 git 基本教程。
这里推荐一个:廖雪峰-Git教程
本文内容稍显陈旧,可以参考这篇:
深入理解Git - 一切皆commit - J.晒太阳的猫 - 博客园
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 fetchgit 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
并不会让本地远端仓库自动去远端拉取最新的代码。
原文链接: https://blog.jgrass.cc/posts/git-note/
本作品采用 「署名 4.0 国际」 许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。