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

创建并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,涉及到远程以及分支,当然也得分开写了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • @synthesize和@dynamic分别有什么作用?@property有两个对应的词,一个是 @synthes...
    笔笔请求阅读 505评论 0 1
  • 【Aipm引导页】 https://58976235.wodemo.net/down/20170514/44034...
    Mr_洛寒阅读 2,529评论 3 5
  • 猜想runloop内部是如何实现的?一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。如果我们需要一...
    笔笔请求阅读 410评论 0 0
  • 讲班课是非常锻炼人的行为 没讲过班课的老师 不是完整的老师 各种阴差阳错 去年错过了大好的锻炼机会 这里不提了总之...
    哲轩88阅读 422评论 0 1
  • 不知不觉中,在简书已经日更一年了。 对,一年,从2016年8月30日到今天--2017年8月29日,一共365天,...
    德万托阿阅读 526评论 6 10