Git学习-笔记摘要
说明:本文是对Git原理的学习过程中,一些重要的内容摘抄。
里面的图文大部分来自git-sam.com网站。此网站对git的介绍很详细,收益匪浅
https://git-scm.com/book/zh/v1/%E8%B5%B7%E6%AD%A5
Git基本概念
Git其实是一个分布式版本控制系统(Distributed Version Control System,简称 DVCS)。
客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
文章图片
image Git存储方式 -直接记录快照,而非差异比较
Git 在保存和对待各种信息的时候与其它版本控制系统有很大差异。
Git 更像是把数据看作是对小型文件系统的一组快照。 每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个 快照流。
文章图片
image
文章图片
ATTACH_ded8928862774d37.png
文章图片
ATTACH_3de8bb671a674aa3.png Git分支
Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照。
在进行提交操作时,Git 会保存一个提交对象(commit object)。知道了 Git 保存数据的方式,我们可以很自然的想到——该提交对象会包含一个指向暂存内容快照的指针。 但不仅仅是这样,该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象,为了更加形象地说明,我们假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件。
首次提交之后,对应的git仓库的结构如下:
$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'
文章图片
image 首次提交对象及其树结构 做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。
文章图片
image 提交对象及其父对象 Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master。 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。 它会在每次的提交操作中自动向前移动。
文章图片
image 分支创建 Git 是怎么创建新分支的呢? 很简单,它只是为你创建了一个可以移动的新的指针。 比如,创建一个 testing 分支, 你需要使用 git branch 命令:
git branch testing
这会在当前所在的提交对象上创建一个指针。
文章图片
image
分支切换 要切换到一个已存在的分支,你需要使用 git checkout 命令。 我们现在切换到新创建的 testing 分支去:
git checkout testing
这样 HEAD 就指向 testing 分支了。
文章图片
image
HEAD 分支随着提交操作自动向前移动 如图所示,你的 testing 分支向前移动了,但是 master 分支却没有,它仍然指向运行 git checkout 时所指的对象。 这就有意思了,现在我们切换回 master 分支看看:
git checkout master
文章图片
image 【Git学习-笔记摘要】
创建并check分支 想要新建一个分支并同时切换到那个分支上,你可以运行一个带有 -b 参数的 git checkout 命令:
git checkout -b iss53
Switched to a new branch "iss53"
它是下面两条命令的简写:
git branch iss53
git checkout iss53
文章图片
image 合并分支 有时候我们会遇到如下的场景,在你拉一个分支修改iss53分支时,中间又需要临时拉一个分支去hotfix修改一个紧急问题
文章图片
image
当我们把hotfix修改完,测试没有问题之后,需要把hotfix修改的内容合并到master分支上,进行发布。
git checkout -b hotfix
git checkout master
git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
在合并的时候,你应该注意到了"快进(fast-forward)"这个词。 由于当前 master 分支所指向的提交是你当前提交(有关 hotfix 的提交)的直接上游,所以 Git 只是简单的将指针向前移动。 换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。
合并完成之后,master分支直接往前推进到hotfix分支之后的最新指针状态如下:
文章图片
image 合并master最新的代码到当前分支,并继续修改
$ git checkout iss53
Switched to branch 'iss53'
$ git merge master
把最新的分支合并到master 一般在研发过程中,时常也需要把master上别人提交的稳定的最新的代码合并到当前分支。
$ git checkout iss53
Switched to branch 'iss53'
$ git merge master
等当前分支开发完成之后,需要把当前分支合并到master以待发布上线。
假如当前的状态是:
文章图片
image
git checkout master
git merge iss53
Auto-merging README
Merge made by the 'recursive' strategy.
README | 1 +
1 file changed, 1 insertion(+)
这次合并操作的底层实现,并不同于之前 hotfix 的并入方式。因为这次你的开发历史是从更早的地方开始分叉的。由于当前 master 分支所指向的提交对象(C4)并不是 iss53 分支的直接祖先,Git 不得不进行一些额外处理。就此例而言,Git 会用两个分支的末端(C4 和 C5)以及它们的共同祖先(C2)进行一次简单的三方合并计算。图 3-16 用红框标出了 Git 用于合并的三个提交对象:
文章图片
image
** Git 为分支合并自动识别出最佳的同源合并点。 **
这次,Git 没有简单地把分支指针右移,而是对三方合并后的结果重新做一个新的快照,并自动创建一个指向它的提交对象(C6)(见图 3-17)。这个提交对象比较特殊,它有两个祖先(C4 和 C5)。
值得一提的是 Git 可以自己裁决哪个共同祖先才是最佳合并基础;这和 CVS 或 Subversion(1.5 以后的版本)不同,它们需要开发者手工指定合并基础。所以此特性让 Git 的合并操作比其他系统都要简单不少。
文章图片
image 远程分支与本地分支的关系 远程分支 origin master:表示代码服务器上的真正远程仓库的分支。
origin/master:当我们用clone或者fetch命令把服务器上远程分支拉取下来后,在本地git 仓库就有了一个真正远程服务器仓库上分支的一个拷贝,对远程仓库中的分支的索引。我们也叫远程分支。 注意 本地远程仓库(origin/master)是无法在本地进行编辑的,如果要修改只能修改本地master的分支
master:当我们用clone或者fetch命令把服务器上远程分支拉取代码时,除开在远程分支在本地创建一个origin/master的分支索引之后,还会创建一个本地分支,master。
当用Git clone时,Git 克隆会建立你自己的本地分支 master 和远程分支 origin/master,并且将它们都指向 origin 上的 master 分支。
文章图片
image
如果clone之后,随着我们在本地研发的推进(commit),会把本地分支的master指针往前推进,而同时随着远程仓库中的master分支有其它研发伙伴push之后在往前推进。
如下图:
文章图片
image 通过git fetch获取远程代码的变更 我们在研发过程中可以通过fetch命令把远程仓库中的最新代码变更下载到本地的远程分支,在origin/master与orgin master一致。
文章图片
image 推送代码到服务器 可通过git push,把本地分支的代码,推送到远程仓库中,这样其它的同伴就可收通过git fetch获取到你push的最新的代码了。
git push [远程名] [本地分支]:[远程分支]
######### 跟踪远程分支
从远程分支 checkout 出来的本地分支,称为 跟踪分支 (tracking branch)。跟踪分支是一种和某个远程分支有直接联系的本地分支。在跟踪分支里输入 git push,Git 会自行推断应该向哪个服务器的哪个分支推送数据。同样,在这些分支里运行 git pull 会获取所有远程索引,并把它们的数据都合并到本地分支中来。
一个共享共同远程分支的协作研发示例 https://git-scm.com/book/zh/v1/%E5%88%86%E5%B8%83%E5%BC%8F-Git-%E4%B8%BA%E9%A1%B9%E7%9B%AE%E4%BD%9C%E8%B4%A1%E7%8C%AE
分支的https://git-scm.com/book/zh/v1/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E7%9A%84%E5%8F%98%E5%9F%BA基与rebase 常用命令 分支管理相关 git branch
git branch
不加任何参数,则列出当前所有分支;当前分支前面用"*"标识;git branch -v
查看各分支最后一个提交对象的信息;git branch --merged
查看已经被合并的分支;git branch --no-merged
查看未被合并的分支;git fetch
把远程仓库中的变更同步获取到本地仓库中。git push [远程名] [本地分支]:[远程分支]
把本地的分支push到远程仓库中。相关链接文章:
5.2 分布式 Git - 向一个项目贡献
2.3 Git 基础 - 查看提交历史
2.4 Git 基础 - 撤消操作
2.5 Git 基础 - 远程仓库的使用
3.2 Git 分支 - 分支的新建与合并
3.5 Git 分支 - 远程分支
3.6 Git 分支 - 变基
7.7 Git 工具 - 重置揭密
7.8 Git 工具 - 高级合并
master、origin master 与 origin/master 有什么区别?
master 这个很好理解,它代表本地的某个分支名。举几个例子可能会更加清晰地说明问题:
origin master 代表着两个概念,前面的 origin 代表远程名,后面的 master 代表远程分支名。
origin/master 只代表一个概念,即远程分支名,是从远程拉取代码后在本地建立的一份拷贝(因此也有人把它叫作本地分支)。
执行 git fetch origin master 时,它的意思是从名为 origin 的远程上拉取名为 master 的分支到本地分支 origin/master 中。既然是拉取代码,当然需要同时指定远程名与分支名,所以分开写。
执行 git merge origin/master 时,它的意思是合并名为 origin/master 的分支到当前所在分支。既然是分支的合并,当然就与远程名没有直接的关系,所以没有出现远程名。需要指定的是被合并的分支。
执行 git push origin master 时,它的意思是推送本地的 master 分支到远程 origin,涉及到远程以及分支,当然也得分开写了
推荐阅读
- EffectiveObjective-C2.0|EffectiveObjective-C2.0 笔记 - 第二部分
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- Android中的AES加密-下
- 一起来学习C语言的字符串转换函数
- gitlab|gitlab 通过备份还原 admin/runner 500 Internal Server Error
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- 《深度倾听》第5天──「RIA学习力」便签输出第16期