why?

为什么要写一篇这样的文章?

  • 团队开发中是选择rebase还是merge?
  • rebase/merge两者之间究竟有何不同?
  • git log的点线图如何理解?
  • git log 常见的命令选择?
  • 如何从Gitlog中查找凶手?

以上就是本文需要简单介绍的内容。
我会从一个最简单的示例开始演进团队开发的全部过程,虽不尽详细但是可以窥见一个大致的过程。

本地操作记录

创建Git和master并且初次提交(master-first-commit)

➜ GitGraph git:(branch01) /Users/zhuge/Desktop/GitGraph 
➜ GitGraph git init
Initialized empty Git repository in /Users/zhuge/Desktop/GitGraph/.git/
➜ GitGraph git:(master) touch master 
➜ GitGraph git:(master) ✗ git add .
➜ GitGraph git:(master) ✗ gcam 'master-first-commit'
[master (root-commit) facfb68] master-first-commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 master

创建br1和br2, 并且br1初次提交(br1-first-commit)

➜ GitGraph git:(master) gb br1
➜ GitGraph git:(master) gb br2
➜ GitGraph git:(master) gco br1
Switched to branch 'br1'
➜ GitGraph git:(br1) touch br1
➜ GitGraph git:(br1) ✗ git add .
➜ GitGraph git:(br1) ✗ gcam 'br1-first-commit'
[br1 00b2a4c] br1-first-commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 br1

master前进,第2次提交(master-second-commit)

➜ GitGraph git:(br1) gco master
Switched to branch 'master'
➜ GitGraph git:(master) touch master2
➜ GitGraph git:(master) ✗ git add .
➜ GitGraph git:(master) ✗ gcam 'master-second-commit'
[master d5c36b0] master-second-commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 master2

br2初次提交(br2-first-commit)

➜ GitGraph git:(master) gco br2
Switched to branch 'br2'
➜ GitGraph git:(br2) touch br2
➜ GitGraph git:(br2) ✗ git add .
➜ GitGraph git:(br2) ✗ gcam 'br2-first-commit'
[br2 b3ebbd7] br2-first-commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 br2
➜ GitGraph git:(br2) 

br1 merge master

➜ GitGraph git:(br2) gco br1
Switched to branch 'br1'
➜ GitGraph git:(br1) git merge master
Merge made by the 'recursive' strategy.
 master2 | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 master2

br2 rebase master

➜ GitGraph git:(br2) gco master
Switched to branch 'master'
➜ GitGraph git:(master) touch m3
➜ GitGraph git:(master) ✗ git add .
➜ GitGraph git:(master) ✗ gcam 'master-third-commit'
[master 763f88e] master-third-commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 m3
➜ GitGraph git:(master) gco br2
Switched to branch 'br2'
➜ GitGraph git:(br2) git rebase master
First, rewinding head to replay your work on top of it...
Applying: br2-first-commit
➜ GitGraph git:(br2) 

git 开发简单流程

  1. 主干master稳定
  2. 切出feature分支br1, br2
  3. br1,br2独立前进:commit
  4. master合稳定功能,前进: master-second-commit
  5. br1合入master代码:rebase方式
  6. br2合入master代码:merge
  7. br1,br2前进:commit
  8. br1, br2稳定准备合入master
  9. master merge br1/br2
  10. 功能完毕,回到第2步骤循环往复,不断迭代bug

git log常见命令

演示中操作在zsh (Oh My Zsh is a delightful, open source, community-driven framework for managing your Zsh configuration. https://ohmyz.sh/) 中进行,为了方便查看并没有使用git flow。

  • glol
  • git log –graph –decorate –oneline –simplify-by-decoration –all
  • git log –graph

br2 git log点线图

为什么先看br2呢?因为rebase相比于merge使用更少一些尤其在小团队开发中。先来看这个陌生人吧!

  • glol
    ➜ GitGraph git:(br2) glol
    1. 只看commit前部可以看见只有4个*,并且没有合入迹象。
    2. 看具体信息:首先时间上即使master-third-commit操作在br2-first-commit前,但是rebase之后时间也是在其之后。
    3. 因为rebase本身操作就是将切入点后的所有提交全部取出,将master后面的commit全部patch到master上,这一步是不会产生冲突的。这之后会将取出的commits重新按照顺序patch上去,此时可能会产生冲突。
    4. 基于此最终的log就是按照顺序的一个综合结果
      看log info可以发现master的提交都是顺序的, 此时head指向了br2
* 62765a6 - (HEAD -> br2) br2-first-commit (43 seconds ago) <zhuge>
* 763f88e - (master) master-third-commit (52 seconds ago) <zhuge>
* d5c36b0 - master-second-commit (11 minutes ago) <zhuge>
* facfb68 - master-first-commit (12 minutes ago) <zhuge>
  • git log –graph
    相对比glol显示了更多的信息。
    ➜ GitGraph git:(br2) git log --graph
* commit 62765a62d67b0fb3955ff30e86cdf255b1c751c3 (HEAD -> br2)
| Author: zhuge <zhuge@bilibili.com>
| Date:   Fri Sep 7 11:27:38 2018 +0800
| 
|     br2-first-commit
| 
* commit 763f88e6737a1dad5498cd8601077068590282f1 (master)
| Author: zhuge <zhuge@bilibili.com>
| Date:   Fri Sep 7 11:36:48 2018 +0800
| 
|     master-third-commit
| 
* commit d5c36b01b8f701b89ba3ab0619f2d13d659268e2
| Author: zhuge <zhuge@bilibili.com>
| Date:   Fri Sep 7 11:26:40 2018 +0800
| 
|     master-second-commit
| 
* commit facfb683c432f7497be0faf73f570342c7eea1c6
  Author: zhuge <zhuge@bilibili.com>
  Date:   Fri Sep 7 11:25:14 2018 +0800

      master-first-commit
  • git log –graph –decorate –oneline –simplify-by-decoration –all
    ➜ GitGraph git:(br2) git log --graph --decorate --oneline --simplify-by-decoration --all
    参数解释:
--decorate: 标记会让git log显示每个commit的引用
--oneline: 一行显示
--simplify-by-decoration:只显示被branch或tag引用的commit
--all: 所有分支

全参数

* 62765a6 (HEAD -> br2) br2-first-commit
* 763f88e (master) master-third-commit
| * e320d7c (br1) Merge branch 'master' into br1
|/  
* facfb68 master-first-commit
(END)

你也可以尝试调整参数的增减,目前我个人最喜欢的选择如下:
➜ GitGraph git:(br2) git log --graph --decorate --oneline --all
这里写图片描述
如上图所示:
符号解释:

*表示一个commit, 注意不要管*在哪一条主线上
|表示分支前进
/表示分叉
\表示合入

过程解释:
1. base master: master first commit
2. |/这个符号表示新分支, 可以看见是新增br1: br1-first-commit
3. master前进:master-second-commit
4. master merged into br1
这里写图片描述
5. master前进:master-third-commit
6. br2前进:br2-first-commit(rebase)
7. br2前进:br2-second-commit(rebase【此commit在rebase后提交】)

br1 git log点线图

  • glol
    ➜ GitGraph git:(br1) glol
    这里写图片描述

  • git log –graph
    ➜ GitGraph git:(br1) git log --graph
    可以看见master first commit的base上,叉出分支br1,br1前进first commit,然后master 前进, 最后有一个merge标记并且当前HEAD在br1
    这里写图片描述

rebase vs merge

以下都是个人理解,如有问题请在评论区说明。
1. rebase也叫变基,是指feature功能分支在从主干分支切出来之后,主干和功能分支独立前进几个提交之后。功能分支需要合入最新的主干代码而进行的操作。对br2的rebase操作相当于以下操作:

最新的master
gb br3: 创建分支br3
gco br3: 切入br3
br3 cherry-pick br2-first-commit: br3 cp了br2后面的commit
br3 change name to br2, delete br2
  1. merge操作就没有rebase那么优雅干净了,直接将代码的修改插入。commit log的顺序按照提交先后。
  2. rebase的优势:如果你在一个分支上的提交有20个,而主干因为团队提交了30个commit,此时主干rebase进来的30个commit肯定排在前面。这样比较符合逻辑,因为虽然按照commit的时间,你有部分代码可能会在30个commit中间,但是并不是稳定的代码就是一堆bug,算不上产出。如果是以稳定为优先级,rebase肯定是最佳的。另外 rebase 的话你所有的提交都会在一起,查找起来会非常方便. git log点线图是一条线看起来非常舒服。
  3. rebase的问题:的确会失去一些关于时间上面的信息,例如分支切出的点信息会丢失。
  4. merge的优势:就是保证了时间信息的准确性
  5. merge的问题:引入了一次不必要的history join,git log点线图会非常难看,增加了查看log的成本。

基于以上个人会选择rebase方式如何代码。
另外介绍rebase的另一个操作
git rebase -i commitID
这个命令可以合并几个commit,如果你的commit修改会出现比较零散内容的时候,例如修改bug,合并提交会让log看起来很干净。

master merge feature

➜  GitGraph git:(br1) gco master
Switched to branch 'master'
➜  GitGraph git:(master) git merge br2
Updating 763f88e..0f4e670

这里写图片描述
上图可以看见br2合入之后log依然很是清晰。

这里写图片描述
加入br1的信息之后log就不那么漂亮了,不漂亮就会给找凶手带来难度,尤其是在commit的人和次数变多的时候。

➜  GitGraph git:(master) git merge br1
Merge made by the 'recursive' strategy.

这里写图片描述
上图可以看见merge的br1于master的*线不在一起,有很多分叉信息需要你费尽的查阅。如果你觉得好像还可以的话,请看下面的图:
这里写图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐