git学习笔记之二 -- git分支
前面对git基础作了简单的总结,这次对git的杀手锏--分支做一总结。
Git分支简介
几乎每个版本控制系统都以某种形式支持分支,可以使你的工作从开发主线上分离开来,以免影响开发主线。很多版本控制系统常常要创建一个源代码目录的副本,略微低效。而Git保存的不是文件的差异和变化,而是一些列不同时刻的文件快照。当进行commit操作的时候,Git会保存一个提交对象(commit object),该提交对象包含作者的姓名和邮箱,提交时输入的信息,指向父对象的指针和一个指向暂存内容快照的指针,首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象。
形象的说,工作目录下有三个文件,暂存操作会为每个文件计算校验和,并把当前版本的文件快照使用blob对象保存到Git仓库中,最终将校验和添加到暂存区中等待提交,当进行commit提交时,Git先会计算每一个子目录的校验和,然后在Git仓库中将这些校验和保存为树对象,随后Git就会创建一个提交对象,除了上面提到的还会保存这个树对象的指针,就可以在需要时重现此次保存的快照。此时Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)。
做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。
Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master
。 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master
分支。 它会在每次的提交操作中自动向前移动。
创建分支 git branch
git branch testing ##创建testing分支,但不会切换到testing分支
这会在当前提交对象上创建一个指针。Git有一个名为HEAD的特殊指针,指向当前所在的分支。
你可以用git log 命令查看各个分支当前所指的对象,--decorate 参数提供此命令
$ git log --oneline --decorate
472aa16 (HEAD -> testing, master) all ## testing,master分支均指向校验和为472aa16的提交对象
24a207f add
de99f0e all
切换分支 git checkout
git checkout testing ## 切换到testing分支,这是HEAD就指向testing
这时,做些修改提交一次,看提交历史
$ git log --oneline --decorate
c2183f6 (HEAD -> testing) new branch ## 这里可以看到HEAD指向testing分支,testing分支向前移动,master分支却没变化
472aa16 (master) all
24a207f add
de99f0e all
这是切换回master分支,
git checkout master ##切换回master
此时其实是两步操作,一是使HEAD指向master分支,二是将工作目录恢复至master分支所指向的快照内容,也就是说忽略了刚才testing分支下的修改。
再做一次提交后,运行 git log --oneline --decorate --graph --all
,它会输出你的提交历史、各个分支的指向以及项目的分支分叉情况
$ git log --oneline --decorate --graph --all
* 2b6f868 (HEAD -> master) new tt.txt ## HEAD指向master,一次添加文件的提交
| * c2183f6 (testing) new branch ## testing分支上次提交的校验和为c2183f6的提交对象
|/
* 472aa16 all
* 24a207f add
分支的新建与合并
实际工作中,你可能会遇到类似的工作流。开发一个项目,为实现某个功能,创建一个分支iss,在分支iss上开展工作。此时有一个bug急需处理,你将按如下方式处理:
切换到你的线上分支(production branch)。
为这个紧急任务新建一个分支,并在其中修复它。
在测试通过之后,切换回线上分支,然后合并这个修补分支,最后将改动推送到线上分支。
切换回你最初工作的分支iss上,继续工作。
首先,你运行带参数-b的git checkout命令创建了iss分支并切换到iss分支,是git branch iss和git checkout iss两个命令的简写
git checkout -b iss ## 新建分支iss,参数-b表示并切换到iss分支
你已经做了一些提交,HEAD已经指向iss,此时修复bug,就需要切换到master分支,新建fix分支来处理bug,在切换分支前要要留意你的工作目录和暂存区里那些还没有被提交的修改。当切换分支的时候,Git会重置工作目录,使其看起来像回到了你在那个分支上最后一次提交的样子。
git checkout -b fix ## 新建并切换到fix分支,修改bug
合并分支 git merge
bug修改完成提交后,你要与master分支合并,就需要先切换到master分支,然后再合并
$git checkout master ## 切换回master分支
$ git merge fix ## 合并fix分支
Updating 558d34c..0f49f4e
Fast-forward ## 快进
index.html | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 index.html
你会注意到Fast-forward这个词,是由于master分支是需要合并的fix分支直接上游,git只是简单的将指针移动。也就是说当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧,就叫做Fast-forward.
删除分支 git branch -d
$ git branch -d fix ## 删除不需要的fix分支
Deleted branch fix (was 0f49f4e).
现在切换回iss分支,由于在fix上的修改没有包含到iss中,你可以用git merge master命令将master合并到iss分支,也可以等iss完成修改后合并回master分支
$ git merge iss
Merge made by the 'recursive' strategy. ## 合并提交
tt.txt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
由于master分支所在的提交不是iss分支所在提交的直接祖先,Git会把两个分支的末端所指的快照(0f49f4e和88502d9),以及这两个分支的工作祖先(558d34c),进行一个简单的三方合并,合并结果不是简单的快进(Fast-forward),而是生成了个新的快照(ce91eb7)并创建一个新的提交指向它,这个过程是一次合并提交,合并完成后就可以删除iss分支了。需要说明,Git 会自行决定选取哪一个提交作为最优的共同祖先,并以此作为合并的基础。
$ git log --oneline --decorate --graph --all
* ce91eb7 (HEAD -> master) Merge branch 'iss' ## 合并提交后生成一个新的快照,并指向新的提交
|\
| * 88502d9 (iss) iss ## iss分支的最后一次提交
| * 8de2c03 second
| * be76065 new iss
* | 0f49f4e fix ## master分支的最后一次提交
|/
* 558d34c all ## iss分支和master分支的工作祖先
* 863dcdc test
遇到冲突时的分支合并
如果在两个不同的分支中,对同一文件的同一部分进行了不同的修改,Git就无法自动合并。使用git status命令就会看到发生冲突的文件,打开冲突的文件,(=======)分割的上段为当前分支master的修改,下段为iss的修改,删除冲突标识符,手动修改保留一个分支的修改,对每个文件使用git add命令表示冲突已解决,git commit来完成合并提交
<<<<<<< HEAD
master edit.
=======
iss edit.
>>>>>>> iss
分支管理
$ git branch ## 列出当前所有分支的一个列表,*表示HEAD指向的分支
iss
* master
$ git branch -v ## 参数-v查看每个分支的最后一次提交
iss 5735ce0 iss edit
* master 3ab0a47 merge
$ git branch --merged ## 查看已合并到当前分支的分支
iss
* master
$ git branch --no-merged ## 查看未合并到当前分支的分支
testing
$ git branch -d testing ## 未合并的分支删除时,如果你确认需要删除,参数-D强制删除
error: The branch 'testing' is not fully merged.
If you are sure you want to delete it, run 'git branch -D testing'.
分支开发工作流
长期分支:
只做简单的快进合并,反复的把一个分支合并到稳定的分支。常常会只在master分支保留完全稳定的代码(有可能仅仅是已经发布或即将发布的代码),还有一些develop或next的平行分支,被用来做后续开发或测试稳定性,这些分支不必保持稳定状态,一旦达到稳定状态就可以合并到稳定的master分支。可以用这种方法维护更多层次的分支。
特性分支:
特性分支对任何规模的项目都适合。性分支是一种短期分支,它被用来实现单一特性或其相关工作。之前的iss分支和fix分支就是这种用法。在iss和fix分支中提交一些更新,合并到主干后又删除它们,这样能使你快速并完整的切换,更容易的看出做了哪些改动。你可以在改动的特性分支中保留很久,等成熟后再合并。
请牢记:当你新建和合并分支的时候,所有这一切都只发生在你本地的 Git 版本库中 —— 没有与服务器发生交互。
远程分支
远程引用是对远程仓库的引用(指针),包括分支和标签等等。可以用git remote show获取远程分支的更多信息,但常用的做法是远程分支跟踪。
远程跟踪分支是远程分支状态的引用。它们以(remote)/(branch)的形式存在。远程仓库的名字origin跟分支master,没有什么特殊的含义,master是git init时默认的分支名字,origin是git clone时远程仓库默认的名字。
git fetch origin 从远程抓取仓库origin中本地没有的数据。
推送
当需要公开分享一个分支时,将其推送到一个有写入权限的远程仓库,本地的分支不会自动的与远程的仓库同步,你必须显示的推送你想要分享的分支。这样你就可以把不愿分享的内容放到私人分支上,需要和别人协作的内容放到公开的分支上。
git push origin serverfix ## 推送本地的 serverfix 分支来更新远程仓库上的 serverfix 分支
git push origin serverfix:serverfix ## 推送本地的 serverfix 分支,将其作为远程仓库的 serverfix 分支
git push origin serverfix:awesomebranch ## 推送本地的 serverfix 分支,将其作为远程仓库的 awesomebranch 分支,给远程分支改名
其他协作者从服务器上抓取数据时,就会在本地生成一个远程分支origin/serverfix,指向服务器serverfix分支的引用。但当抓取新的远程跟踪分支时,本地不会自动生成一个可编辑的副本,即不会有一个新的分支serverfix,只是一个不可修改的origin/serverfix的指针。可以运行 git merge origin/serverfix
将这些工作合并到当前所在的分支。
如果想要在自己的 serverfix
分支上工作,可以将其建立在远程跟踪分支之上:git checkout -b serverfix origin/serverfix
跟踪分支
从一个远程跟踪分支检出一个本地分支会自动创建一个叫做 “跟踪分支”。 跟踪分支是与远程分支有直接关系的本地分支。 如果在一个跟踪分支上输入git pull
Git 能自动地识别去哪个服务器上抓取、合并到哪个分支。当克隆一个仓库时,它通常会自动地创建一个跟踪 origin/master
的 master
分支。如果想跟踪其他分支,就运行git checkout -b [branch] [remotename]/[branch]。因为比较常用Git提供了--track快捷方式。
git checkout --track origin/serverfix ## 跟踪远程分支serverfix
git checkout -b sf origin/serverfix ## 本地分支与远程分支设置不同的名字
git branch -u origin/serverfix ## 设置已有的本地分支跟踪一个刚刚拉取下来的远程分支,或者想要修改正在跟踪的上游分支
git branch -vv ## 查看设置的所有跟踪分支
git branch -vv 查看每一个分支正在跟踪哪个远程分支与本地分支是否是领先、落后,这些都是与最后一次抓取的数据作比较,要想统计最新的需要在git branch -vv前先执行git fetch --all命令抓取所有的远程仓库。
拉取
当用git fetch命令从服务器抓取本地没有的数据时,不会修改工作目录中的内容,只会让你自己合并。git pull命令大多数情况下是执行git fetch后接着执行git merge。如果设置好跟踪分支,git pull都会查找当前分支所跟踪的服务器与分支,从服务器上抓取数据然后尝试合并入那个远程分支。所以通常单独显式地使用 fetch
与 merge
命令会更好一些。
删除远程分支
如果远程分支的工作已经完成并合并到远程仓库的master分支,就可以用带有--delete选项的git push命令删除远程分支了。
$ git push origin --delete serverfix ##从服务器上删除 serverfix
分支
基本上这个命令做的只是从服务器上移除这个指针。 Git 服务器通常会保留数据一段时间直到垃圾回收运行,所以如果不小心删除掉了,通常是很容易恢复的。
变基
变基一般是为了确保在向远程分支推送时能保持提交历史的整洁,修改了提交历史。但请记住不要对在你的仓库外有副本的分支执行变基。
总的原则是,只对尚未推送或分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作。变基就不做说明了。
Git笔记先写到这。下次用到更高级的功能继续补充。
git学习笔记之二 -- git分支的更多相关文章
- Git学习笔记(二)分支管理与合并及Bug分支
一.分支管理 1.什么是分支 分支就相当于我们看科幻片里的平行宇宙,如果两个平行宇宙互不干扰,那铁定是啥事儿没有.不过,在某个时间点,两个平行宇宙合并了呢?假如两个宇宙中都有你的影子, 合并之后相当于 ...
- Git学习笔记(二) · 非典型性程序猿
远程库的使用 前面说到的都是git在本地的操作,那么实际协作开发过程中我们肯定是要有一个远程版本库作为项目的核心版本库,也就是投入生产使用的版本.这里我们以 Github为例.Github是一个开放的 ...
- git 学习笔记 —— 保留/丢弃当前分支修改并切换至其他分支
笔者在本地终端进行 git 工作目录的相关处理时,遇到由于某种情况需要使用 git checkout 命令切换到其他分支的情景.此时,若已经对当前分支做了一定的修改,则直接切换分支时 git 会提示错 ...
- Git学习笔记(二)
一.创建远程仓库(GitHub) 1.GitHub网站地址:https://github.com/,这个网站就是提供Git仓库托管服务的,所以,只要注册一个GitHub账号,就可以免费获得Git远程仓 ...
- git——学习笔记(三)分支管理
一.创建.合并分支 每次提交,git都往后走一格,串成一跳时间线,head指向的是分支,分支指向提交.master是主分支,dev是另一条分支,分支就像指针一样,合并.删除分支时,修改的都是指针,工作 ...
- git——学习笔记(二)远程仓库
GIT杀手锏之一——远程仓库 拥有远程仓库的两个办法 1:搭一个Git服务器 2:在GitHub上免费托管的Git仓库 本地仓库 远程仓库 一.在GitHub上免费托管的Git仓库 电脑: 1. ...
- git学习笔记(四)—— 分支管理
一.创建与合并分支 git branch //查看分支 git branch <name> //创建分支 git checkout <name> //切换分支 git chec ...
- git学习笔记(二)—— 创建版本库&&版本管理
一.创建版本库 创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录: mkdir gitHub_CXWcd gitHub_CXW git init Initialized empty G ...
- Git学习笔记(5)——分支管理
本文主要记录了分支的原理.分支的创建,删除,合并.以及分支的使用策略. 分支在实际中的作用 假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不 ...
随机推荐
- MVC学习笔记1-MVC家族间的区别
ASP.NET下的MVC从原始的1.0走到2.0,再到3.0,现在走到4.0,也许明年5.0就问世了,先不管那些,那说说这些MVC在ASP.NET是如何变化发展的.对于.net编程人员来说可能会很熟悉 ...
- Spring初识(通过小实例清晰认识Spring)
1.spring架构: spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,iba ...
- jumpserver跳板机
一.安装依赖包 yum -y install epel-release yum clean all && yum makecache yum -y update yum -y inst ...
- google官方的下拉刷新+自定义上拉加载更多
转载请标注转载:http://blog.csdn.net/oqihaogongyuan/article/details/50949118 google官方的下拉刷新+自定义上拉加载更多 现在很多app ...
- 读Zepto源码之代码结构
虽然最近工作中没有怎么用 zepto ,但是据说 zepto 的源码比较简单,而且网上的资料也比较多,所以我就挑了 zepto 下手,希望能为以后阅读其他框架的源码打下基础吧. 源码版本 本文阅读的源 ...
- sleep()和wait()的区别 --- 快入睡了,突然想起一个知识点,搞完就睡
自从开了博客之后,大部分是转发的,不断的ctrl+c和ctrl+v,知识是越屯越多,吸收的却很少,后来越来越懒,直接保存链接了. 我已经认识到了自己的错误,自己查询到的这些知识,以后还是会定期保存的, ...
- 使用Microsoft SQL Server Migration Assistant for Oracle迁移数据库
前言:使用Microsoft SQL Server Migration Assistant for Oracle迁移Oracle数据库到SqlServer数据库. 准备:Oracle11g.SqlSe ...
- 极化SAR图像基础知识(2)
本篇主要关注物理含义 1.极化 电磁波在传播时,传播的方向和电场.磁场相互垂直,我们把电波的电场方向叫电波的极化.(i.e.依据电场E的方向来定义电磁波的极化). 如果电场矢量端点随时间变化的轨迹是一 ...
- Sitemesh 3 配置和使用(最新)
Sitemesh 3 配置和使用(最新) 一 Sitemesh简介 Sitemesh是一个页面装饰器,可以快速的创建有统一外观Web应用 -- 导航 加 布局 的统一方案~ Sitemesh可以拦截任 ...
- 概率检索模型及BM25
概率排序原理 以往的向量空间模型是将query和文档使用向量表示然后计算其内容相似性来进行相关性估计的,而概率检索模型是一种直接对用户需求进行相关性的建模方法,一个query进来,将所有的文档分为两类 ...