认识分支

Git中分支管理是Git的一大特色,由于在实际项目开发中的也确定性以及需求变更的复杂性,所有的开发都集中在一条分支上开发势必造成开发与维护成本的提高。以软件项目开发为例,由于开发会有多个开发周期,发布多个软件版本,每个已发布的版本又可能出现Bug,以及适应时代的变化,不断升级软件,推出新功能。这些都是开发中可能出现的情况,试想这些开发都在一个分支(目前是master)上进行开发,那么会严重影响软件的开发进度,这样算下来的时间成本是非常之高的。现在流行的敏捷开发方式就需要完善的分支管理方案。

使用分支将某个功能或者Bug的修复独立出来,这样就实现了与主开发分支的隔离,不同开发组的开发工作也不会发生冲突,大大提高了开发效率。

分支操作

分支命令

在Git中使用非分支操作命令是git branch。该命令的用法有如下几种:

//查看分支git branch//创建分支git branch <branchname>//从某个起始点创建分支git branch <branchname> <start-point>//删除分支git branch -d <branchname>//强制删除分支git branch -D <branchname>//重命名分支git branch -m <oldbranch> <newbranch>//强制重命名分支git branch -M <oldbranch> <newbranch>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

分支操作实例

继续上一篇文章的操作,查看之前的提交日志:

项目初始化

//配置命令别名git config --global alias.lol "log --oneline --decorate --graph --all"//之后就可以使用git lol查看日志了git lol
  • 1
  • 2
  • 3
  • 4

输出如下:

*   e4e0025 (HEAD -> master, origin/master) Merge tag 'mytag3' of file:///home/rhwayfun/java/notes/repos2/share|\  | * 1ed8141 (tag: mytag3) blank commit for GnuPG-signed tag test.|/  * 6d095e6 blank commit for annotated tag test.* abb48d5 (tag: mytag) blank commit.*   1e5c656 Merge README.txt: Hello, user2 and user1.|\  | * 04eed97 create README.txt* | b14d8be create README.txt|/  *   0432ca1 Merge branch 'master' of file:///home/rhwayfun/java/notes/repos2/share|\  | * 5f642a9 create team/user2.txt* 14cc834 create team/user1.txt
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

现在开始在这个基础上执行分支操作,为了与之前的提交区别开,开始先创建一个空提交,然后在该提交创建带说明的里程碑(上一篇有讲解哦),执行操作如下:

//创建一个空白提交git commit --allow-empty -m "start git branch learning."//创建里程碑v1.0git tag -m "Release 1.0" v1.0//将里程碑推送到共享仓库git push origin v1.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

user1完成speak功能

现在已经创建了里程碑并推送到了远程分支,接下来就开始创建分支,并在分支上进行开发了。

首先需要创建分支:

//切换到user1的工程目录cd user1/project//创建user1/dev分支git branch user1/dev//切换到user1/dev分支git checkout user1/dev
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

查看创建的分支:

master
  * user1/dev

这样就把分支切换到user1/dev分支上了,在user1/dev分支需要实现人说话和走路的功能,说话的功能由user1实现,走路的功能由user2实现。执行如下操作:

//创建PersonService接口touch src/main/java/PersonService.java//编辑PersonService.javavim src/main/java/PersonService.java
  • 1
  • 2
  • 3
  • 4

在接口中定义了两个方法:说话和走路的方法。

package com.rhwayfun.hello.service;public interface PersonService{        //speak--->assign to user1 to finish.        void speak();        //walk--->assign to user2 to finish.        void walk();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

编译PersonService.java文件:

javac -d /home/rhwayfun/java/notes/to2/user1/project/src/main/java/com/rhwayfun/hello/service src/main/java/com/rhwayfun/hello/service/PersonService.java
  • 1
  • 2

创建PersonServiceImpl.java文件,然后由user1实现speak方法,如下:

package com.rhwayfun.hello.service.impl;import com.rhwayfun.hello.service.PersonService;public class PersonServiceImpl implements PersonService {        //finish by user1.        public void speak(){                System.out.println("I can speak English.");        }        //finish by user2.        public void walk(){                // to do by user2        }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

现在user1已经完成了speak功能的开发,然后执行如下操作将修改推送到共享版本库:

//将工作区所有的修改都添加到暂存区git add .//提交到本地版本库git commit -m "user1 finish speak function."//切换到master主分支git checkout master//合并user1/dev开发分支git merge user1/dev
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这样在本地版本库就有了最新的提交,在正式推送到共享仓库之前,可以简单分析以上命令的执行过程,分支实际上是在目录.git/refs/heads下的引用,版本库初始时创建的master分支就在该目录下,为了验证这一点,可以执行如下命令:

ls -F .git/refs/heads
  • 1

输出结果为:

master
  user1/

ls -F .git/refs/user1
  • 1

输出结果为:

dev

创建非分支user1/dev是基于头指针HEAD创建的,因此当前分支和master分支的指向是一致的。

现在可以将user1的成果推送到共享版本库了,只需要执行git push就可以完成。接下来的走路的功能需要user2来完成,因此首先切换到user2的工作区:

cd user2/project//拉取最新的提交git pull
  • 1
  • 2
  • 3

user2完成walk功能

现在user2已经拥有了最新的功能,为了不影响master主分支的开发,需要将walk功能的开发切换到一个分支上进行:

//创建user2/dev分支并切换到该分支上git checkout -b user2/dev
  • 1
  • 2

在PersonServiceImpl.java文件中完成walk方法的开发,代码如下:

...    //finish by user2.    public void walk(){        // to do by user2        System.out.println("Nice, I can walk.");    }...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这样user2就完成了walk功能的开发,执行如下操作将user2完成的功能推送到共享版本库:

git add .git commit -m "user2 finish walk function."git checkout mastergit merge user2/devgit tag -m "Release 1.1" v1.1git push//推送里程碑v1.1到远程仓库git push origin v1.1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

要注意的是里程碑必须额外手动推送到远程仓库,不然直接执行git push只会将master分支的修改推送到远程仓库。最后我们可以看看user1和user2完成PersonService接口开发的提交日志情况:

* 4fc2175 (HEAD -> master, tag: v1.1, origin/master) user2 finish walk function.* f62c2cf user1 finish speak function.* 8f126fc (tag: v1.0) start git branch leanring.*   e4e0025 Merge tag 'mytag3' of file:///home/rhwayfun/java/notes/repos2/share|\  | * 1ed8141 (tag: mytag3) blank commit for GnuPG-signed tag test.|/  * 6d095e6 blank commit for annotated tag test.* abb48d5 (tag: mytag2, tag: mytag) blank commit.*   1e5c656 Merge README.txt: Hello, user2 and user1.|\  | * 04eed97 create README.txt* | b14d8be create README.txt|/  *   0432ca1 Merge branch 'master' of file:///home/rhwayfun/java/notes/repos2/share|\  | * 5f642a9 create team/user2.txt* 14cc834 create team/user1.txt
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

Bug分支协同操作

现在user1和user2已经通过协作共同完成PersonService接口的开发,嗯,非常好,这个过程通过使用Git 分支操作很顺利地完成了功能的开发。现在因为需求变更,需要修改speak和walk功能的实现,因为两个功能是由两个开发者user1和user2协同完成的,所以需要创建一个bug分支,修复代码并提交。

在user1的工作区下执行如下命令:

//创建协同工作分支git checkout -b hello-1.x v1.1//查看两者的对应的提交git rev-parse hello-1.x v1.1^{} master
  • 1
  • 2
  • 3
  • 4

修改PersonServiceImpl.java代码如下:

...    //finish by user1.    public void speak(){        System.out.println("I can speak English.");     }...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这样user1就完成了speak功能的bug修复,于是执行如下操作:

git add -ugit commit -m "fix speak bug."git checkout mastergit merge hello-1.x git push origin hello-1.x 
  • 1
  • 2
  • 3
  • 4
  • 5

现在已经把需要协同处理的bug分支提交到共享仓库了,切换到user2的工作区目录下,执行如下命令:

//获取共享最新的更新,但不执行merge操作git fetch//显示远程仓库指向的引用git ls-remote origin//从上一个命令中可以发现有一个hello-1.x的bug分支//从远程仓库origin/hello-1.x分支创建本地hello-1.x分支并切换到该分支git checkout -b hello-1.x origin/hello-1.x
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

打开PersonServiceImpl.java文件,修改walk方法的代码如下:

...    //finish by user2.    public void walk(){        // to do by user2        System.out.println("Oh oh, I can only walk.");    }...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这样user2也完成了bug的修复,于是执行如下操作:

git add -ugit commit -m "fix walk bug."git checkout mastergit merge hello-1.xgit push
  • 1
  • 2
  • 3
  • 4
  • 5

现在user2已经最后的bug修复修复结果合并到master分支了,为了保持同步,user1需要执行如下操作:

git pull//因为user1的本地hello-1.x分支不是最新的git checkout hello-1.x//合并到master分支git merge master
  • 1
  • 2
  • 3
  • 4
  • 5

完成以上bug修复之后,显示的最新提交日志输出如下:

* 0b8844a (HEAD -> master, origin/master, hello-1.x) fix walk bug.* 55889c6 (origin/hello-1.x) fix speak bug.* 4fc2175 (tag: v1.1) user2 finish walk function.* f62c2cf user1 finish speak function.* 8f126fc (tag: v1.0) start git branch leanring.*   e4e0025 Merge tag 'mytag3' of file:///home/rhwayfun/java/notes/repos2/share|\  | * 1ed8141 (tag: mytag3) blank commit for GnuPG-signed tag test.|/  * 6d095e6 blank commit for annotated tag test.* abb48d5 (tag: mytag2, tag: mytag) blank commit.*   1e5c656 Merge README.txt: Hello, user2 and user1.|\  | * 04eed97 create README.txt* | b14d8be create README.txt|/  *   0432ca1 Merge branch 'master' of file:///home/rhwayfun/java/notes/repos2/share|\  | * 5f642a9 create team/user2.txt* 14cc834 create team/user1.txt
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

变基操作和拣选操作

变基操作使用的命令是git rebase
拣选操作使用的命令是git cherry-pick

先说说拣选操作,可以选择某一个分支中的一个或几个commit(s)来进行操作,使用的场景有两个:

1、把弄错分支的提交移动到正确的地方
  2、把其他分支的提交添加到现在的分支

再说说变基操作,可以改写、替换、删除或合并提交。常在需要合并的场景下使用,而合并和变基的操作可以使用如下简图加以区别:

假设初始状态是这样的:

合并操作是这样的:

变基操作是这样的:

可以看到变基操作不会产生新的提交,降低了代码维护的成本,而且合并方式更加优雅。

下面通过实际操作演示变基操作:

在user2的工作区执行如下操作:

touch rebase.txtvim rebase.txt
  • 1
  • 2

编辑rebase.txt文件如下:

This is rebase operatio by user2.

之后将所做的修改提交到本地仓库,然后推送到共享版本库,这个过程执行的一系列操作如下:

git add rebase.txtgit commit -m "create rebase.txt file"git checkout mastertouch rebase.txtvim rebase.txt
  • 1
  • 2
  • 3
  • 4
  • 5

在user2的master分支编辑rebase.txt文件如下:

It is a rebase operation by user2.

之后执行如下操作,在master分支上添加到本地仓库,这样做的目的是造成变基操作过程冲突:

git add .git commit -m "create rebase.txt on master."git checkout user2/devgit rebase master
  • 1
  • 2
  • 3
  • 4

在执行变基操作git rebase时出现如下错误:

First, rewinding head to replay your work on top of it…
  Applying: create rebase.txt file
  Using index info to reconstruct a base tree…
  Falling back to patching base and 3-way merge…
  Auto-merging rebase.txt
  CONFLICT (add/add): Merge conflict in rebase.txt
  Failed to merge in the changes.
  Patch failed at 0001 create rebase.txt file
  The copy of the patch that failed is found in:
     /home/rhwayfun/java/notes/to2/user2/project/.git/rebase-apply/patch
  When you have resolved this problem, run “git rebase –continue”.
  If you prefer to skip this patch, run “git rebase –skip” instead.
  To check out the original branch and stop rebasing, run “git rebase –abort”.

意思就是变基操作出现了冲突,需要在工作区处理冲突后将处理冲突的文件添加到暂存区,然后继续变基操作。同时我们直到发生冲突的文件是rebase.txt文件,将工作区的rebase.txt文件修改如下:

This is a rebase operation by user2.

再执行如下操作,完成最终的变基操作:

git add -ugit rebase --continuegit checkout mastergit merge user2/dev //用本地的user2/dev分支直接更新远程版本库的master分支git push origin user2/dev:master
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这样就是完成了变基操作,而拣选操作就很好理解了,可以在不同的分支上将其他的commit拿过来并接到该分支之后,就完成了拣选操作。

小结

通过以上实例的演示,可以非常清楚地看到分支操作在协同开发中的重要性,分支操作大大节省了开发时间,所以好好掌握分支操作是很重要的。此外,演示中还将Git中比较难以理解的变基操作、合并操作以及拣选操作进行了说明和演示。变基操作相比合并操作是一种更优雅的合并方式,因为合并操作会产生第三个提交,在合并操作很多的时候,代码维护的难度就会上升。

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

Git学习8 Git分支操作相关推荐

  1. Git学习笔记:分支管理3

    前言 在补习python的时候主要参考的是廖雪峰的教程Python教程,在学习完后准备完成期末作业时,遇到了一个技术难题,需要初步掌握git,因此开始了git的学习. 本教程参考廖雪峰的Git教程 G ...

  2. Git学习笔记:分支管理(2)

    前言 在补习python的时候主要参考的是廖雪峰的教程Python教程,在学习完后准备完成期末作业时,遇到了一个技术难题,需要初步掌握git,因此开始了git的学习. 本教程参考廖雪峰的Git教程 G ...

  3. Git实战:branch分支操作详解

    什么是分支 分支是指在主干道上分支的支线,可以前往不同的地方,也可以到达相同的终点(只是实现的路线不同).Git指向团队开发中的个体,各开发者可以有自己的分支,开发时不会影响其他分支的开发进度.分支完 ...

  4. 超详细的Git学习记录(Git基础内容/IDEA集成Git/GitHub/Gitee/GitLab及Centos7部署GitLab)

    超详细的Git学习笔记 从B站搜到的尚硅谷视频学习了Git,记录了一下学习的内容,收获很大 学习地址: https://www.bilibili.com/video/BV1vy4y1s7k6?p=11 ...

  5. Git之常见的分支操作

    目录 分支管理 1.创建与合并分支 1.2switch 2.解决冲突 3.分支管理策略 4.分支策略 5.Bug分支 6.Feature分支 7.多人协作 8.推送分支 9.抓取分支 10.Rebas ...

  6. Git学习小记之分支原理

    介绍 如果想要熟练使用 Git,没有分支理念是绝对行不通的,在用 Git 管理项目的时候,经常需要使用 commit 这个命令,那么这个 commit 到底是指什么呢? 按照官方的解释,这应该成为一个 ...

  7. Git学习系列(五)分支管理详解

    分支管理在咱们实际工作中经常用到,因此掌握分支对于咱们从事移动开发并且使用到了Git这样的分布式版本管理工具来说是很有必要的.比如当你饿了的时候,甲帮你做饭,一帮你烧菜: 当然你也可以自己做饭烧菜.但 ...

  8. Git - 学习/实践 - 以及相关操作

    1.环境 win10 64位 专业版 默认, 已安装git.[git bash]所有操作均在git bash 中. 2.使用 1. 文档阅读/查阅 https://git-scm.com/docsht ...

  9. git常用命令,分支操作,子模块

    Git 是一个很强大的分布式版本管理工具,它不但适用于管理大型开源软件的源代码(如:linux kernel),管理私人的文档和源代码也有很多优势(如:wsi-lgame-pro) 二. Git 常用 ...

  10. git学习------gt;Git 分支管理最佳实践

    ps:本文转载于 : https://www.ibm.com/developerworks/cn/java/j-lo-git-mange/index.html Git 是目前最流行的源代码管理工具.大 ...

最新文章

  1. 你还是只会用数组吗?不懂Java集合,还想找工作?(集合概述)
  2. Golang的for range遍历
  3. oracle激活锁定用户,oracle 锁用户,oracle解除用户锁定
  4. sikuli 搜索例子
  5. 监理公司的核心竞争力
  6. 二分法(leetcode分类解题,C++代码详细注释)
  7. 荣耀x10max能不能升级为鸿蒙,荣耀X10 Max即将亮相:容量很“放肆” 身材却很“克制”...
  8. MySQL访问权限管理
  9. LeetCode(1108)——IP 地址无效化(JavaScript)
  10. 在河北大学就读是怎样一种体验?
  11. 李开复:21世纪最需要的7种人才
  12. python下载特别慢-Python3 用 urllib 下载图片非常慢,会是什么原因呢?
  13. left join on 左边为主
  14. eclipse为项目设置jdk
  15. 嵌入式开发与单片机开发有什么区别
  16. XMPP即时通讯基础知识
  17. python计算皮尔森相关系数
  18. matlab画直方图
  19. 关于MPU6050学习的一些总结之一MPU6050芯片手册的整理
  20. 天津大学计算机学院院长及副院长,微软亚洲研究院副院长周明教授和段楠研究员来天津大学-中国计算机学会...

热门文章

  1. Android之数据统计TalkingData集成
  2. Dapr for dotnet | 发布与订阅- Publish Subscribe
  3. win10开机自动拨号上网
  4. iOS之推荐六款不错的 iOS 15 Safari 浏览器扩展
  5. 第二人生的源码分析(八十四)保存UI的界面布局
  6. 如何查看内存条的实际使用频率
  7. 转:移动定制机S5820改造手记
  8. 基于Spring MVC + Spring + MyBatis的【银行卡系统】
  9. freecodecamp小练习——Falsy Bouncer过滤数组假值
  10. 龟兔赛跑Description乌龟与兔子在马路上赛跑,马路边可以随地进行休息。