Git是分布式的,但多数时候仍然要使用中央仓库作为所有开发者的交互中心,和svn一样,开发人员仍要在本地写代码并提交到中央服务器。Git相较于svn最大的优势就在于其强大的分支系统,而git的工作流程配合其强大的分支系统,可以说几乎完美的契合了敏捷开发的要求。任何事情都一样,有一个明确的管理规范,做事情才能有条理,git使用这个事情,Vincent Driessen同学提出了这么一套理论:http://nvie.com/posts/a-successful-git-branching-model,文章的翻译版本:http://www.cnblogs.com/yaks/p/5666400.html。

  几个常用分支约定:

  •  Master分支:主干分支,一般用作生产分支
  •  Develop分支:开发分支,开发人员日常交互所用分支
  •  Release分支:发布分支,一般是打包给测试人员的分支
  •  Feature分支:功能分支,开发人员在本地为某个功能而建立的分支
  •  Hotfix分支:热修复分支,生产出现问题,临时修复bug所用的分支

  各个分支如何协同工作:

  Master是线上版本,所有的提交都应该打tag,并记录修改内容;Release、develop跟feature分支:

  

  Develop分支是从master分支检出的,开发人员自己本地具体的feature分支是开发人员在自己本地建立的(过程2跟3),命名一般是自己名字或者功能名字之类,如果该功能跟其它开发人员无关,一般不建议推送服务器(开发人员多的时候,看上去太乱)。开发人员完成功能(也可能没完成功能,每天下班提交代码),提交到develop分支(过程4),有功能开发完毕,需要打包给测试人员,我们需要从develop分支检出一个分支release(过程5),其它功能仍然正常提交develop分支(过程6,开发分支仍然正常往下走),release分支进行测试,有bug直接在release进行修改,测试通过后,将改动合并到develop分支(过程8),如果该功能需要上线,则合并到master分支,上线。

  疑问1、为什么要在本地建一个feature分支?

  因为在开发一个新功能时,我们肯定不想把原来的代码给搞乱了,所以我们搞一个新的分支,开发完成后合并到开发分支。如果你觉得就喜欢在develop分支进行开发,保证不会因为搞乱代码之类的造成一些困扰,没问题,可以不要feature分支。

  疑问2、为啥打包的时候要独立出一个release分支,在原来的develop分支上打包进行测试不行么?

  不是说不行,是不好,比如说第一次打包develop0.1给测试人员,第二天经过测试后发现了几个bug,然后开发人员进行修复后提交到develop,重新打包develop0.2给测试人员,注意,这里提交代码的时候,可能其它的开发人员也提交了代码到develop分支,这些代码有可能对develop0.1测试的几个问题有影响!因此为了避免这种情况,单独打一个release分支出来,维持不变,develop继续提交。因此:一旦打了Release分支之后不要从Develop分支上合并新的改动到Release分支。

  热修复分支用于线上发布版本的快速bug修复。它直接从master分支检出,修复测试完成后合并到master跟develop分支(过程9跟10)。为了bug修复使用专门分支,让团队可以处理掉问题而不用打断其它工作或者是等待下一个发布循环。

  具体使用(以eclipse的egit为例):

  1、上传项目到git

  Eclipsegit插件egit为例,项目右键---->share project---->勾选use or create repository in parent folder of project---->点击project下的复选框,然后点击create repository---->finish,然后项目右键---->team---->commit---->填写提交信息---->commit and push,url一栏填写资源库的url,插件会自动补齐host跟repository path,下方填写账号密码用于验证,然后finish就可以了。

  2、添加忽略文件

  跟svn一样,有一些配置文件之类的是我们不想提交到中央服务器的,因为每个人的配置都会不一样。添加忽略文件为:文件右键---->team---->ignore,会在本地生成一个名称为.ignore的文件,也可以手动修改该文件,把要忽略的文件路径添加进来。

  

  3、分支的新建、切换、删除

  在项目上右键---->team---->switch to可以进行新建分支或者切换分支,点击new branch进行新建分支,点击列表中的分支名称进行切换分支,切换后会看到项目名后的分支名称变化(图中蓝色框部分),删除分支在项目右键---->team---->advanced---->delete branch(只能删除非当前分支,需要切换到其它分支删除本分支)。

  

  4、本地的功能开发开发,分支合并,冲突解决以及提交

  两个用户同时检出dev分支,并以此为基础分别在本地新建分支feature1_branch,feature2_branch,项目有两个java文件,内容分别为:

package test.gittest;
public class A {
public static void main(String[] args){
System.out.println("aaaaaaaaaaaaa");
System.out.println("aaaaaaaaaaaaa");
System.out.println("aaaaaaaaaaaaa");
System.out.println("aaaaaaaaaaaaa");
}
} 
package test.gittest;
public class App {
public static void main( String[] args ){
System.out.println( "Hello World!" );
}
}

  假设feature1_branch只改动了A.java,改动后内容如下(修改,新增各一行): 

package test.gittest;
public class A {
public static void main(String[] args){
System.out.println("aaaaaaaaaaaaa");
System.out.println("aaaaaaaaaaaaa");
System.out.println("aaaaaaaaaaaaa");
System.out.println("aaaaaaaaaaaaa_feature1_branch修改");
System.out.println("feature1_branch新增");
}
}

  feature1_branch在本分支本地提交,然后切换到dev分支,然后项目右键---->team---->merge,选择feature1_branch,可直接将代码merge到dev分支。然后项目右键team---->synchronize workspace进行本地跟中央库代码同步,双击,可以看到本地文件跟中央库文件的差别:

  

  没有冲突,点击上方的push图标,可以将本地修改push到远程仓库,或者项目右键---->team---->commit,选择commit and push推送远程。

  Feature2_branch改动A.java跟App.java如下:

package test.gittest;
public class A {
public static void main(String[] args){
System.out.println("aaaaaaaaaaaaa");
System.out.println("aaaaaaaaaaaaa");
System.out.println("aaaaaaaaaaaaa");
System.out.println("aaaaaaaaaaaaa_feature2_branch修改");
System.out.println("feature2_branch新增");
}
}
package test.gittest;
public class App {
public static void main( String[] args ){
System.out.println( "Hello World!" );
System.out.println("feature2_branch新增2");
}
}

  同feature1_branch,右键跟中央库进行同步对比,结果如下:

  问题出现了,有冲突!

  1、错误做法,错误做法,错误做法:先merge后synchronize

  类似于svn的做法,直接在本页面进行合并,并提交。找到feature1_branch的开发人员,沟通后合并代码,假设沟通后决定此例中第7行代码应该为System.out.println("aaaaaaaaaaaaa_feature1_branch修改_feature2_branch修改");第8行两者均需保留,则可以直接在此页面的左侧完成此修改,并直接右键commit and push或者直接点上方的push按钮推送到中央服务器。这种做法极不推荐,可以认为这种操作时不对的。这会覆盖掉服务器的上次提交,虽然本地代码提交了,服务器的代码也是正常的,但会导致他人更新时的一些冲突:feature1_branch的用户pull时报错:

  

  2、 正确做法:先synchronize后merge

  本地feature2_branch开发完成并本地commit后,切换到dev分支,先不要merge新的feature2_branch的内容到dev分支,先将dev跟远程synchronize一下看是否有差别,若有,进行pull,然后再把feature2_branch的改动merge进去。(同样,feature1_branchmerge前同样应该先synchronize)

  注意:在merge页面,merge options选择第三个,否则无法填写提交的备注信息。

  

  由于feature1_branch的内容先提交到dev分支,因此要先pull一下,再merge本地的feature2_branch,merge后会有冲突,提示如下:

  

  这时候右键---->team---->merge tools由灰色变成了亮色,点击merge tools进行合并:

  

  merge tools 提供的图形界面,可以比较方便的进行对比并修改代码,这是egit比git bash等命令行为数不多的优点之一。

  合并完后,右键文件---->add index---->项目右键---->team---->commit。不点add to index,不会纳入git管理,提交的时候列表中看不到这个文件。

  这种方式的提交,他人在更新代码的时候不会有冲突,会直接pull到正常的代码,无需本地合并。

  这个地方,跟svn的使用习惯略有不同(个人感觉是这样,不知大家怎么用svn),svn是synchronize,然后可以直接在synchronize这个视图进行代码合并,合并完成后把有冲突的标记为合并,然后就可以commit了,egit的话,经过尝试,这么搞不可以,它的synchronize视图功能比较弱,我们只是用来看一下是否有更新,有的话pull下来,然后本地merge即可,剩下的跟synchronize视图无关了。

  注意:1、提交后如果所建的分支feature1_branch,feature2_branch无用,最好删掉分支,保持服务分支的整洁。

       2、git提供了丰富的操作命令,我们也可以通过在命令行完成以上操作,且更加便捷(只有merge冲突的时候不够直观),但相对命令较多,不利于新手使用。建议可以采用gui跟命令相结合的方式来学习使用git;intellij idea也自带了git插件,并同时支持命令行操作(eclipse只能自己打开文件夹然后使用命令行操作),想要尝试的可以试一下。

git如何使用的更多相关文章

  1. Git 子模块 - submodule

    有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目. 也许是第三方库,或者你 独立开发的,用于多个父项目的库. 现在问题来了:你想要把它们当做两个独立的项目,同时又想在 一个项目中使用另 ...

  2. Git 在团队中的最佳实践--如何正确使用Git Flow

    我们已经从SVN 切换到Git很多年了,现在几乎所有的项目都在使用Github管理, 本篇文章讲一下为什么使用Git, 以及如何在团队中正确使用. Git的优点 Git的优点很多,但是这里只列出我认为 ...

  3. Git与Repo入门

    版本控制 版本控制是什么已不用在说了,就是记录我们对文件.目录或工程等的修改历史,方便查看更改历史,备份以便恢复以前的版本,多人协作... 一.原始版本控制 最原始的版本控制是纯手工的版本控制:修改文 ...

  4. Git Bash的一些命令和配置

    查看git版本号: git --version 如果是第一次使用Git,你需要设置署名和邮箱: $ git config --global user.name "用户名" $ gi ...

  5. 在Ubuntu 16.10 安装 git 并上传代码至 git.oschina.net

    1. 注册一个账号和创建项目 先在git.oschina.net上注册一个账号和新建一个project ,如project name 是"myTest". 2.安装git sudo ...

  6. 史上最详细git教程

    题外话 虽然这个标题很惊悚,不过还是把你骗进来了,哈哈-各位看官不要着急,耐心往下看 Git是什么 Git是目前世界上最先进的分布式版本控制系统. SVN与Git的最主要的区别 SVN是集中式版本控制 ...

  7. [版本控制之道] Git 常用的命令总结(欢迎收藏备用)

    坚持每天学习,坚持每天复习,技术永远学不完,自己永远要前进 总结日常开发生产中常用的Git版本控制命令 ------------------------------main-------------- ...

  8. 【解决方案】Myeclipse 10 安装 GIT 插件 集成 步骤 图解

    工程开发中,往往要使用到集成GIT ,那么下面说说插件安装步骤 PS:以Myeclipse 10 为例,讲解集成安装步骤. ----------------------main------------ ...

  9. git 命令

    切换仓库地址: git remote set-url origin xxx.git切换分支:git checkout name撤销修改:git checkout -- file删除文件:git rm  ...

  10. git亲测命令

    一.Git新建本地分支与远程分支关联问题 git checkout -b branch_name origin/branch_name 或者 git branch --set-upstream bra ...

随机推荐

  1. Python 利用循环画散点图

    import pandas as pd data = pd.read_csv('D:/suning/iris.csv') data = data.iloc[:,1:] ###2维散点图 import ...

  2. 公有云Docker镜像P2P加速之路:安全篇

    一.问题 在使用Docker运行容器化应用时,宿主机通常先要从Registry服务(如Docker Hub)下载相应的镜像(image).这种镜像机制在开发环境中使用还是很有效的,团队成员之间可以很方 ...

  3. Docker部署MySql应用

    1. MySQL部署 1.1拉取MySQL镜像 docker pull mysql 查看镜像 docker images 1.2创建MySQL容器 docker run -di --name piny ...

  4. 数据结构1:数据结构与算法C语言版分析概述

    本节开始将带领大家系统地学习数据结构,作为一门计算机专业大二学生的必修课程,该课程面对的目标人群为初步具备基本编程能力和编程思想的程序员(大一接触了 C 语言或者 C++).通过系统地学习数据结构,可 ...

  5. C++基础学习8:类的定义(class)

    先来说说C和C++中结构体的不同 a) C语言中的结构体不能为空,否则会报错(??) b) C语言中内存为空结构体分配大小为0,C++中为结构体和类分配大小为1byte c) C语言中的结构体只涉及到 ...

  6. CF581D Three Logos 暴力

    Three companies decided to order a billboard with pictures of their logos. A billboard is a big squa ...

  7. 字串变换 bfs + 字符串

    题目描述 已知有两个字串A,BA,BA,B及一组字串变换的规则(至多666个规则): A1A_1A1​ ->B1 B_1B1​ A2A_2A2​ -> B2B_2B2​ 规则的含义为:在 ...

  8. Java内存区域与内存溢出异常---对象的创建

    对象的创建   在语言层面,创建一个对象通常仅仅是一个new关键字而已.在虚拟机层面,虚拟机遇到一个new指令时,首先回去检查这个指令的参数是能在常量池中定位到一个类的符号引用,并检查这个符号引用代表 ...

  9. 【笔记】Django基础(一)

    ---恢复内容开始--- [笔记]Django基础(一) oldboy Django  一 关于Python框架的本质 1. HTTP协议消息的格式: 请求(request) 请求方法 路径 HTTP ...

  10. P1415 拆分数列

    传送门 DP数列长度过大无法枚举,考虑DP设f1[i]储存以第i个字符为结尾时,的最后一个数最小时,这个数的开头的位置(很难想有木有)OK,状态有了,方程想一想就出来了:设$num[i][j]$为数列 ...