Git 工作流的正确打开方式

前言

一直在使用git做版本控制,也一直工作很顺利,直到和别人发生冲突的时候。这才注意到git 工作流并不是那么简单。比如,之前遇到的清理历史。百度到的资料很多,重复性也很多,但实践性操作很少,我很难直接理解其所表达的含义。直接望文生义经常得到错误的结论,只能用时间去检验真理了,不然看到的结果都是似懂非懂,最后还是一团糟。

作者:@Ryan-Miao
本文为作者原创,转载请注明出处:http://www.cnblogs.com/woshimrf/p/git-workflow.html

学习git工作流

1. 最简单的使用,不推荐

1.1.创建仓库

$ pwd
/home/ryan/workspace/l4git-workflow
$ touch readme.md
$ ls
readme.md
$ touch .gitignore
$ git init
初始化空的 Git 仓库于 /home/ryan/workspace/l4git-workflow/.git/
$ touch test.txt
$ git add .
$ git commit -m "init"
[master (根提交) dae77d6] init
 3 files changed, 12 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 readme.md
 create mode 100644 test.txt
$ git remote add origin git@github.com:Ryan-Miao/l4git-workflow.git
$ git push -u origin master
对象计数中: 5, 完成.
Delta compression using up to 4 threads.
压缩对象中: 100% (3/3), 完成.
写入对象中: 100% (5/5), 388 bytes | 0 bytes/s, 完成.
Total 5 (delta 0), reused 0 (delta 0)
To git@github.com:Ryan-Miao/l4git-workflow.git
 * [new branch]      master -> master
分支 master 设置为跟踪来自 origin 的远程分支 master。

1.2. 模拟用户A

git clone git@github.com:Ryan-Miao/l4git-workflow.git
git checkout a
touch a.txt
//write one
//....
$ git add .
$ git commit -m "one"
[a 53ff45e] one
 2 files changed, 34 insertions(+), 2 deletions(-)
 create mode 100644 a.txt

此时,a还没有提交到origin。 git log 如下:

1.3. 模拟用户B

git clone git@github.com:Ryan-Miao/l4git-workflow.git
git checkout b
$ touch b.txt

//write something
//…

$ git add .
$ git commit -m "b write one"
[b 847078e] b write one
 1 file changed, 1 insertion(+)
 create mode 100644 b.txt

//write something
//….
“`
gitadd. git commit -m “b write two”
[b 3f30f41] b write two
1 file changed, 2 insertions(+), 1 deletion(-)


此时,git log如下
![](http://oe20lp6p0.bkt.clouddn.com/blog/2017/git/b-two.png)


## 1.4. 模拟用户A
A和B分别是在本地开发,所以这种顺序是未知的,也许A比B先commit一次,也许B先commit一次。这里的先后是指commit的时间戳。但都是在本地提交的代码。
write something

git add .
git commit -m “a write two”

wirte something

git add .
git commit -m “write three”

A push to server branch `a`

$ git push origin a:a
Total 0 (delta 0), reused 0 (delta 0)
To [email protected]:Ryan-Miao/l4git-workflow.git
* [new branch] a -> a

A created a Pull Request

![](http://oe20lp6p0.bkt.clouddn.com/blog/2017/git/a-push.png)
![](http://oe20lp6p0.bkt.clouddn.com/blog/2017/git/a-pr.png)


## 1.5. 模拟用户C
C review the PR and then merged it.

![](http://oe20lp6p0.bkt.clouddn.com/blog/2017/git/c-merge.png)
此时,github的历史如下:
![](http://oe20lp6p0.bkt.clouddn.com/blog/2017/git/github-a.png)
可以看出,merge的时候多了一次commit,message默认为 `Merge pull request #1 from Ryan-Miao/a...`
现在看起来,只有a一个人的历史记录,还算清楚,a做了3次提交。

## 1.6. 模拟用户B
用户B提交前先pull master,更新最新的代码到本地,防止冲突。

git fetch
git merge origin/master

此时log看起来有点乱。如下:
![](http://oe20lp6p0.bkt.clouddn.com/blog/2017/git/b-merge-master.png)
让人感到混乱的是b原来的历史只有自己的提交,更新了master到本地之后,历史记录被插入了master中的历史。于是,发现原来自己干净的历史被中间插入多次commit。甚至两次merge master的日志显得又长又碍眼。但不管怎么说,B还是要提交的。

于是,B提交到远程分支b:
![](http://oe20lp6p0.bkt.clouddn.com/blog/2017/git/b-push.png)

## 1.7. 模拟用户C
这时候,A完成了feature a,然后提了PR,然后找他人C merge了。而后,B也完成了feature b,提了PR,需要review and merge。 C review之后,approved, 然后D review, D merge。

此时,项目基本走上正规。feature一个一个添加进去,重复之前的工作流程: fetch -》 work -》 commit -》 push -》 PR -》 merged。
然后,项目历史就变成了这样:

![](http://oe20lp6p0.bkt.clouddn.com/blog/2017/git/github-log2.png)

一眼大概看起来还好,每次都能看到提交历史,只要不是message写的特别少,差不多可以理解最近提交的内容。然而,仔细一看,顺序好像不对。目前一共两个feature,但历史却远远超过2个。没关系,保证细粒度更容易体现开发进度。然而,这些历史并不是按照feature的发布顺序,那么,当我想要找到feature a的时候就很难串联起来。如果commit足够多,时间跨度足够大,甚至根本看不出来feature a到底做了哪些修改。

这时候想要使用图形化git 历史工具来帮助理解历史:
![](http://oe20lp6p0.bkt.clouddn.com/blog/2017/git/tu.png)

这里,还好,还勉强能看出走向。但当10个上百个人同时开发的话,线简直不能看了,时间跨度足够大的话,线也看不完。


因此,这种模式,正是我们自己当前采用的模式。差评。这还不算完,后面更大的困难来了。最先发布的feature a出了问题,必须回滚。怎么做到。关于[回滚](http://www.cnblogs.com/woshimrf/p/5702696.html),就是另一个话题了。 但我们应该知道使用`revert`而不是`reset`. 但revert只能回滚指定的commit,或者连续的commit,而且revert不能revert merge操作。这样,想回滚feature a, 我们就要找到a的几次提交的版本号,然后由于不是连续的,分别revert。这会造成复杂到不想处理了。好在github给了方便的东西,PR提供了revert的机会。找到以前的PR。

![](http://oe20lp6p0.bkt.clouddn.com/blog/2017/git/revert.png)

但是,这绝对不是个好操作!



----

# 2. 推荐的工作流程

造成上述现象的原因是因为各自异步编程决定的。因为每个人都可以随时间提交,最后合并起来的时候以提交时间戳来作为序列的依据,就会变成这样。因此,当需要提交的远程服务器的时候,如果能重写下commit的时间为当前时间,然后push到服务端,历史就会序列到最后了。

## 2.1 模拟用户C
C用户新下载代码。

$ git clone [email protected]:Ryan-Miao/l4git-workflow.git c正克隆到 ‘c’…
remote: Counting objects: 28, done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 28 (delta 8), reused 22 (delta 4), pack-reused 0
接收对象中: 100% (28/28), 5.90 KiB | 0 bytes/s, 完成.
处理 delta 中: 100% (8/8), 完成.
检查连接… 完成。

然后编辑,提交

cdc git config user.name “C”
lsa.txtb.txtreadme.mdtest.txt vim c.txt
gitadd. git commit -m “C write one”
[master cf3f757] C write one
1 file changed, 2 insertions(+)
create mode 100644 c.txt




## 2.2 模拟用户D

同时,D也需要开发新feature

gitclonegit@github.com:RyanMiao/l4gitworkflow.gitd

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值