有人把 Git 的分支模型称为它的`‘必杀技特性’',也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出。 为何 Git 的分支模型如此出众呢? Git 处理分支的方式可谓是难以置信的轻量,创建新分支这一操作几乎能在瞬间完成,并且在不同分支之间的切换操作也是一样便捷。 与许多其它版本控制系统不同,Git 鼓励在工作流程中频繁地使用分支与合并,哪怕一天之内进行许多次。 理解和精通这一特性,你便会意识到 Git 是如此的强大而又独特,并且从此真正改变你的开发方式。

分支简介

在进行提交操作时,Git 会保存一个提交对象(commit object)。知道了 Git 保存数据的方式,我们可以很自然的想到——该提交对象会包含一个指向暂存内容快照的指针。 但不仅仅是这样,该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象,

为了更加形象地说明,我们假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件。 暂存操作会为每一个文件计算校验和(使用我们在 起步 中提到的 SHA-1 哈希算法),然后会把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 对象来保存它们),最终将校验和加入到暂存区域等待提交:

git add README test.rb LICENSE
git commit -m 'The inittial commit of my project'

当使用 git commit 进行提交操作时,Git 会先计算每一个子目录(本例中只有项目根目录)的校验和,然后在 Git 仓库中这些校验和保存为树对象。 随后,Git 便会创建一个提交对象,它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。如此一来,Git 就可以在需要的时候重现此次保存的快照。

现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)。

你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支。

一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:

分支创建

Git 是怎么创建新分支的呢? 很简单,它只是为你创建了一个可以移动的新的指针。 比如,创建一个 testing 分支, 你需要使用 git branch 命令:

git branch testing

分支切换

要切换到一个已存在的分支, 你需要使用 git checkout  命令, 我们现在切换到新创建的 testing  分支去:

git checkout  testing

那么,这样的实现方式会给我们带来什么好处呢? 现在不妨再提交一次:

vim test.rb
git commit -a -m 'made a change'

首先, 我们创建dev  分支, 然后切换到 dev 分支:

git checkout  -b dev
Switched to a new branch 'dev'

git checkout 命令加上 -b  参数表示创建切换, 相当于以下两条命令:

git branch dev
git checkout dev
witched to branch 'dev'

然后, 用  git  branch  命令查看当前分支:

git  branch
* dev
master

git branch  命令会列出所有分支, 当前分支前面会标一个 * 号. 

然后, 我们就可以在dev 分支上正常提交, 比如对 readme.txt 做个修改, 加上一行:

Creating a new branch is quick.

分支删除

你可以使用带 -d选项的 git branch 命令来删除分支:

git branch -d  hotfix
Deleted branch hotfix (3a0874c).

分支的合并

假设你已经修正了 #53 问题,并且打算将你的工作合并入 master 分支。 为此,你需要合并 iss53 分支到 master 分支,这和之前你合并 hotfix 分支所做的工作差不多。 你只需要检出到你想合并入的分支,然后运行 git merge 命令:

git checkout  master
Switched to branch 'master'
git merge iss53
Merge made by the 'recursive' strategy.
index.html | 1 +
1 file changed, 1 insertion(+)

这和你之前合并 hotfix 分支的时候看起来有一点不一样。 在这种情况下,你的开发历史从一个更早的地方开始分叉开来(diverged)。 因为,master 分支所在提交并不是 iss53 分支所在提交的直接祖先,Git 不得不做一些额外的工作。 出现这种情况的时候,Git 会使用两个分支的末端所指的快照(C4 和 C5)以及这两个分支的工作祖先(C2),做一个简单的三方合并。

遇到冲突时的分支合并

有时候合并操作不会如此顺利, 如果你在两个不同的分支中, 对同一个文件的同一个部分进行了不同的修改, Git  就没法干净的合并他们, 如果你对 #53问题的修改和有关 hotfix  的修改都涉及到同一个文件的同一处, 在合并它们的时候就会产生合并冲突

git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

此时Git 做个合并, 但是没有自动创建一个新的合并提交, Git 会暂停下来, 等待你去解决合并产生的冲突, 你可以在你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件:

git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit") Unmerged paths:
(use "git add <file>..." to mark resolution) both modified: index.html no changes added to commit (use "git add" and/or "git commit -a")

任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。 出现冲突的文件会包含一些特殊区段,看起来像下面这个样子:

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。 例如,你可以通过把这段内容换成下面的样子来解决冲突:

<div id="footer">
please contact us at email.support@github.com
</div>

上述的冲突解决方案仅保留了其中一个分支的修改,并且 &lt;&lt;&lt;&lt;&lt;&lt;&lt; , ======= , 和 &gt;&gt;&gt;&gt;&gt;&gt;&gt; 这些行被完全删除了。 在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。

分支管理

现在已经创建、合并、删除了一些分支,让我们看看一些常用的分支管理工具。

git branch 命令不只是可以创建与删除分支。 如果不加任何参数运行它,会得到当前所有分支的一个列表:

git branch
iss53
* master
testing

注意 master 分支前的 * 字符:它代表现在检出的那一个分支(也就是说,当前 HEAD 指针所指向的分支)。 这意味着如果在这时候提交,master 分支将会随着新的工作向前移动。 如果需要查看每一个分支的最后一次提交.

Bug分支

版本控制git之二-分支的更多相关文章

  1. 版本控制git之二 分支 切换分支 创建分支 合并 删除

      版本控制git之二 分支   有人把 Git 的分支模型称为它的`‘必杀技特性’',也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出. 为何 Git 的分支模型如此出众呢? Git 处 ...

  2. 版本控制Git研究二

    经过好几周的工作忙碌,终于可以有时间静下心来学习东西了,做为崇尚技术的人来说,应该是最幸福的时光了,呵呵,当然也是宅神的表现啦,话不多说,继续git的学习,上次已经对git的一些概念进行了说明,具体可 ...

  3. Git版本控制 — 日常使用(二)

    本地使用 以下是我的一些日常操作. (1) 创建版本库 # cd /proj # git init Initialized empty Git repository in /proj/.git/ (2 ...

  4. 版本控制git(三)-git分支

    通过本系列的上两篇文章(查看系列文章:http://www.cnblogs.com/jerehedu/p/4607599.html#bbkz),我们已经知道了如何使用Git完成对文件的版本控制.本次我 ...

  5. 第二篇:版本控制git之分支

    有人把 Git 的分支模型称为它的`‘必杀技特性’',也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出. 为何 Git 的分支模型如此出众呢? Git 处理分支的方式可谓是难以置信的轻量, ...

  6. 版本控制git之三-多人协作 变基 推送 拉取 删除远程分支

      版本控制git之三-多人协作 wangfeng7399已关注0人评论350人阅读2019-02-20 21:33:08   如果你想获得一份已经存在了的 Git 仓库的拷贝,比如说,你想为某个开源 ...

  7. Git教程之分支管理之二

    分支管理策略 通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息.如果要强制禁用Fast forward模式,Git就会在merge时生成一个 ...

  8. git总结二、关于分支上——好好认识下分支是怎么回事

    同样需要先来明确两件事: HEAD指针指向的是当前分支 分支(master, dev)指向的是最新的提交 一开始,git 中只有一个master分支,严格来讲,HEAD不是指向提交而是指向master ...

  9. git(二) 分支管理

    概念 分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN. 如果两个平行宇宙互不干扰,那对现在的你也没啥影响.不过,在某个时间点,两个平行宇 ...

随机推荐

  1. admin- 源码解析(流程)

    首先我们需要了解一个知识点:---单例模式--- 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中 ...

  2. erlang开发环境配置

    第一步  从源码安装erlang git clone https://github.com/erlang/otp 目前最新版本为17.X cd otp/ ./configer  检查编译环境 sudo ...

  3. Why I am not afraid of AI (TBC)

    Freud! Yes, according to Freud's theory, most human activities are driven by libido (or aim-inhibite ...

  4. absolute的left和right的妙用

    之前做了一个自定义鼠标右键的布局,做的过程中遇到了一个很有趣的问题,之前一直没有注意到. 目标样式如下: 期初并不知道文字内容需要随机,所以写的时候写“死”了. 所有的内容都是按照设计的四个文字走的, ...

  5. threejs 画二维圆(圆弧)

    画圆: var radius = 40, segments = 64, material = new THREE.LineBasicMaterial({ color: 0x0000ff }), geo ...

  6. 一个简洁、好用的Pytorch训练模板

    一个简洁.好用的Pytorch训练模板 代码地址:https://github.com/KinglittleQ/Pytorch-Template 怎么使用 1) 更改template.py 替换 __ ...

  7. 利用 ReSharper 自定义代码中的错误模式,在代码审查之前就发现并修改错误

    多人协作开发的项目总会遇到代码编写风格上的差异.一般工具都能帮我们将常见的差异统一起来——例如 if 的换行:但也有一些不那么通用,但项目中却经常会出现的写法也需要统一. 例如将单元测试中的 Asse ...

  8. NET Core项目模板

    打造自己的.NET Core项目模板 https://www.cnblogs.com/catcher1994/p/10061470.html 前言 每个人都有自己习惯的项目结构,有人的喜欢在项目里面建 ...

  9. 轻量级KVO[译]

        在这篇文章中,我会实现一个自己用的简单KVO类,我认为KVO非常棒,然而对于我大部分的使用场景来说,有这两个问题: 1. 我不喜欢在observeValueForKeyPath:ofObjec ...

  10. oracle-分区(笔记)

    partition by 用于指定分区方式 range 表示分区的方式是范围划分 partition pn 用于指定分区的名字 values less than 指定分区的上界(上限) ------- ...