Git学习——Git分支篇(未完)

Git学习——Git分支篇(未完)


前言

完成了Git学习的基础篇,继续学习Git的分支特性,这是Git出众之处。

目录

  • 分支简介
  • 分支创建
  • 分支切换
  • 分支新建与合并
    • 分支新建
    • 分支合并
    • 遇到冲突时的分支合并

分支简介

首先,Git保存数据的方式比较特殊,保存的是文件的快照,而不是文件的变化。

因此,在执行提交( commit )操作时,Git会保存一个提交对象( commit object)。该提交对象包含一个指针指向暂存的内容快照,同时包含作者的姓名、邮箱、提交时输入的信息和指向它父对象的指针。

首次提交产生的提交对象没有父对象,普通提交产生的提交对象又一个父对象,多个分支合并产生的提交又多个父亲对象。

暂存操作会为每一个文件计算校验和(使用SHA-1哈希算法),然后保存当前版本的文件快照( Git使用blob对象来保存)。

提交操作会计算每个子目录的校验和,然后保存树对象在仓库中。然后Git会创建一个提交对象,它包含除了以上信息外,还有指向这个树对象(项目根目录)的指针。

当做出修改后再提交,所产生的提交对象会包含一个指向上次提交对象(父对象)的指针。

Git的分支,其本质是指向提交对象的可变指针。Git默认分支名为master,多次提交后,已经有一个指向最后提交对象的master分支,会在多次提交的操作中自动向前移动。

Git 的 master 分支并不特殊,它和其它分支一样,只是大多数人不会改变它。


分支创建

Git创建新分支实际上是创建了一个可以移动的指针,执行 git branch branch-name 完成。

    $ git branch testing

这会在当前所在的提交对象上创建一个指针。此时拥有两个分支 master 和 testing 。

Git 是如何知道当前所在分支,这是由于它有一个名为 HEAD 的特殊指针,指向当前所在的本地分支。此时我们还是 master 分支上,因为 git branch 命令只创建了一个新分支,并不会自动切换到新分支中去。

简单的使用 git log 命令可以查看各个分支当前所指向的对象。只要加上 --decorate选项。

$ git log --oneline --decorate
21eeb6c (HEAD -> master, testing) init the repo

可以看见当前的 master 和 testing 分支都指向校验和以 21eeb6c 开头的提交对象。


分支切换

执行 git checkout branch-name 可以切换到相应分支。

$ git checkout testing
Switched to branch ‘testing‘

此时的 HEAD 指向新分支 testing 。那么这么实现的作用是什么。假如此时在Git中修改并执行提交。

$ vim Hello.c
$ git add Hello.c
$ git commit -m "add Hello.c"

这里添加一个新文件举例,再使用 git log 查看。

$ git log --oneline --decorate
b6e0678 (HEAD -> testing) add Hello.c
21eeb6c (master) init the repo

可以看见的是,HEAD 指向了 testing并伴随其向前移动到了新的提交对象上,对象的校验和为b6e0678。值得注意的是,master 分支并没有向前移动,还是停留在上一次提交的状态。再次切换到 master 分支查看。

$ git checkout master
Switched to branch ‘master‘

这里,Git 做了两件事,以是将 HEAD 指向 master 分支,二是将工作目录恢复成 master 分支所指向的快照内容。也就是说,如果现在做修改,将始于一个较旧的版本。本质上就是忽略 testing 分支所做的修改,以便于向另一个方向进行开发。

分支切换会改变你工作目录中的文件在切换分支时,一定要注意你工作目录里的文件会被改变。 如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。 如果 Git 不能干净利落地完成这个任务,它将禁止切换分支。

此时我们在 master 分支中添加 Hello.java 并提交。执行以下命令,输出提交历史、各个分支的指向以及项目的分支交叉情况。

$ git log --oneline --decorate --graph --all
* ee4b05d (HEAD -> master) another version of Hello
| * b6e0678 (testing) add Hello.c
|/
* 21eeb6c init the repo

注意这里的master 和 testing 指向不同的对象。


分支的新建与合并

让我们来看一个简单的分支新建与分支合并的例子,实际工作中你可能会用到类似的工作流。 你将经历如下步骤:

  1. 开发某个网站。
  2. 为实现某个新的需求,创建一个分支。
  3. 在这个分支上开展工作。

    正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补。 你将按照如下方式来处理:

  4. 切换到你的线上分支(production branch)。
  5. 为这个紧急任务新建一个分支,并在其中修复它。
  6. 在测试通过之后,切换回线上分支,然后合并这个修补分支,最后将改动推送到线上分

    支。

  7. 切换回你最初工作的分支上,继续工作。

新建分支

首先,假设正在项目上工作,并且有了两次提交,记为C0(第一次提交),C1(第二次提交),此时的HEAD和和master在第二次提交处。

$ git log --oneline
d093652 (HEAD -> master) add homepage
64d793d add README

此时你决定要解决公司使用的问题追踪系统中的#53问题,于是想要新建一个分支并切换过去。可以执行如下命令。

$ git checkout -b iss53
Switched to a new branch ‘iss53‘

这条命令实际上和以两条下命令等价。

$ git branch iss53
$ git checkout iss53

此时的 master 和 iss53 都在第二次提交处,即C1。

假设你在iss53分支上工作并且做出了修改,经行了一次提交,这里记为C2。iss53的分支向前推进。

$ vim index.html
$ git add issue53.html
$ git commit -m "added a new footer [issue 53]"
$ git log --oneline
b8deb27 (HEAD -> iss53) added a new footer [issue 53]
d093652 (master) add homepage
64d793d add README

现在,你接到电话,有个紧急问题需要解决,在Git中,不需要将这个问题和iss53放到一起,也不需要还原关于#53问题的修改,然后再添加这个紧急问题的修改,所需要做的是切换回 master 分支。

在这么做之前,要留意工作目录和暂存区里那些还没有被提交的修改,它可能会和即将检出的分支产生冲突从而阻止 Git 切换到该分支。 最好的方法是在切换分支之前,保持好一个干净的状态。 有一些方法可以绕过这个问题,这先不深究。切换回 master 。

$ git checkout master
Switched to branch ‘master‘

此时的工作目录将和开始#53问题前一模一样,可以开始修复紧急问题,建立一个针对该紧急问题的分支( hotfix ),在该分支上工作直到问题解决。

假设问题很简单,只进行了一次提交完成了问题的解决。这次提交记为C3。

$ vim homepage.html
$ git commit -a -m "fixed the problem"

分支合并

在确保问题解决后想要合并回 master 分支 来部署到线上。执行 git merge branch-name 命令,记得要切换到 master 分支上。

$ git checkout master
Switched to branch ‘master‘
$ git merge hotfix
Updating d093652..4a8a77e
Fast-forward
 homepage.html | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 homepage.html

值得注意的是"Fast-forward"这个词。由于当前的 master 分支所指向的提交是有关hotfix的提交的直接上游,所以Git只是简单的将指针向前移动,因为这种情况下的合并操作没有需要解决的分歧,这叫做"快进Fast-forward"。

完成了紧急任务,你又要回到之前的工作,不过记得删除hotfix这个分支,因为你以及不需要了,master 已经指向了同一位置,删除操作如下。

$ git branch -d hotfix
Deleted branch hotfix (was 4a8a77e).

此时再切换到 iss53 分支继续之前的工作。假设你工作了一段时间经行了一次提交,记为C4。这里先梳理一下,master指向C3提交,iss53指向C4,C4的上游为C2,C2和C3的上游为C1。

$ git checkout iss53
vim index.html
...
...
$ git commit -a -m "fix some issues"

你在 hotfix 分支上所做的工作并没有包含到 iss53 分支中。 如果你需要拉取hotfix 所做的修改,你可以使用 git merge master 命令将 master 分支合并入 iss53 分支,或者你也可以等到 iss53 分支完成其使命,再将其合并回 master 分支。

假设这里#53已经解决,打算合并到master分支上,执行和之前合并 hotfix 差不多的命令。

$ git checkout master
Switched to branch ‘master‘
$ git merge iss53
Merge made by the ‘recursive‘ strategy.
 index.html   | 7 +++++++
 issue53.html | 0
 2 files changed, 7 insertions(+)
 create mode 100644 issue53.html

这里合并和 hotfix 的合并看起来不一样。因为 iss53 是从更早的时候分叉出来的(即 master 为C1时)。此时 master 为C3,并不是C4的直接祖先,Git需要做额外的工作,即将两个分支的末端快照(C3和C4)以及这两个分支的共同祖先(c1),做一个简单的三方合并。

和之前不同的是,这里将三方合并的结果做了一个新的快照并且自动创建一个新的提交指向了它。这个被称作一次合并提交,它的特别之处在于它有不止一个父提交。不妨记作C5。

$ git log --oneline --graph --all
*   f9d8ac1 (HEAD -> master) Merge branch ‘iss53‘
|| * 3c230d6 (iss53) fix some issues
| * b8deb27 added a new footer [issue 53]
* | 4a8a77e fixed the problem
|/
* d093652 add homepage
* 64d793d add README

这里由下向上显示了合并的过程,由于hotfix已经删除,所以不再显示。
64d793d代表C0,d093652代表C1,4a8a77e代表C3,b8deb27代表C2,3c230d6代表C4,f9d8ac1代表C5。此时可以删除iss53分支。

$ git branch -d iss53

原文地址:https://www.cnblogs.com/JayJudge/p/10357967.html

时间: 2024-10-08 10:29:14

Git学习——Git分支篇(未完)的相关文章

Git 学习笔记<分支管理> (三)

分支是什么? 分支就像树分出的树枝,不同的是,它们之间可以互相合并. 将版本的推进想象成一个链表的伸长:  version 1.0 ==> version 2.0 ==>version3.0  . master是主要的分支基本上用于发布产品.你可以从master分出一个dev,在上面创建新功能,或者修bug然后调试.最后再合并到master里面.就像下面这样. master分支:  version 1.0=========>version 2.0===... \            

git 学习之分支

在一开始学习 git 的时候我们经常提到一个东西---- master.那么 master 到底是什么呢?其实它就是一个分支,一般这个分支就是主分支.而在一般 git 中都有一个指向当前你工作的分支 HEAD. 对于一开始的时候,master 分支是一条线的.对于我们每次提交的时候,git 分支都会向前移动一次,因此随着我们的提交越来越多,master 分支也越来越长.当我们创建一个新的分支(hotFix)的时候,git 会为我们创建一个新的指针(hotFix),而我们可以把当前工作的地方指向当

四、git学习之——分支管理、解决冲突

分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN. 如果两个平行宇宙互不干扰,那对现在的你也没啥影响.不过,在某个时间点,两个平行宇宙合并了,结果,你既学会了Git又学会了SVN! 分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了.如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险. 现在有了分支,就不用怕了.你

git学习 六 分支管理

分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN. 如果两个平行宇宙互不干扰,那对现在的你也没啥影响.不过,在某个时间点,两个平行宇宙合并了,结果,你既学会了Git又学会了SVN! 分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了.如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险. 现在有了分支,就不用怕了.你

git学习(2)---分支操作

一.目的 本文将介绍git分支的操作,包括新建和删除分支.查看和切换分支.合并分支和合并冲突等内容. 本文涉及到的所有操作都是在Ubuntu14.04环境中进行的,git版本是1.9.1. 二.新建和删除分支 使用git branch name命令新建一个名为name的分支:使用git branch -d name命令删除一个名为name的分支. git默认的分支叫做master,在实际的项目中一般还会存在一个next分支.master分支作为主干版本,接受bugfix需求:next分支用来集成

git学习——远程分支

远程分支 远程分支(remote branch)是对远程仓库状态的索引.它们是一些无法移动的本地分支:只有在进行 Git 的网络活动时才会更新.远程分支就像是书签,提醒着你上次连接远程仓库时上面各分支的位置. 我们用 (远程仓库名)/(分支名) 这样的形式表示远程分支.比如我们想看看上次同 origin 仓库通讯时 master 的样子,就应该查看 origin/master 分支.如果你和同伴一起修复某个问题,但他们先推送了一个 iss53 分支到远程仓库,虽然你可能也有一个本地的 iss53

git学习 九 分支管理策略

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息. 如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息. 下面我们实战一下--no-ff方式的git merge: 首先,仍然创建并切换dev分支: $ git checkout -b dev Switched to a new branch 'dev' 修改readme.txt文件,并提交一个新的commit

Git学习0基础篇(下)

server上的 Git - 协议 Git能够使用四种基本的协议传输资料:本地协议(Local).HTTP 协议.SSH(Secure Shell) 协议以及 Git 协议.眼下使用最普及的是 SSH 协议和 HTTP 协议. 本地协议 本地协议的长处是简单,缺点是不方便从多个位置訪问. 克隆一个本地版本号库,能够运行例如以下命令: $ git clone /opt/git/project.git 或 $ git clone file:///opt/git/project.git HTTP 协议

git学习——Git 基础要点【转】

转自:http://blog.csdn.net/zeroboundary/article/details/10549555 简单地说,Git 究竟是怎样的一个系统呢?请注意,接下来的内容非常重要,若是理解了 Git 的思想和基本的工作原理,用起来就会知其所以然,游刃有余.在开始学习 Git 的时候,请不要尝试把各种概念和其他的版本控制系统诸如 Subversion 和 Perforce 等相比拟,否则容易混淆每个操作的实际意义.Git 在保存和处理各种信息的时候,虽然操作起来的命令形式非常相近,