数据API 案例 开发者 关于
掌握聚合最新动态了解行业最新趋势
API接口,开发服务,免费咨询服务
新闻动态 > 媒体报道

通过对比更好的了解Git

Git已经成为我们日常接触最多的工具,借助日常Git使用经验积累和Google搜索想必大家对它了如指掌了吧,然而事实真的是如此吗?

为什么会出现这种现象呢?网上大多数资料是操作过程以及如何使用的范例,极少会深入分析其原理过程。这里我就跟大家图解分析一下几个常用命令的原理,并且通过对比更容易的理解什么样的场景对应什么命令。

  • Merge vs Rebase and 合并多个commit

  • Git的版本回退:revert vs reset

  • Comparing Workflow

  • 附录

    I. 关于GIT的一些经验

    II. GIT的版本控制

    III. 常见错误

1Merge vs Rebase and 合并多个commit

先来说下Merge和Rebase这两条最最常用的命令吧;

我们合并分支经常会用到merge,其实rebase能达到殊途同归的作用;

话不多说,这里直接上图分析一下两者有何不同。

场景:

Featrue是我们创建的一个分支开发功能,现在另外一个人在master上添加了两个提交;

为了将master上新增的这两个提交并入Feature分支,我们可以选择merge or rebase;

merge

git checkout feature

git mergemaster 

另外也可以用一条命令表示

git merge master feature

Feature所在点就是新的合并提交;

每次merge合并更改后feature会产生一个合并提交历史,如果merge很多整个分支的提交历史看起来不怎么清晰干净,不容易理解。

rebase

git checkout feature 

git rebase master 

539-640.jpg.jpg

rebase执行的操作相当于先回到Fork之前的共同commits点(也就是白色共同的区域),再根据featrue之后提交绿色点的commits,在master分支的最后提交添加绿色点的commits,生成新的Feature分支。

说完对比了,趁热打铁我们再说下rebase的更重要的一个功能,这就是交互式的rebase;

交互式的rebase解决了一个开发非常头痛的问题,每次功能分支开发完,有时会产生很多的commit,如果一个个合并到主干上,不仅混乱而且不容易revert回退;此时rebase命令可以帮助开发合并这些commit,使得提交历史一目了然,更容易理解;

(注:发起pull request之前,合并commit,可以保证主要分支commit提交历史清晰。)

这里可以使用git rebase命令 

git rebase -i 

以下是具体的一个实例——合并多个commit场景

开发分支dev2

540-640.jpg.jpg

现在我们要把dev2分支的最后三条commit合并,执行

git checkout dev2

git rebase -i HEAD~3

通过指定HEAD~3作为新的提交,并没有做分支的操作,只是把最后的3次commit提交重写。

紧接着我们进入互动界面

541-640.jpg.jpg

此时会列出了dev2分支的最新的3个commit,排列顺序是越下面越新,默认是pick操作命令。

往下就是命令的注释了,这里详细说明一下各个命令注释:

    •      p,pick 选中使用的commit

    •      r,reword 选中使用该commit,并且修改commit提交信息;

    •      e,edit 选择,rebase时暂停,,允许修改该commit

    •      s,squash 选中,该commit会合并到前一个commit中,并且保留该commit的提交信息

    •      f,fixup  与squash一样,但是不会保留该commit的提交信息

    •      x,exec 执行shell命令

    •      d,drop  去除该commit

我们这里默认把最新的两个commit合并到第一个里面,然后保留提交信息,把最新的两个commit的操作命令修改为squash。

(如果不需要最新的一个commit提交信息,可以修改其操作命令为fixup即可。)

542-640.jpg.jpg

保存后会显示出这三个commit合并后的详细信息,确认没问题了保存退出即可;

543-640.jpg.jpg

以上显示合并后的commit历史注释以及文件的改变信息;

好了,我们wq保存退出;

544-640.jpg.jpg

Successfully rebased and updated dev2

提示rebase成功;

查看一下git log,可以看到最新的一条commit包含了之前三个的commit提交信息;大功告成。

545-640.jpg.jpg

到了最后一步,我们推送到远程仓库;

这里需要使用--force排除有可能与远程分支不兼容的情况;

git push --force origin dev2

提交commit信息之后,有时会发现跟预期的效果不一样,想要回退到之前的状态,这时我们就可以搬出Git的另外两个常用命令,这就是revert和reset。

2Git的版本回退:revert vs reset

经常有这种情况发生,一个cherry-pick做好之后测试不通过需要回滚,这时就会用到  reset  revert命令了;现在通过例子对比一下这两条命令。

reset

在提交的时候,reset将该分支的HEAD从末端往前移动,用来移除当前分支的某些提交;直接删除指定的commit;

 git checkout hotfix

git reset HEAD~2

546-640.jpg.jpg

hotfix分支最后两个提交会被扔掉,也就是下次提交的时候,Hotfix的最新的两个提交会从分支提交历史中删除;

另外reset还有两种实用的方法:

git reset —mixed HEAD

将你当前的改动从缓存区中移除,但是改动仍然留在工作目录;

git reset —-hard HEAD

完全舍弃你没有提交的改动。

revert

revert撤销一个提交会创建一个新的提交,版本会递增,这样做提交历史就会比较干净容易处理;

547-640.jpg.jpg

git checkout hotfix

git revert HEAD~2

547-640.jpg.jpg

549-640.jpg.jpg

git revert 不会改变已有的提交历史,git revert更加安全,更适合用在公共分支上; 

git reset会直接删除指定的commit,把HEAD指向移动,更适合私有分支 ;

git revert 撤销已经提交的更改,git reset HEAD可以用于撤销没有提交的更改;

目前针对项目进行的撤销我们一般使用revert命令进行;

既然讲到撤销,这里就不得不说下revert撤销时用法:

命令                        作用

git revert HEAD      撤销前一个commit

git revert HEAD^    撤销前前一次commit

git revert HEAD~3  撤销最新的三个commit,把状态HEAD指向第四个commit,并创建一个新的commit提交记录

git revert commit    撤销指定的commit提交,撤销并创建一个新的commit提交记录

这里简单的说一个撤销的实例:

场景:

开发分支dev2,需要在开发分支上撤销最新的一个commit

550-640.jpg.jpg

使用git log查看最新的一个提交历史,接下来我们撤销最新的这个 f3a08e0

git revert HEAD

551-640.jpg.jpg

界面会显示出  Revert + 最新的commit提交历史的注释信息以及该commit带来的文件改变;

没有问题后我们wq保存一下;

552-640.jpg.jpg

显示出撤销带来的最新的commit提交历史, 然后是改变的文件状态;

现在撤销生效了,我们git log确认一下提交历史,如果无误开发分支会生成一个新的提交历史记录信息;

553-640.jpg.jpg

这里最新的一个commit会显示出撤销所创建的提交历史,下面即是撤销前最新的一条commit;你也可以这样理解,最新的一条是+1,撤销创建的是-1,加起来相当于这两个commit对该分支没有任何作用;

接下来git push origin dev2即可。  

3Comparing Workflows

说完了Git的命令,接下来说下Git分支的工作流程,我们使用的Git工作流程大致可以分为三类,即是Git flow,Githubflow以及Gitlab flow,结合自己的使用经验本来打算写,但是网络上已经出现了针对这三种工作流程作出的详细文章,所以就不再讲解,如有兴趣可以看一下两篇即可;这里针对这三种不同的工作流程做一下简要对比:

Git的工作流程 http://www.ruanyifeng.com/blog/2015/12/git-workflow.html

Asuccessful Git branching model 

开源中国社区翻译中文版地址 http://www.oschina.net/translate/a-successful-git-branching-model 


Git flow

Github flow

Gitlab flow

主要分支

master develop

master

master

版本周期

时间较长

时间短,可持续发布

稳定版本周期性发布

优点

多分支类型,主分支和开发分支并列,功能分支补丁分支预发布分支;分支类型细化清晰

持续发布的优势,单分支简单维护

持续发布和版本发布两种开发流程,分支结构明确,持续发布性不错

缺点

同时维护两个分支比较复杂,持续发布性较差

只有单分支,版本发布时间比较固定

大型项目分支比较吃力

由于工作中很多时间都在跟Git打交道,这里也来总结一下经常遇见的错误和Git的一些使用经验,希望对大家有用。

4附录

I. 关于GIT的一些经验

(i) push.default 设置为simple模式

git的全局配置有一个push.default属性,决定了push操作的默认行为;在Git 2.0之前,这个属性默认是’matching’,2.0以后修改为了’simple’

通过git config —global push.default ‘option'设置默认行为

push.default有以下可选值:

nothing,current,upstream,simple,matching

这里就说明一下最常用的simple和matching

    •      simple  simple必须保证本地分支和远程upstream分支同名,否则拒绝push操作

    •      matching push所有本地和远程两端都存在的同名分支.(相比simple不安全)

(ii) 本地开发尽量使用gitfetch,不要使用gitpull,gitfetch获取更新后,手动进行merge

git pull= git fetch +merge

git  pull从远程获取最新版本到本地merge到本地仓库;而fetch无疑更加安全,从远程获取版本后,手动执行进行合并;

(iii) merge节点

Git有两种形式的合并,fast forward 和none fast-forward;

前者不生成单独的合并节点,后者会生成单独节点;

前者不利于保持commit提交信息,不利于回滚;建议采用后者,发生合并产生一个单独的合并节点。

(iv) Squash多个commit

为了方便cherry-pick或回撤代码的提交变化,发起pull request之前,把多个commit合并成一个;开发发出来的cherry-pick的commit有些甚至多达七八个,

这样处理既让分支提交信息混乱不清晰,而且不利于回撤;使用rebase手动处理-具体方法已在文章开头作详细介绍;

GIT的版本控制

(i) 经常性提交 

这样使得你得提交更小,相比团队其他人更容易整合更新,避免merge到主分支的冲突;如果极少的提交更新,单个更新会变得更大,别人合并冲突也不好解决

(ii) 不要进行未完成的功能提交

当代码的逻辑块完成后尽早提交和经常提交,临时需要提交的可以考虑Git的Stash功能暂时提交。

III. 常见错误

(i) 冲突处理

手动解决冲突

554-640.jpg.jpg

冲突符号<<<<<<<HEAD 与 =======之间的内容和  =======与>>>>>>> 6853e5ff9之间的内容产生冲突,只需要保留正确的内容并且去除冲突标识行即可;

(ii) 帐号问题不能执行git操作

情景一:

git操作执行返回 

fatal:Authentication failed for ……

这种情况下一般是因为之前的操作帐号认证有问题,或者是帐号连接不上,即使帐号没问题后,依然会如此报错,这时你需要重新设置下个人帐号信息。

解决:

git config —global user.name “xxx”

git config —global user.email “xxx@xxx.com"

情景二:

在做git pull 或git  push时传输文件比较大的时候,容易出现:

error: RPC failed; result=22, HTTP code = 413 

fatal: The remote end hung up unexpectedly 

fatal: The remote end hung up unexpectedly

Everything up-to-date

解决:

git config http.postBuffer 524288000

情景三:

如果The  requested URL returned error:400,极有可能是DNS问题,请查看自己的网络DNS确定正确,一般即可解决。

文章中有不足或任何问题,欢迎交流,谢谢!



原文来自:点融黑帮

掌握聚合最新动态了解行业最新趋势
API接口,开发服务,免费咨询服务
新闻动态 > 媒体报道
通过对比更好的了解Git
发布:2017-08-25

Git已经成为我们日常接触最多的工具,借助日常Git使用经验积累和Google搜索想必大家对它了如指掌了吧,然而事实真的是如此吗?

为什么会出现这种现象呢?网上大多数资料是操作过程以及如何使用的范例,极少会深入分析其原理过程。这里我就跟大家图解分析一下几个常用命令的原理,并且通过对比更容易的理解什么样的场景对应什么命令。

  • Merge vs Rebase and 合并多个commit

  • Git的版本回退:revert vs reset

  • Comparing Workflow

  • 附录

    I. 关于GIT的一些经验

    II. GIT的版本控制

    III. 常见错误

1Merge vs Rebase and 合并多个commit

先来说下Merge和Rebase这两条最最常用的命令吧;

我们合并分支经常会用到merge,其实rebase能达到殊途同归的作用;

话不多说,这里直接上图分析一下两者有何不同。

场景:

Featrue是我们创建的一个分支开发功能,现在另外一个人在master上添加了两个提交;

为了将master上新增的这两个提交并入Feature分支,我们可以选择merge or rebase;

merge

git checkout feature

git mergemaster 

另外也可以用一条命令表示

git merge master feature

Feature所在点就是新的合并提交;

每次merge合并更改后feature会产生一个合并提交历史,如果merge很多整个分支的提交历史看起来不怎么清晰干净,不容易理解。

rebase

git checkout feature 

git rebase master 

539-640.jpg.jpg

rebase执行的操作相当于先回到Fork之前的共同commits点(也就是白色共同的区域),再根据featrue之后提交绿色点的commits,在master分支的最后提交添加绿色点的commits,生成新的Feature分支。

说完对比了,趁热打铁我们再说下rebase的更重要的一个功能,这就是交互式的rebase;

交互式的rebase解决了一个开发非常头痛的问题,每次功能分支开发完,有时会产生很多的commit,如果一个个合并到主干上,不仅混乱而且不容易revert回退;此时rebase命令可以帮助开发合并这些commit,使得提交历史一目了然,更容易理解;

(注:发起pull request之前,合并commit,可以保证主要分支commit提交历史清晰。)

这里可以使用git rebase命令 

git rebase -i 

以下是具体的一个实例——合并多个commit场景

开发分支dev2

540-640.jpg.jpg

现在我们要把dev2分支的最后三条commit合并,执行

git checkout dev2

git rebase -i HEAD~3

通过指定HEAD~3作为新的提交,并没有做分支的操作,只是把最后的3次commit提交重写。

紧接着我们进入互动界面

541-640.jpg.jpg

此时会列出了dev2分支的最新的3个commit,排列顺序是越下面越新,默认是pick操作命令。

往下就是命令的注释了,这里详细说明一下各个命令注释:

    •      p,pick 选中使用的commit

    •      r,reword 选中使用该commit,并且修改commit提交信息;

    •      e,edit 选择,rebase时暂停,,允许修改该commit

    •      s,squash 选中,该commit会合并到前一个commit中,并且保留该commit的提交信息

    •      f,fixup  与squash一样,但是不会保留该commit的提交信息

    •      x,exec 执行shell命令

    •      d,drop  去除该commit

我们这里默认把最新的两个commit合并到第一个里面,然后保留提交信息,把最新的两个commit的操作命令修改为squash。

(如果不需要最新的一个commit提交信息,可以修改其操作命令为fixup即可。)

542-640.jpg.jpg

保存后会显示出这三个commit合并后的详细信息,确认没问题了保存退出即可;

543-640.jpg.jpg

以上显示合并后的commit历史注释以及文件的改变信息;

好了,我们wq保存退出;

544-640.jpg.jpg

Successfully rebased and updated dev2

提示rebase成功;

查看一下git log,可以看到最新的一条commit包含了之前三个的commit提交信息;大功告成。

545-640.jpg.jpg

到了最后一步,我们推送到远程仓库;

这里需要使用--force排除有可能与远程分支不兼容的情况;

git push --force origin dev2

提交commit信息之后,有时会发现跟预期的效果不一样,想要回退到之前的状态,这时我们就可以搬出Git的另外两个常用命令,这就是revert和reset。

2Git的版本回退:revert vs reset

经常有这种情况发生,一个cherry-pick做好之后测试不通过需要回滚,这时就会用到  reset  revert命令了;现在通过例子对比一下这两条命令。

reset

在提交的时候,reset将该分支的HEAD从末端往前移动,用来移除当前分支的某些提交;直接删除指定的commit;

 git checkout hotfix

git reset HEAD~2

546-640.jpg.jpg

hotfix分支最后两个提交会被扔掉,也就是下次提交的时候,Hotfix的最新的两个提交会从分支提交历史中删除;

另外reset还有两种实用的方法:

git reset —mixed HEAD

将你当前的改动从缓存区中移除,但是改动仍然留在工作目录;

git reset —-hard HEAD

完全舍弃你没有提交的改动。

revert

revert撤销一个提交会创建一个新的提交,版本会递增,这样做提交历史就会比较干净容易处理;

547-640.jpg.jpg

git checkout hotfix

git revert HEAD~2

547-640.jpg.jpg

549-640.jpg.jpg

git revert 不会改变已有的提交历史,git revert更加安全,更适合用在公共分支上; 

git reset会直接删除指定的commit,把HEAD指向移动,更适合私有分支 ;

git revert 撤销已经提交的更改,git reset HEAD可以用于撤销没有提交的更改;

目前针对项目进行的撤销我们一般使用revert命令进行;

既然讲到撤销,这里就不得不说下revert撤销时用法:

命令                        作用

git revert HEAD      撤销前一个commit

git revert HEAD^    撤销前前一次commit

git revert HEAD~3  撤销最新的三个commit,把状态HEAD指向第四个commit,并创建一个新的commit提交记录

git revert commit    撤销指定的commit提交,撤销并创建一个新的commit提交记录

这里简单的说一个撤销的实例:

场景:

开发分支dev2,需要在开发分支上撤销最新的一个commit

550-640.jpg.jpg

使用git log查看最新的一个提交历史,接下来我们撤销最新的这个 f3a08e0

git revert HEAD

551-640.jpg.jpg

界面会显示出  Revert + 最新的commit提交历史的注释信息以及该commit带来的文件改变;

没有问题后我们wq保存一下;

552-640.jpg.jpg

显示出撤销带来的最新的commit提交历史, 然后是改变的文件状态;

现在撤销生效了,我们git log确认一下提交历史,如果无误开发分支会生成一个新的提交历史记录信息;

553-640.jpg.jpg

这里最新的一个commit会显示出撤销所创建的提交历史,下面即是撤销前最新的一条commit;你也可以这样理解,最新的一条是+1,撤销创建的是-1,加起来相当于这两个commit对该分支没有任何作用;

接下来git push origin dev2即可。  

3Comparing Workflows

说完了Git的命令,接下来说下Git分支的工作流程,我们使用的Git工作流程大致可以分为三类,即是Git flow,Githubflow以及Gitlab flow,结合自己的使用经验本来打算写,但是网络上已经出现了针对这三种工作流程作出的详细文章,所以就不再讲解,如有兴趣可以看一下两篇即可;这里针对这三种不同的工作流程做一下简要对比:

Git的工作流程 http://www.ruanyifeng.com/blog/2015/12/git-workflow.html

Asuccessful Git branching model 

开源中国社区翻译中文版地址 http://www.oschina.net/translate/a-successful-git-branching-model 


Git flow

Github flow

Gitlab flow

主要分支

master develop

master

master

版本周期

时间较长

时间短,可持续发布

稳定版本周期性发布

优点

多分支类型,主分支和开发分支并列,功能分支补丁分支预发布分支;分支类型细化清晰

持续发布的优势,单分支简单维护

持续发布和版本发布两种开发流程,分支结构明确,持续发布性不错

缺点

同时维护两个分支比较复杂,持续发布性较差

只有单分支,版本发布时间比较固定

大型项目分支比较吃力

由于工作中很多时间都在跟Git打交道,这里也来总结一下经常遇见的错误和Git的一些使用经验,希望对大家有用。

4附录

I. 关于GIT的一些经验

(i) push.default 设置为simple模式

git的全局配置有一个push.default属性,决定了push操作的默认行为;在Git 2.0之前,这个属性默认是’matching’,2.0以后修改为了’simple’

通过git config —global push.default ‘option'设置默认行为

push.default有以下可选值:

nothing,current,upstream,simple,matching

这里就说明一下最常用的simple和matching

    •      simple  simple必须保证本地分支和远程upstream分支同名,否则拒绝push操作

    •      matching push所有本地和远程两端都存在的同名分支.(相比simple不安全)

(ii) 本地开发尽量使用gitfetch,不要使用gitpull,gitfetch获取更新后,手动进行merge

git pull= git fetch +merge

git  pull从远程获取最新版本到本地merge到本地仓库;而fetch无疑更加安全,从远程获取版本后,手动执行进行合并;

(iii) merge节点

Git有两种形式的合并,fast forward 和none fast-forward;

前者不生成单独的合并节点,后者会生成单独节点;

前者不利于保持commit提交信息,不利于回滚;建议采用后者,发生合并产生一个单独的合并节点。

(iv) Squash多个commit

为了方便cherry-pick或回撤代码的提交变化,发起pull request之前,把多个commit合并成一个;开发发出来的cherry-pick的commit有些甚至多达七八个,

这样处理既让分支提交信息混乱不清晰,而且不利于回撤;使用rebase手动处理-具体方法已在文章开头作详细介绍;

GIT的版本控制

(i) 经常性提交 

这样使得你得提交更小,相比团队其他人更容易整合更新,避免merge到主分支的冲突;如果极少的提交更新,单个更新会变得更大,别人合并冲突也不好解决

(ii) 不要进行未完成的功能提交

当代码的逻辑块完成后尽早提交和经常提交,临时需要提交的可以考虑Git的Stash功能暂时提交。

III. 常见错误

(i) 冲突处理

手动解决冲突

554-640.jpg.jpg

冲突符号<<<<<<<HEAD 与 =======之间的内容和  =======与>>>>>>> 6853e5ff9之间的内容产生冲突,只需要保留正确的内容并且去除冲突标识行即可;

(ii) 帐号问题不能执行git操作

情景一:

git操作执行返回 

fatal:Authentication failed for ……

这种情况下一般是因为之前的操作帐号认证有问题,或者是帐号连接不上,即使帐号没问题后,依然会如此报错,这时你需要重新设置下个人帐号信息。

解决:

git config —global user.name “xxx”

git config —global user.email “xxx@xxx.com"

情景二:

在做git pull 或git  push时传输文件比较大的时候,容易出现:

error: RPC failed; result=22, HTTP code = 413 

fatal: The remote end hung up unexpectedly 

fatal: The remote end hung up unexpectedly

Everything up-to-date

解决:

git config http.postBuffer 524288000

情景三:

如果The  requested URL returned error:400,极有可能是DNS问题,请查看自己的网络DNS确定正确,一般即可解决。

文章中有不足或任何问题,欢迎交流,谢谢!



原文来自:点融黑帮

电话 0512-88869195
数 据 驱 动 未 来
Data Drives The Future