Add links in 3.5.

This commit is contained in:
Zhongyi Tong
2016-02-02 16:16:32 +08:00
parent 0fee9b66b0
commit b1796d1978

View File

@ -6,7 +6,14 @@
多种多样的工作流使得在项目中实施Git时变得难以选择。这份教程提供了一个出发点调查企业团队最常见的Git工作流。
阅读的时候,请记住工作流应该是规范而不是具体的规矩。我们希望向你展示所有工作流,让你融会贯通,因地制宜。
阅读的时候,请记住工作流应该是一种规范而不是金科玉律。我们希望向你展示所有工作流,让你融会贯通,因地制宜。
这份教程讨论了下面四种工作流:
- [中心化的工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#%E4%B8%AD%E5%BF%83%E5%8C%96%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81)
- [基于功能分支的工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#feature%E5%88%86%E6%94%AF%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81)
- [Gitflow工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#gitflow%E5%B7%A5%E4%BD%9C%E6%B5%81)
- [Fork工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#fork%E5%B7%A5%E4%BD%9C%E6%B5%81)
## 中心化的工作流
@ -16,9 +23,9 @@
过渡到分布式分版本控制系统看起来是个可怕的任务,但你 *不必改变你现有的工作流* 来利用Git的优点。你的团队仍然可以用以前SVN的方式开发项目。
过渡到分布式分版本控制系统看起来是个令人恐惧的任务,但你不必为了利用Git的优点而改变你现有的工作流。你的团队仍然可以用以前SVN的方式开发项目。
但是使用Git来驱动你的开发工作流显示出了一些SVN没有的优点。首先它让每个开发者都有了自己 *本地* 的完整项目副本。隔离的环境使得每个开发者的工作独立于项目的其修改——他们可以在自己的本地仓库中添加提交,完全无视上游的开发,直到需要的时候。
然而使用Git来驱动你的开发工作流显示出了一些SVN没有的优点。首先它让每个开发者都有了自己 *本地* 的完整项目副本。隔离的环境使得每个开发者的工作独立于项目的其修改——他们可以在自己的本地仓库中添加提交,完全无视上游的开发,直到需要的时候。
第二它让你接触到了Git鲁棒的分支和合并模型。和SVN不同Git分支被设计为一种故障安全的机制用来在仓库之间整合代码和共享更改。
@ -28,7 +35,7 @@
开发者将中央仓库克隆到本地后开始工作。在他们的本地项目副本中他们可以像SVN一样修改文件和提交更改不过这些新的提交被保存在 *本地* ——它们和中央仓库完全隔离。这使得开发者可以将和上游的同步推迟到他们方便的时候。
为了向官方项目发布修改,开发者将他们的本地`master`分支“推送”到中央仓库。这一等同于`svn commit`,除了它添加了所有不在中央`master`分支上的所有本地提交。
为了向官方项目发布修改,开发者将他们的本地`master`分支“推送”到中央仓库。这一等同于`svn commit`,除了Git添加的是所有不在中央`master`分支上的本地提交。
@ -46,13 +53,13 @@
在开发者发布他们的功能之前他们需要fetch更新的中央提交在它们之上rebase自己的更改。这就像是“我想要在其他人的工作进展之上添加我的修改。”它会导致完美的线性历史就像和传统的SVN工作流一样。
在开发者发布他们的功能之前他们需要fetch更新的中央提交在它们之上rebase自己的更改。这就像是“我想要在其他人的工作进展之上添加我的修改。”它会产生完美的线性历史就像和传统的SVN工作流一样。
如果本地修改和上游提交冲突时Git会暂停rebase流程给你机会手动解决这些冲突。Git很赞的一点是使用同一个`git status``git add`命令来生成提交和解决合并冲突。这使得开发者能够轻而易举地管理他们的合并。另外如果他们改错了什么Git让他们轻易地退出rebase过程然后重试或者找人帮忙
如果本地修改和上游提交冲突时Git会暂停rebase流程给你机会手动解决这些冲突。Git很赞的一点是将[`git status`](https://github.com/geeeeeeeeek/git-recipes/wiki/2.4-%E6%A3%80%E6%9F%A5%E4%BB%93%E5%BA%93%E7%8A%B6%E6%80%81#git-status)和[`git add`](https://github.com/geeeeeeeeek/git-recipes/wiki/2.3-%E4%BF%9D%E5%AD%98%E4%BD%A0%E7%9A%84%E6%9B%B4%E6%94%B9#git-add)命令同时用来生成提交和解决合并冲突。这使得开发者能够轻而易举地管理他们的合并。另外如果他们改错了什么Git让他们轻易地退出rebase过程然后重试或者找人帮忙
## 栗子
让我们一步步观察一个寻常的小团队是如何使用这种工作流协作的。我们有两位开发者John和Mary分别在开发两个功能通过中心化的仓库共享代码。
让我们一步步观察一个普通的小团队是如何使用这种工作流协作的。我们有两位开发者John和Mary分别在开发两个功能他们通过中心化的仓库共享代码。
### 一人初始化了中央仓库
@ -62,7 +69,7 @@
首先,有人需要在服务器上创建中央仓库。如果这是一个新项目你可以初始化一个空的仓库。不然你需要导入一个已经存在的GitSVN项目。
首先,需要有人在服务器上创建中央仓库。如果这是一个新项目你可以初始化一个空的仓库。不然你需要导入一个已经存在的GitSVN项目。
中央仓库应该永远是裸仓库(没有工作目录),可以这样创建:
@ -70,7 +77,7 @@
ssh user@host git init --bare /path/to/repo.git
```
但确保你使用的`user`SSH用户名、服务器`host`的域名或IP地址、储存仓库的地址`/path/to/repo.git`是有效的。注意`.git`约定俗成地出现在仓库名的后面,表明这是一个裸仓库。
但确保你使用的SSH用户名`user`、服务器`host`的域名或IP地址、储存仓库的地址`/path/to/repo.git`是有效的。注意`.git`约定俗成地出现在仓库名的后面,表明这是一个裸仓库。
### 所有人将仓库克隆到本地
@ -82,13 +89,13 @@ ssh user@host git init --bare /path/to/repo.git
接下来,每个开发者在本地创建一份完整项目的副本。使用`git clone`命令:
接下来,每个开发者在本地创建一份完整项目的副本。使用[`git clone`](https://github.com/geeeeeeeeek/git-recipes/wiki/2.2-%E5%88%9B%E5%BB%BA%E4%BB%A3%E7%A0%81%E4%BB%93%E5%BA%93#git-clone)命令:
```
git clone ssh://user@host/path/to/repo.git
```
当你克隆仓库时Git自动添加了一个名为`origind`的远程连接,指向“父”仓库,假设你以后想要和这个仓库交换数据。
当你克隆仓库时Git自动添加了一个名为`origin`的远程连接,指向“父”仓库,以便你以后和这个仓库交换数据。
### John在开发他的功能
@ -101,9 +108,9 @@ git clone ssh://user@host/path/to/repo.git
在他的本地仓库中John可以用标准的Git提交流程开发功能编辑、缓存、提交。如果你对缓存区还不熟悉你也可以不用记录工作目录中每次的变化。于是你创建了一个高度集中的提交即使你已经在本地做了很多修改。
```
git status # View the state of the repo
git add <some-file> # Stage a file
git commit # Commit a file</some-file>
git status # 查看仓库状态
git add <some-file> # 缓存一个文件
git commit # 提交一个文件</some-file>
```
记住这些命令创建的是本地提交John可以周而复始地重复这个过程而不用考虑中央仓库。对于庞大的功能需要切成更简单、原子化的片段时这个特性就很有用。
@ -126,13 +133,13 @@ git commit # Commit a file</some-file>
一旦John完成了他的功能他应该将本地提交发布到中央仓库这样其他项目成员就可以访问了。他可以使用`git push`命令,就像:
一旦John完成了他的功能他应该将本地提交发布到中央仓库这样其他项目成员就可以访问了。他可以使用[`git push`](https://github.com/geeeeeeeeek/git-recipes/wiki/3.2-%E4%BF%9D%E6%8C%81%E5%90%8C%E6%AD%A5#git-push)命令,就像:
```
git push origin master
```
记住,`origin`是John克隆中央仓库时指向它的远程连接。`master`参数告诉Git试着将`origin`的`master`分支变得和他本地的`master`分支一致。因为中央仓库在John克隆之后还没有进展因此这个推送如他所愿没有产生冲突。
记住,`origin`是John克隆中央仓库时指向它的远程连接。`master`参数告诉Git试着将`origin`的`master`分支变得和他本地的`master`分支一样。中央仓库在John克隆之后还没有进展因此这个推送如他所愿没有产生冲突。
### Mary试图发布她的功能
@ -158,7 +165,7 @@ hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
```
Git防止Mary覆盖官方的修改。她需要将John的更新拉取到她的仓库和她的本地修改整合后然后试。
Git防止Mary覆盖官方的修改。她需要将John的更新拉取到她的仓库和她的本地修改整合后然后试。
### Mary在John的提交之上rebase
@ -168,7 +175,7 @@ Git防止Mary覆盖官方的修改。她需要将John的更新拉取到她的仓
Mary可以使用`git pull`来将上游修改并入她的仓库。这个命令和`svn update`很像——它拉取整个上游提交历史到Mary的本地仓库并和她的本地提交一起整合
Mary可以使用[`git pull`](https://github.com/geeeeeeeeek/git-recipes/wiki/3.2-%E4%BF%9D%E6%8C%81%E5%90%8C%E6%AD%A5#git-pull)来将上游修改并入她的仓库。这个命令和`svn update`很像——它拉取整个上游提交历史到Mary的本地仓库并和她的本地提交一起整合
```
git pull --rebase origin master
@ -182,7 +189,7 @@ git pull --rebase origin master
如果你忘了这个选项拉取同样会成功只不过你每次和中央仓库同步时都会多出一个“合并提交”。在这种工作流中rebase和生成一个合并提交总是一个更好的选择。
如果你忽略这个选项拉取同样会成功只不过你每次和中央仓库同步时都会多出一个“合并提交”。在这种工作流中rebase和生成一个合并提交相比,总是一个更好的选择。
### Mary解决了合并冲突
@ -192,7 +199,7 @@ git pull --rebase origin master
Rebase的工作是将每个本地提交一个个转移到更新后的`master`分支。也就是说,你可以可以一个个提交分别解决合并冲突,而不是在一个庞大的合并提交中解决。它会让你的每个提交保持专注,并获得一个干净的项目历史。另一方面你更容易发现bug是在哪引入的如果有必要的话用最小的代价回滚这些修改。
Rebase的工作是将每个本地提交一个个转移到更新后的`master`分支。也就是说你可以一个个提交分别解决合并冲突而不是在一个庞大的合并提交中解决。它会让你的每个提交保持专注并获得一个干净的项目历史。另一方面你更容易发现bug是在哪引入的如果有必要的话用最小的代价回滚这些修改。
如果Mary和John开发的功能没有关联rebase的过程不太可能出现冲突。但如果出现冲突时Git在当前提交会暂停rebase输出下面的信息和一些相关的指令
@ -206,7 +213,7 @@ CONFLICT (content): Merge conflict in <some-file>
Git的优越之处在于 *每个人* 都能解决他们自己的合并冲突。在这个例子中Mary只需运行一下`git status`就可以发现问题是什么。冲突的文件会出现在未合并路径中:
Git的优在于 *每个人* 都能解决他们自己的合并冲突。在这个例子中Mary只需运行一下[`git status`](https://github.com/geeeeeeeeek/git-recipes/wiki/2.4-%E6%A3%80%E6%9F%A5%E4%BB%93%E5%BA%93%E7%8A%B6%E6%80%81#git-status)就可以发现问题是什么。冲突的文件会出现在未合并路径中:
```
# Unmerged paths:
@ -216,7 +223,7 @@ Git的优越之处在于 *每个人* 都能解决他们自己的合并冲突。
# both modified: <some-file>
```
接下来,修改这些文件。如果她对结果满意了,和往常一样缓存这些文件,然后让`git rebase`完成接下来的工作:
接下来,修改这些文件。如果她对结果满意了,和往常一样缓存这些文件,然后让[`git rebase`](https://github.com/geeeeeeeeek/git-recipes/wiki/2.7-%E9%87%8D%E5%86%99%E9%A1%B9%E7%9B%AE%E5%8E%86%E5%8F%B2#git-rebase)完成接下来的工作:
```
git add <some-file>
@ -249,7 +256,7 @@ git push origin master
正如你所见使用一丢丢Git命令来复制一套传统的Subversion开发环境也是可行的。这对于从SVN转变而来的团队来说很棒但这样没有利用到Git分布式的本质。
如果你的团队已经习惯了中心化的工作流但希望提高协作效率那么探索Feature分支工作流的好处是完全值当的。每个功能在专门的独立分支上进行在代码并入官方项目之前就可以启动围绕新修改的深度讨论。
如果你的团队已经习惯了中心化的工作流,但希望提高协作效率,那么探索[Feature分支工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#feature%E5%88%86%E6%94%AF%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81)的好处是完全值当的。每个功能在专门的独立分支上进行,在代码并入官方项目之前就可以启动围绕新修改的深度讨论。
## Feature分支的工作流
@ -259,23 +266,23 @@ git push origin master
一旦你掌握了中心化工作流的使用姿势,在你的开发流程中添加功能分支是一个简单的方式,鼓励协作和促进开发者之间的交流。这种封装使得多个开发者专注自己的功能而不会打扰主代码库。它还保证`master`分支永远不会包含损坏的代码,给持续集成环境带来了是很大的好处。
一旦你掌握了[中心化工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#%E4%B8%AD%E5%BF%83%E5%8C%96%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81)的使用姿势,在你的开发流程中添加功能分支是一个简单的方式,来促进协作和开发者之间的交流。这种封装使得多个开发者专注自己的功能而不会打扰主代码库。它还保证`master`分支永远不会包含损坏的代码,给持续集成环境带来了是很大的好处。
封装功能的开发使得pull request的使用成为可能用来启动围绕一个分支的讨论。它给了其他开发者在功能并入主项目之前参与决策的机会。或者如果你开发功能时卡在一半你可以发起一个pull request向同事寻求建议。重点是pull request使得你的团队在评论其他人的工作时变得非常简单。
封装功能的开发使得[pull request](https://github.com/geeeeeeeeek/git-recipes/wiki/3.3-%E5%88%9B%E5%BB%BAPull-Request)的使用成为可能用来启动围绕一个分支的讨论。它给了其他开发者在功能并入主项目之前参与决策的机会。或者如果你开发功能时卡在一半你可以发起一个pull request向同事寻求建议。重点是pull request使得你的团队在评论其他人的工作时变得非常简单。
## 如何工作
Feature分支工作流同样使用中央仓库`master`同样代表官方的项目历史。但是,与其直接提交在本地的`master`分支开发者每次进行新的工作时创建一个新的分支。Feature分支应该包含描述性的名称比如`animated-menu-items`(菜单项动画)或`issue-#1061`。每个分支都应该有一个清晰、高度集中的目的。
Git在技术上不会区别`master`和功能分支所以开发者可以在feature分支上编辑、缓存、提交就和中心化工作流中一样。
Git在技术上无法区别`master`和功能分支所以开发者可以在feature分支上编辑、缓存、提交就和中心化工作流中一样。
此外feature分支可以也应该被推送到中央仓库。这使得你和其他开发者共享这个功能而又不改变官方代码。既然`master`只是一个“特殊”的分支在中央仓库中储存多个feature分支不会引出什么问题。当然了这也是备份每个开发者本地提交的好办法。
### Pull Request
除了隔离功能开发之外分支使得通过pull request讨论修改成为可能。一旦有人完成了一个功能他们不会立即将它并入`master`。他们feature分支推送到中央服务器上发布一个pull request请求将他们的修改并入`master`。这给了其他开发者在修改并入主代码库之前审查的机会。
除了隔离功能开发之外,分支使得通过[pull request](https://github.com/geeeeeeeeek/git-recipes/wiki/3.3-%E5%88%9B%E5%BB%BAPull-Request)讨论修改成为可能。一旦有人完成了一个功能,他们不会立即将它并入`master`。他们feature分支推送到中央服务器上发布一个pull request请求将他们的修改并入`master`。这给了其他开发者在修改并入主代码库之前审查的机会。
代码审查pull request的主要好处但他们事实上被设计原意是成为讨论代码的一般场所。你可以把pull request看作是专注某个分支的讨论版。也就是说他们可以用于开发流程之前。比如一个开发者在某个功能上需要帮助他只需发起一个pull request。感兴趣的小伙伴会自动收到通知看到相关提交中的问题。
代码审查pull request的主要好处但他们事实上被设计成为讨论代码的一般场所。你可以把pull request看作是专注某个分支的讨论版。也就是说他们可以用于开发流程之前。比如一个开发者在某个功能上需要帮助他只需发起一个pull request。感兴趣的小伙伴会自动收到通知看到相关提交中的问题。
一旦pull request被接受了发布功能的行为和中心化的工作流是一样的。首先确定你本地的`master`和上游的`master`已经同步。然后将feature分支并入`master`,将更新的`master`推送回中央仓库。
@ -291,13 +298,13 @@ Git在技术上不会区别`master`和功能分支所以开发者可以在fea
在她开始开发一个功能之前Mary需要一个独立的分支。她可以用下面的命令创建新分支
在她开始开发一个功能之前Mary需要一个独立的分支。她可以用下面的命令[创建新分支](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF#git-checkout)
```
git checkout -b marys-feature master
```
一个基于`master`、名为`marys-feature`的分支将会被checkout`-b`标记告诉Git如果分支不存在时创建它。在这个分支上Mary和常一样编辑、缓存、提交更改,用足够多的提交来构建这个功能:
一个基于`master`、名为`marys-feature`的分支将会被checkout`-b`标记告诉Git分支不存在时创建它。在这个分支上Mary和常一样编辑、缓存、提交更改,用足够多的提交来构建这个功能:
```
git status
@ -313,13 +320,13 @@ git commit
Mary在早上给她的功能添加了一些提交。在她去吃午饭前将她的分支推送到中央仓库是个不错的想法。这是一种方便的备份但如果Mary和其他开发者一起协作他们也可以看到她的初始提交了。
Mary在早上[给她的功能添加了一些提交](https://github.com/geeeeeeeeek/git-recipes/wiki/2.3-%E4%BF%9D%E5%AD%98%E4%BD%A0%E7%9A%84%E6%9B%B4%E6%94%B9#git-commit)。在她去吃午饭前,[将她的分支推送到中央仓库](https://github.com/geeeeeeeeek/git-recipes/wiki/3.2-%E4%BF%9D%E6%8C%81%E5%90%8C%E6%AD%A5#git-push)是个不错的想法。这是一种方便的备份但如果Mary和其他开发者一起协作他们也可以看到她的初始提交了。
```
git push -u origin marys-feature
```
这个美丽将`marys-feature`推送到中央仓库(`origin`)`-u`标记将它添加为远程跟踪的分支。在设置完跟踪的分支之后Mary调用不带任何参数的`git push`来推送她的功能。
这个命令将`marys-feature`推送到中央仓库(`origin`)`-u`标记将它添加为远程跟踪的分支。在设置完跟踪的分支之后Mary调用不带任何参数的`git push`来推送她的功能。
### Mary完成了她的工作
@ -329,13 +336,13 @@ git push -u origin marys-feature
当Mary吃完午饭回来她完成了她的功能。在并入`master`之前她需要发布一个pull request让其他的团队成员知道她所做的工作。但首先她应该保证中央仓库包含了她最新的提交
当Mary吃完午饭回来她完成了她的功能。在[并入`master`](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF#git-merge)之前她需要发布一个pull request让其他的团队成员知道她所做的工作。但首先她应该保证中央仓库包含了她最新的提交
```
git push
```
然后,她她的Git界面上发起了一个pull request请求将`marys-feature`合并进`master`团队成员会收到自动的通知。Pull request的好处是评论显示在相关的提交正下方方便询问特定的修改。
然后,她她的Git界面上发起了一个pull request请求将`marys-feature`合并进`master`团队成员会收到自动的通知。Pull request的好处是评论显示在相关的提交正下方方便讨论特定的修改。
### Bill收到了pull request
@ -384,11 +391,11 @@ git push
### 同时John以同样的方式工作着
Mary和Bill一起开发`marys-feature`在pull request上讨论的同时John还在开发他自己的feature分支。通过将功能用不同分支隔离开来每个人可以独地工作,但很容易和其他开发者共享修改。
Mary和Bill一起开发`marys-feature`在pull request上讨论的同时John还在开发他自己的feature分支。通过将功能用不同分支隔离开来每个人可以独地工作,但很容易和其他开发者共享修改。
## 接下来该怎么做
为了彻底了解Github上的功能分支你应该查看[使用分支一章](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF)。现在,你应该已经看到了功能分支极大地增强了中心化工作流中单一`master`分支的作用。除此之外功能分支还便利了pull request的使用在版本控制界面上直接讨论特定的提交。Gitflow工作流是管理功能开发、发布准备、维护的常见模式。
为了彻底了解Github上的功能分支你应该查看[使用分支一章](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF)。现在,你应该已经看到了功能分支极大地增强了[中心化工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#%E4%B8%AD%E5%BF%83%E5%8C%96%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81)中单一`master`分支的作用。除此之外功能分支还便利了pull request的使用在版本控制界面上直接讨论特定的提交。Gitflow工作流是管理功能开发、发布准备、维护的常见模式。
## Gitflow工作流
@ -400,13 +407,13 @@ Mary和Bill一起开发`marys-feature`在pull request上讨论的同时Joh
下面的[Gitflow工作流](http://nvie.com/posts/a-successful-git-branching-model/)一节源于[nvie](http://nvie.com/)网站上的作者Vincent Driessen。
Gitflow工作流围绕项目发布定义了一个严格的分支模型。有些地方比功能分支工作流更复杂为管理大型项目提供了鲁棒的框架。
Gitflow工作流围绕项目发布定义了一个严格的分支模型。有些地方比[功能分支工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#feature%E5%88%86%E6%94%AF%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81)更复杂,为管理大型项目提供了鲁棒的框架。
和功能分支工作流相比这种工作流没有增加任何新的概念或命令。它给不同的分支指定了特定的角色定义它们应该如何、什么时候交流。除了功能分支之外它还为准备发布、维护发布、记录发布分别使用了单独的分支。当然你还能享受到功能分支工作流带来的所有好处pull request、隔离实验和更高效的协作。
和功能分支工作流相比这种工作流没有增加任何新的概念或命令。它给不同的分支指定了特定的角色定义它们应该如何、什么时候交流。除了功能分支之外它还为准备发布、维护发布、记录发布分别使用了单独的分支。当然你还能享受到功能分支工作流带来的所有好处pull request、隔离实验和更高效的协作。
## 如何工作
Gitflow工作流仍然使用中央仓库作为开发者沟通的中心。和其他工作流一样开发者在本地工作将分支推送到中央仓库。唯一的区别在于项目的分支结构。
Gitflow工作流仍然使用中央仓库作为开发者沟通的中心。和[其他工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83)一样,开发者在本地工作,将分支推送到中央仓库。唯一的区别在于项目的分支结构。
### 历史分支
@ -422,7 +429,7 @@ Gitflow工作流仍然使用中央仓库作为开发者沟通的中心。和其
### 功能分支
每个新功能放置在自己的分支中,可以在备份/协作时推送到中央仓库。但是,与其合并到`master`,功能分支将开发分支作为父分支。当一个功能完成时,它将被并入`develop`。功能永远不应该直接`master`上交互。
每个新功能放置在自己的分支中,可以[在备份/协作时推送到中央仓库](https://github.com/geeeeeeeeek/git-recipes/wiki/3.2-%E4%BF%9D%E6%8C%81%E5%90%8C%E6%AD%A5#git-push)。但是,与其合并到`master`,功能分支将开发分支作为父分支。当一个功能完成时,它将被[合并回`develop`](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF#git-merge)。功能永远不应该直接`master`上交互。
@ -442,12 +449,12 @@ Gitflow工作流仍然使用中央仓库作为开发者沟通的中心。和其
一旦`develop`分支的新功能足够发布(或者预先确定的发布日期即将到来),你可以从`develop`分支fork一个发布分支。这个分支的创建开始了下个发布周期只有和发布相关的任务应该在这个分支进行如修复bug、生成文档等。一旦准备好了发布发布分支将合并进`master`,打上版本号的标签。另外,它也应该合并回`develop`,后者可能在发布启动之后有了新的进展。
使用一个专门的分支来准备发布确保一个团队打磨当前的发布其他团队可以继续开发下一个发布的功能。它还建立了清晰的开发阶段比如说“这周我们准备4.0版本的发布”,而我们在仓库的结构中也能看到这个阶段)。
使用一个专门的分支来准备发布确保一个团队完善当前的发布其他团队可以继续开发下一个发布的功能。它还建立了清晰的开发阶段比如说“这周我们准备4.0版本的发布”,而我们在仓库的结构中也能看到这个阶段)。
通常我们约定:
- 从`develop`创建分支
- 并入`master`
- 合并进`master`分支
- 命名规范`release-* or release/*`
### 维护分支
@ -474,14 +481,14 @@ Gitflow工作流仍然使用中央仓库作为开发者沟通的中心。和其
你要做的第一步是为默认的`master`分支创建一个互补的`develop`分支。最简单的办法是在本地创建一个空的`develop`分支,将它推送到服务器上:
你要做的第一步是为默认的`master`分支创建一个互补的`develop`分支。最简单的办法是[在本地创建一个空的`develop`分支](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF#git-branch),将它推送到服务器上:
```
git branch develop
git push -u origin develop
```
这个分支将会包含项目中所有的历史,而`master`将包含不完全的版本。其他开发者应该将中央仓库克隆到本地创建一个分支来追踪develop分支
这个分支将会包含项目中所有的历史,而`master`将包含不完全的版本。其他开发者应该[将中央仓库克隆到本地](https://github.com/geeeeeeeeek/git-recipes/wiki/2.2-%E5%88%9B%E5%BB%BA%E4%BB%A3%E7%A0%81%E4%BB%93%E5%BA%93#git-clone)创建一个分支来追踪develop分支
```
git clone ssh://user@host/path/to/repo.git
@ -498,7 +505,7 @@ git checkout -b develop origin/develop
我们的栗子从John和Mary在不同分支上工作开始。他们都要为自己的功能创建单独的分支。他们的功能分支都应该基于`develop`,而不是`master`
我们的栗子从John和Mary在不同分支上工作开始。他们都要为自己的功能创建单独的分支。[他们的功能分支都应该基于`develop`](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF#git-checkout),而不是`master`
```
git checkout -b some-feature develop
@ -520,7 +527,7 @@ git commit
在添加了一些提交之后Mary决定她的功能以及准备好了。如果她的团队使用pull request现在正是发起pull request的好时,请求将她的功能并入`develop`分支。否则,她可以向下面一样,将它并入本地的`develop`分支,推送到中央仓库:
在添加了一些提交之后Mary确信她的功能以及准备好了。如果她的团队使用pull request现在正是发起pull request的好时,请求将她的功能并入`develop`分支。否则,她可以向下面一样,将它并入本地的`develop`分支,推送到中央仓库:
```
git pull origin develop
@ -530,7 +537,7 @@ git push
git branch -d some-feature
```
第一个命令在尝试并入功能分支之前确保`develop`分支已是最新。注意,功能绝不该被直接并入`master`。冲突的处理方式和中心化工作流相同。
第一个命令在尝试并入功能分支之前确保`develop`分支已是最新。注意,功能绝不该被直接并入`master`。冲突的处理方式和[中心化工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#%E4%B8%AD%E5%BF%83%E5%8C%96%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81)相同。
### Mary开始准备发布
@ -548,7 +555,7 @@ git checkout -b release-0.1 develop
这个分支用来整理提交,充分测试,更新文档,为即将到来的发布做各种准备。它就像是一个专门用来完善发布的功能分支。
一旦Mary创建了这个分支推送到中央仓库这次发布的功能便被锁定了。不在`develop`分支中的功能将被推迟到下个发布周期。
一旦Mary创建了这个分支推送到中央仓库这次发布的功能便被锁定了。不在`develop`分支中的功能将被推迟到下个发布周期。
### Mary完成了她的发布
@ -558,7 +565,7 @@ git checkout -b release-0.1 develop
一旦发布准备稳妥Mary将它并入`master`和`develop`,然后删除发布分支。合并回`develop`很重要,因为可能已经有关键的更新添加到了发布分支上,而开发新功能需要用到它们。重复一下如果Mary的团队重视代码审查现在将是发起pull request的完美时机。
一旦发布准备稳妥Mary将它并入`master`和`develop`,然后删除发布分支。合并回`develop`很重要,因为可能已经有关键的更新添加到了发布分支上,而开发新功能需要用到它们。同样的如果Mary的团队重视代码审查现在将是发起pull request的完美时机。
```
git checkout master
@ -597,7 +604,7 @@ git merge issue-#001
git push
```
和发布分支一样,维护分支包含了`develop`中需要的重要更新因此Mary同样需要执行这个合并。接下来她可以删除这个分支了
和发布分支一样,维护分支包含了`develop`中需要的重要更新因此Mary同样需要执行这个合并。接下来她可以[删除这个分支](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF#git-branch)了:
```
git checkout develop
@ -608,7 +615,7 @@ git branch -d issue-#001
## 接下来该怎么做
现在,希望你已经很熟悉中心化的工作流、功能分支工作流和Gitflow工作流。你应该已经可以抓住本地仓库、推送/拉取模式和Git鲁棒的分支和合并模型的无限潜力。
现在,希望你已经很熟悉[中心化的工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#%E4%B8%AD%E5%BF%83%E5%8C%96%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81)、[功能分支工作流](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#feature%E5%88%86%E6%94%AF%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81)和Gitflow工作流。你应该已经可以抓住本地仓库、推送/拉取模式和Git鲁棒的分支和合并模型的无限潜力。
请记住教程中呈现的工作流只是可行的实践——而非工作中使用Git的金科玉律。因此尽情地取其精华去其糟粕吧。不变的是要让Git为你所用而不是相反。
@ -634,7 +641,7 @@ Fork工作流的主要优点在于贡献可以轻易地整合进项目而不
当他们准备好发布本地提交时他们将提交推送到自己的公开仓库——而非官方仓库。然后他们向主仓库发起一个pull request让项目维护者知道一个更新做好了合并的准备。如果贡献的代码有什么问题的话Pull request可以作为一个方便的讨论版。
我为了将功能并入官方代码库,维护者将贡献者的修改拉取到他们的本地仓库,确保修改不会破坏项目,将它合并到本地的`master`分支,然后将`master`分支推送到服务端的官方仓库。贡献现在已是项目的一部分,其他开发者应该从官方仓库拉取并同步他们的本地仓库。
我为了将功能并入官方代码库,维护者将贡献者的修改拉取到他们的本地仓库,确保修改不会破坏项目,将它[合并到本地的`master`分支](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF#git-merge),然后将`master`分支[推送](https://github.com/geeeeeeeeek/git-recipes/wiki/3.2-%E4%BF%9D%E6%8C%81%E5%90%8C%E6%AD%A5#git-push)到服务端的官方仓库。贡献现在已是项目的一部分,其他开发者应该从官方仓库拉取并同步他们的本地仓库。
### 中央仓库
@ -642,7 +649,7 @@ Fork工作流的主要优点在于贡献可以轻易地整合进项目而不
### Fork工作流中的分支
所有这些个人的公开仓库只是一个在开发者之间共享分支的约定。每个人仍然可以使用分支来隔离功能,就像在功能分支工作流和Gitflow工作流中一样。唯一的区别在于这些分支是如何开始的。在Fork工作流中它们从另一个开发者的本地仓库拉取而来而在功能分支和Gitflow分支它们被推送到官方仓库。
所有这些个人的公开仓库只是一个在开发者之间共享分支的约定。每个人仍然可以使用分支来隔离功能,就像在[功能分支工作流](](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#feature%E5%88%86%E6%94%AF%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81))和[Gitflow工作流中](https://github.com/geeeeeeeeek/git-recipes/wiki/3.5-%E5%B8%B8%E8%A7%81%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%AF%94%E8%BE%83#gitflow%E5%B7%A5%E4%BD%9C%E6%B5%81)一样。唯一的区别在于这些分支是如何开始的。在Fork工作流中它们从另一个开发者的本地仓库拉取而来而在功能分支和Gitflow分支它们被推送到官方仓库。
## 栗子
@ -656,7 +663,7 @@ Fork工作流的主要优点在于贡献可以轻易地整合进项目而不
和任何基于Git的项目一样第一步是在服务端创建一个可以被所有项目成员访问到的官方仓库。一般来说这个仓库同时还是项目维护者的公开仓库。
公开的仓库应该永远是裸的,不管它们是否代表官方代码库。所以项目维护者应该运行下面这样的命令来设置官方仓库:
[公开的仓库应该永远是裸的](https://github.com/geeeeeeeeek/git-recipes/wiki/2.2-%E5%88%9B%E5%BB%BA%E4%BB%A3%E7%A0%81%E4%BB%93%E5%BA%93#git-init),不管它们是否代表官方代码库。所以项目维护者应该运行下面这样的命令来设置官方仓库:
```
ssh user@host
@ -715,7 +722,7 @@ git remote add upstream https://user@bitbucket.org/maintainer/repo.git
在他们刚克隆的本地仓库中,开发者可以编辑代提交更改,和其它分支中一样创建分支:
在他们刚克隆的本地仓库中,开发者可以编辑代码、[提交更改](https://github.com/geeeeeeeeek/git-recipes/wiki/2.3-%E4%BF%9D%E5%AD%98%E4%BD%A0%E7%9A%84%E6%9B%B4%E6%94%B9#git-commit),和其它分支中一样[创建分支](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF#git-branch)
```
git checkout -b some-feature
@ -729,7 +736,7 @@ git commit -a -m "Add first draft of some feature"
git pull upstream master
```
因为开发者应该在专门的功能分支开发,这一般会产生一个快速向前的合并。
因为开发者应该在专门的功能分支开发,这一般会[产生一个快速向前的合并](https://github.com/geeeeeeeeek/git-recipes/wiki/3.4-%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF#git-merge)
### 开发者发布他们的功能
@ -766,7 +773,7 @@ git push origin feature-branch
```
git fetch https://bitbucket.org/user/repo feature-branch
# Inspect the changes
# 检查修改
git checkout master
git merge FETCH_HEAD
```