├── _image ├── 2016-07-14 20-31-39.png ├── 2016-07-14 20-53-25.jpg ├── 2016-07-14 20-57-04.jpg ├── 2016-07-14 21-15-47.jpg ├── 2016-07-14 21-26-37.jpg ├── 2016-07-14 21-44-06.jpg ├── 2016-07-14 21-45-50.jpg ├── 2016-07-19 20-35-30.jpg ├── 2016-07-19-19-58-15.jpg ├── 2016-09-22-20-57-27.jpg └── 2017-06-02-11-51-27.jpg ├── command-handbook ├── git-cheat-sheet.pdf ├── git-cheat-sheet.png ├── git常用命令.png ├── git常用命令.xmind └── readme.md ├── ebooks ├── Git Community Book.pdf ├── Git Magic.pdf ├── git-internals.pdf └── progit_v2.1.37.pdf ├── git-workflow-tutorial.md ├── how-to-use-github.md ├── images ├── branch_module.png ├── example-6.png ├── git-workflow-feature-branch-1.png ├── git-workflow-feature-branch-2.png ├── git-workflow-feature-branch-3.png ├── git-workflow-feature-branch-4.png ├── git-workflow-feature-branch-5.png ├── git-workflow-feature-branch-6.png ├── git-workflow-feature-branch-7.png ├── git-workflow-feature_branch.png ├── git-workflow-forking.png ├── git-workflow-gitflow-enduserbug.png ├── git-workflow-release-cycle-1historical.png ├── git-workflow-release-cycle-2feature.png ├── git-workflow-release-cycle-3release.png ├── git-workflow-release-cycle-4maintenance.png ├── git-workflow-release-cycle-5createdev.png ├── git-workflow-release-cycle-6maryjohnbeginnew.png ├── git-workflow-release-cycle-7maryfinishes.png ├── git-workflow-release-cycle-8maryprepsrelease.png ├── git-workflow-release-cycle-9maryfinishes.png ├── git-workflow-svn-1.png ├── git-workflow-svn-2.png ├── git-workflow-svn-3.png ├── git-workflow-svn-4.png ├── git-workflow-svn-5.png ├── git-workflow-svn-6.png ├── git-workflow-svn-7.png ├── git-workflow-svn-8.png ├── git-workflow-svn-9.png ├── git-workflow-svn-clone.png ├── git-workflow-svn-initialize.png ├── git-workflow-svn-managingconflicts.png ├── git-workflow-svn-push-local.png ├── git-workflow-svn.png ├── git-workflows-forking-1.png ├── git-workflows-forking-2.png ├── git-workflows-forking-3.png ├── git-workflows-forking-4.png ├── git-workflows-forking-5.png ├── git-workflows-forking-6.png ├── git-workflows-forking-7.png ├── git-workflows-forking.png ├── git-workflows-gitflow.png ├── git_workflow.png ├── gitflow-workflow-pull-request.png ├── pull-request-1.png ├── pull-request-2.png ├── pull-request-3.png ├── pull-request-4.png ├── pull-request-5.png ├── pull-request-7.png ├── pull-request-8.png ├── pull-request-9.png ├── pull-request-anatomy.png ├── pull-request-bitbucket.png ├── pull-request-feature-branch.png ├── pull-request-forking-workflow-1.png ├── pull-request-forking-workflow-2.png ├── pull-request-overview.png └── pull-request.png ├── ixirong.com.md ├── readme.md ├── use-gitlab-github-together.md ├── useful-git-command.md ├── using-svn.md ├── video └── why-git.md /_image/2016-07-14 20-31-39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2016-07-14 20-31-39.png -------------------------------------------------------------------------------- /_image/2016-07-14 20-53-25.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2016-07-14 20-53-25.jpg -------------------------------------------------------------------------------- /_image/2016-07-14 20-57-04.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2016-07-14 20-57-04.jpg -------------------------------------------------------------------------------- /_image/2016-07-14 21-15-47.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2016-07-14 21-15-47.jpg -------------------------------------------------------------------------------- /_image/2016-07-14 21-26-37.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2016-07-14 21-26-37.jpg -------------------------------------------------------------------------------- /_image/2016-07-14 21-44-06.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2016-07-14 21-44-06.jpg -------------------------------------------------------------------------------- /_image/2016-07-14 21-45-50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2016-07-14 21-45-50.jpg -------------------------------------------------------------------------------- /_image/2016-07-19 20-35-30.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2016-07-19 20-35-30.jpg -------------------------------------------------------------------------------- /_image/2016-07-19-19-58-15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2016-07-19-19-58-15.jpg -------------------------------------------------------------------------------- /_image/2016-09-22-20-57-27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2016-09-22-20-57-27.jpg -------------------------------------------------------------------------------- /_image/2017-06-02-11-51-27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/_image/2017-06-02-11-51-27.jpg -------------------------------------------------------------------------------- /command-handbook/git-cheat-sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/command-handbook/git-cheat-sheet.pdf -------------------------------------------------------------------------------- /command-handbook/git-cheat-sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/command-handbook/git-cheat-sheet.png -------------------------------------------------------------------------------- /command-handbook/git常用命令.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/command-handbook/git常用命令.png -------------------------------------------------------------------------------- /command-handbook/git常用命令.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/command-handbook/git常用命令.xmind -------------------------------------------------------------------------------- /command-handbook/readme.md: -------------------------------------------------------------------------------- 1 | 说明 2 | ====== 3 | 目前收集的常用命令,包括[git-cheat-sheet.pdf](git-cheat-sheet.pdf) 和 [git常用命令.xmind](git常用命令.xmind) ,以后会持续更新 xmind 版本的命令,图片预览如下: 4 | 5 | ![git-cheat-sheet](git-cheat-sheet.png) 6 | 7 | 8 | git常用命令 9 | 10 | ---------------------- 11 | 12 | ![git常用命令](git常用命令.png) -------------------------------------------------------------------------------- /ebooks/Git Community Book.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/ebooks/Git Community Book.pdf -------------------------------------------------------------------------------- /ebooks/Git Magic.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/ebooks/Git Magic.pdf -------------------------------------------------------------------------------- /ebooks/git-internals.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/ebooks/git-internals.pdf -------------------------------------------------------------------------------- /ebooks/progit_v2.1.37.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/ebooks/progit_v2.1.37.pdf -------------------------------------------------------------------------------- /git-workflow-tutorial.md: -------------------------------------------------------------------------------- 1 | 说明: 2 | ====== 3 | 个人在学习`Git`工作流的过程中,从原有的 SVN 模式很难完全理解`Git`的协作模式,直到有一天我看到了下面的文章,好多遗留在心中的困惑迎刃而解: 4 | 5 | - 我们以使用SVN的工作流来使用`Git`有什么不妥? 6 | - `Git`方便的branch在哪里,团队多人如何协作?冲突了怎么办?如何进行发布控制? 7 | - 经典的master-发布、develop-主开发、hotfix-bug修复如何避免代码不经过验证上线? 8 | - 如何在`GitHub`上面与他人一起协作,star-fork-pull request是怎样的流程? 9 | 10 | 我个人很感激这篇文章,所以进行了整理,希望能帮到更多的人。整篇文章由 [xirong](https://github.com/xirong) 整理自 [oldratlee](https://github.com/oldratlee) 的`GitHub`,方便统一的学习回顾,在此感谢下面两位的贡献。 11 | 12 | 原文链接:[Git Workflows and Tutorials](https://www.atlassian.com/git/workflows) 13 | 简体中文:由 [oldratlee](https://github.com/oldratlee) 翻译在 `GitHub` 上 [`Git`工作流指南](https://github.com/oldratlee/translations/blob/master/git-workflows-and-tutorials/README.md) 14 | 15 | 在第三部分 企业日常开发模式探索,xirong 结合自己所在公司使用git的版本分支开发过程,进行了总结,欢迎大家提出更好的建议。 16 | 17 | 在第四部分 开发工作流的讨论 中,引用了几篇文章,包括 Github 的开发流程以及 Thoughtworkers 工程师发表的「Gitflow 有害论」,旨在表名流程并不是唯一的,适合自己当前团队的才是最好的。 18 | 19 | -------------- 20 | 21 |

22 | 113 |
114 |

115 | 116 | 117 | # 一、译序 118 | 119 | 这篇指南以大家在`SVN`中已经广为熟悉使用的集中式工作流作为起点,循序渐进地演进到其它高效的分布式工作流,还介绍了如何配合使用便利的`Pull Request`功能,系统地讲解了各种工作流的应用。 120 | 如果你`Git`用的还不多,可以从前面的讲的工作流开始操练。在操作过程中去感受指南的讲解:解决什么问题、如何解决问题,这样理解就深了,也方便活用。 121 | 122 | 行文中实践原则和操作示例并重,对于`Git`的资深玩家可以梳理思考提升,而新接触的同学,也可以跟着step-by-step操练学习并在实际工作中上手使用。 123 | 124 | 工作流其实不是一个初级主题,背后的本质问题是 有效的项目流程管理 和 高效的开发协同约定,而不仅仅是`Git`或`SVN`等[`VCS`](http://zh.wikipedia.org/wiki/%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6)或[`SCM`](http://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86)工具的使用。 125 | 126 | 关于`Git`工作流主题,网上体系的中文资料不多,主要是零散的操作说明,希望这篇文章能让你更深入理解并在工作中灵活有效地使用起来。 127 | 128 | `Gitflow`工作流是经典模型,处于核心位置,体现了工作流的经验和精髓。随着项目过程复杂化,你会感受到这个工作流中的深思熟虑和威力! 129 | 130 | `Forking`工作流是分布式协作的(`GitHub`风格)可以先看看`GitHub`的Help:[Fork A Repo](https://help.github.com/articles/fork-a-repo/)和[Using pull requests](https://help.github.com/articles/using-pull-requests/) 。照着操作,给一个`GitHub`项目贡献你的提交,有操作经验再看指南容易意会。指南中给了[自己实现`Fork`的方法](https://github.com/oldratlee/translations/blob/master/git-workflows-and-tutorials/workflow-forking.md#%E5%BC%80%E5%8F%91%E8%80%85fork%E6%AD%A3%E5%BC%8F%E4%BB%93%E5%BA%93):`Fork`就是服务端的克隆。在指南的操练中使用代码托管服务(如`GitHub`、`Bitbucket`),可以点一下按钮就让开发者完成仓库的`fork`操作。 131 | 132 | **_PS_**: 133 | 134 | 文中`Pull Request`的介绍用的是`Bitbucket`代码托管服务,由于和`GitHub`基本一样,如果你用的是`GitHub`(我自己也主要使用`GitHub`托管代码),不影响理解和操作。 135 | 136 | **_PPS_**: 137 | 138 | 更多`Git`学习资料参见 139 | 140 | - [`Git`的资料整理](https://github.com/xirong/my-git) by [@xirong](https://github.com/xirong) 141 | - 自己整理的分享PPT [`Git`使用与实践](https://github.com/oldratlee/software-practice-miscellany/blob/master/git/git-gitlab-usage.pptx) @ [个人整理一些`Git`](https://github.com/oldratlee/software-practice-miscellany/tree/master/git) 142 | 143 | ---------------- 144 | 145 | - :see_no_evil: [自己](http://weibo.com/oldratlee)理解粗浅,翻译中不足和不对之处,欢迎 :clap: 146 | - 建议,[提交`Issue`](https://github.com/oldratlee/translations/issues/new) 147 | - 指正,[`Fork`后提通过`Pull Requst`贡献修改](https://github.com/oldratlee/translations/fork) 148 | - 如有文章理解上有疑问 或是 使用过程中碰到些疑惑,请随时:raised_hands:[提交`Issue`](https://github.com/oldratlee/translations/issues/new) ,一起交流学习讨论! 149 | 150 | ---------------- 151 | 152 | 153 | # 二、`Git`工作流指南 154 | 155 | :point_right: 工作流有各式各样的用法,但也正因此使得在实际工作中如何上手使用变得很头大。这篇指南通过总览公司团队中最常用的几种`Git`工作流让大家可以上手使用。 156 | 157 | 在阅读的过程中请记住,本文中的几种工作流是作为方案指导而不是条例规定。在展示了各种工作流可能的用法后,你可以从不同的工作流中挑选或揉合出一个满足你自己需求的工作流。 158 | 159 | ![Git Workflows](images/git_workflow.png) 160 | 161 | ## 2.1 集中式工作流 162 | 163 | 如果你的开发团队成员已经很熟悉`Subversion`,集中式工作流让你无需去适应一个全新流程就可以体验`Git`带来的收益。这个工作流也可以作为向更`Git`风格工作流迁移的友好过渡。 164 | ![Git Workflows: SVN-style](images/git-workflow-svn.png) 165 | 166 | 转到分布式版本控制系统看起来像个令人生畏的任务,但不改变已用的工作流,你也可以用上`Git`带来的收益。团队可以用和`Subversion`完全不变的方式来开发项目。 167 | 168 | 但使用`Git`加强开发的工作流,相比`SVN`,`Git`有以下两个优势: 169 | 首先,每个开发者可以有属于自己的整个工程的本地拷贝。隔离的环境让各个开发者的工作和项目的其他部分修改独立开来 —— 170 | 即自由地提交到自己的本地仓库,先完全忽略上游的开发,直到方便的时候再把修改反馈上去。 171 | 172 | 其次,`Git`提供了强壮的分支和合并模型。不像`SVN`,`Git`的分支设计成可以做为一种用来在仓库之间集成代码和分享修改的『失败安全』的机制。 173 | 174 | ### 2.1.1 工作方式 175 | 176 | 像`Subversion`一样,集中式工作流以中央仓库作为项目所有修改的单点实体。相比`SVN`缺省的开发分支`trunk`,`Git`叫做`master`,所有修改提交到这个分支上。本工作流只用到`master`这一个分支。 177 | 178 | 首先,开发者克隆中央仓库。在自己的项目拷贝中,像`SVN`一样的编辑文件和提交修改;但修改是存在本地的,和中央仓库是完全隔离的。开发者可以把和上游的同步延后到一个方便时间点。 179 | 180 | 然后,开发者发布修改到正式项目中,开发者要把本地`master`分支的修改『推』到中央仓库中。这相当于`svn commit`操作,但`push`操作会把所有还不在中央仓库的本地提交都推上去。 181 | 182 | ![git-workflow-svn-push-local](images/git-workflow-svn-push-local.png) 183 | 184 | ### 2.1.2 冲突解决 185 | 186 | 中央仓库代表了正式项目,所以提交历史应该被尊重且是稳定不变的。如果开发者本地的提交历史和中央仓库有分歧,`Git`会拒绝`push`提交否则会覆盖已经在中央库的正式提交。 187 | 188 | ![git-workflow-svn-managingconflicts](images/git-workflow-svn-managingconflicts.png) 189 | 190 | 在开发者提交自己功能修改到中央库前,需要先`fetch`在中央库的新增提交,`rebase`自己提交到中央库提交历史之上。 191 | 这样做的意思是在说,『我要把自己的修改加到别人已经完成的修改上。』最终的结果是一个完美的线性历史,就像以前的`SVN`的工作流中一样。 192 | 193 | 如果本地修改和上游提交有冲突,`Git`会暂停`rebase`过程,给你手动解决冲突的机会。`Git`解决合并冲突,用和生成提交一样的[`git status`](https://www.atlassian.com/git/tutorial/git-basics#!status)和[`git add`](https://www.atlassian.com/git/tutorial/git-basics#!add)命令,很一致方便。还有一点,如果解决冲突时遇到麻烦,`Git`可以很简单中止整个`rebase`操作,重来一次(或者让别人来帮助解决)。 194 | 195 | ### 2.1.3 示例 196 | 197 | 让我们一起逐步分解来看看一个常见的小团队如何用这个工作流来协作的。有两个开发者小明和小红,看他们是如何开发自己的功能并提交到中央仓库上的。 198 | 199 | #### 有人先初始化好中央仓库 200 | 201 | ![](images/git-workflow-svn-initialize.png) 202 | 203 | 第一步,有人在服务器上创建好中央仓库。如果是新项目,你可以初始化一个空仓库;否则你要导入已有的`Git`或`SVN`仓库。 204 | 205 | 中央仓库应该是个裸仓库(`bare repository`),即没有工作目录(`working directory`)的仓库。可以用下面的命令创建: 206 | 207 | ```bash 208 | ssh user@host 209 | git init --bare /path/to/repo.git 210 | ``` 211 | 212 | 确保写上有效的`user`(`SSH`的用户名),`host`(服务器的域名或IP地址),`/path/to/repo.git`(你想存放仓库的位置)。 213 | 注意,为了表示是一个裸仓库,按照约定加上`.git`扩展名到仓库名上。 214 | 215 | #### 所有人克隆中央仓库 216 | 217 | ![](images/git-workflow-svn-clone.png) 218 | 219 | 下一步,各个开发者创建整个项目的本地拷贝。通过[`git clone`](https://www.atlassian.com/git/tutorial/git-basics#!clone)命令完成: 220 | 221 | ```bash 222 | git clone ssh://user@host/path/to/repo.git 223 | ``` 224 | 225 | 基于你后续会持续和克隆的仓库做交互的假设,克隆仓库时`Git`会自动添加远程别名`origin`指回『父』仓库。 226 | 227 | #### 小明开发功能 228 | 229 | ![](images/git-workflow-svn-1.png) 230 | 231 | 在小明的本地仓库中,他使用标准的`Git`过程开发功能:编辑、暂存(`Stage`)和提交。 232 | 如果你不熟悉暂存区(`Staging Area`),这里说明一下:**暂存区**用来准备一个提交,但可以不用把工作目录中所有的修改内容都包含进来。 233 | 这样你可以创建一个高度聚焦的提交,尽管你本地修改很多内容。 234 | 235 | ```bash 236 | git status # 查看本地仓库的修改状态 237 | git add # 暂存文件 238 | git commit # 提交文件 239 | ``` 240 | 241 | 请记住,因为这些命令生成的是本地提交,小明可以按自己需求反复操作多次,而不用担心中央仓库上有了什么操作。 242 | 对需要多个更简单更原子分块的大功能,这个做法是很有用的。 243 | 244 | 245 | #### 小红开发功能 246 | 247 | ![](images/git-workflow-svn-2.png) 248 | 249 | 与此同时,小红在自己的本地仓库中用相同的编辑、暂存和提交过程开发功能。和小明一样,她也不关心中央仓库有没有新提交; 250 | 当然更不关心小明在他的本地仓库中的操作,因为所有本地仓库都是私有的。 251 | 252 | #### 小明发布功能 253 | 254 | ![](images/git-workflow-svn-3.png) 255 | 256 | 一旦小明完成了他的功能开发,会发布他的本地提交到中央仓库中,这样其它团队成员可以看到他的修改。他可以用下面的[`git push`命令](https://www.atlassian.com/git/tutorial/remote-repositories#!push): 257 | 258 | ```bash 259 | git push origin master 260 | ``` 261 | 262 | 注意,`origin`是在小明克隆仓库时`Git`创建的远程中央仓库别名。`master`参数告诉`Git`推送的分支。 263 | 由于中央仓库自从小明克隆以来还没有被更新过,所以`push`操作不会有冲突,成功完成。 264 | 265 | #### 小红试着发布功能 266 | 267 | ![](images/git-workflow-svn-4.png) 268 | 269 | 一起来看看在小明发布修改后,小红`push`修改会怎么样?她使用完全一样的`push`命令: 270 | 271 | ```bash 272 | git push origin master 273 | ``` 274 | 275 | 但她的本地历史已经和中央仓库有分岐了,`Git`拒绝操作并给出下面很长的出错消息: 276 | 277 | ``` 278 | error: failed to push some refs to '/path/to/repo.git' 279 | hint: Updates were rejected because the tip of your current branch is behind 280 | hint: its remote counterpart. Merge the remote changes (e.g. 'git pull') 281 | hint: before pushing again. 282 | hint: See the 'Note about fast-forwards' in 'git push --help' for details. 283 | ``` 284 | 285 | 这避免了小红覆写正式的提交。她要先`pull`小明的更新到她的本地仓库合并上她的本地修改后,再重试。 286 | 287 | #### 小红在小明的提交之上`rebase` 288 | 289 | ![](images/git-workflow-svn-5.png) 290 | 291 | 小红用[`git pull`](https://www.atlassian.com/git/tutorial/remote-repositories#!pull)合并上游的修改到自己的仓库中。 292 | 这条命令类似`svn update`——拉取所有上游提交命令到小红的本地仓库,并尝试和她的本地修改合并: 293 | 294 | ```bash 295 | git pull --rebase origin master 296 | ``` 297 | 298 | `--rebase`选项告诉`Git`把小红的提交移到同步了中央仓库修改后的`master`分支的顶部,如下图所示: 299 | 300 | ![](images/git-workflow-svn-6.png) 301 | 302 | 如果你忘加了这个选项,`pull`操作仍然可以完成,但每次`pull`操作要同步中央仓库中别人修改时,提交历史会以一个多余的『合并提交』结尾。 303 | 对于集中式工作流,最好是使用`rebase`而不是生成一个合并提交。 304 | 305 | #### 小红解决合并冲突 306 | 307 | ![](images/git-workflow-svn-7.png) 308 | 309 | `rebase`操作过程是把本地提交一次一个地迁移到更新了的中央仓库`master`分支之上。 310 | 这意味着可能要解决在迁移某个提交时出现的合并冲突,而不是解决包含了所有提交的大型合并时所出现的冲突。 311 | 这样的方式让你尽可能保持每个提交的聚焦和项目历史的整洁。反过来,简化了哪里引入`Bug`的分析,如果有必要,回滚修改也可以做到对项目影响最小。 312 | 313 | 如果小红和小明的功能是不相关的,不大可能在`rebase`过程中有冲突。如果有,`Git`在合并有冲突的提交处暂停`rebase`过程,输出下面的信息并带上相关的指令: 314 | 315 | ``` 316 | CONFLICT (content): Merge conflict in 317 | ``` 318 | 319 | ![](images/git-workflow-svn-8.png) 320 | 321 | `Git`很赞的一点是,任何人可以解决他自己的冲突。在这个例子中,小红可以简单的运行[`git status`](https://www.atlassian.com/git/tutorial/git-basics#!status)命令来查看哪里有问题。 322 | 冲突文件列在`Unmerged paths`(未合并路径)一节中: 323 | 324 | ``` 325 | # Unmerged paths: 326 | # (use "git reset HEAD ..." to unstage) 327 | # (use "git add/rm ..." as appropriate to mark resolution) 328 | # 329 | # both modified: 330 | ``` 331 | 332 | 接着小红编辑这些文件。修改完成后,用老套路暂存这些文件,并让[`git rebase`](https://www.atlassian.com/git/tutorial/rewriting-git-history#!rebase)完成剩下的事: 333 | 334 | ```bash 335 | git add 336 | git rebase --continue 337 | ``` 338 | 339 | 要做的就这些了。`Git`会继续一个一个地合并后面的提交,如其它的提交有冲突就重复这个过程。 340 | 341 | 如果你碰到了冲突,但发现搞不定,不要惊慌。只要执行下面这条命令,就可以回到你执行[`git pull --rebase`](https://www.atlassian.com/git/tutorial/remote-repositories#!pull)命令前的样子: 342 | 343 | ```bash 344 | git rebase --abort 345 | ``` 346 | 347 | #### 小红成功发布功能 348 | 349 | ![](images/git-workflow-svn-9.png) 350 | 351 | 小红完成和中央仓库的同步后,就能成功发布她的修改了: 352 | 353 | ```bash 354 | git push origin master 355 | ``` 356 | 357 | 如你所见,仅使用几个`Git`命令我们就可以模拟出传统`Subversion`开发环境。对于要从`SVN`迁移过来的团队来说这太好了,但没有发挥出`Git`分布式本质的优势。 358 | 359 | 如果你的团队适应了集中式工作流,但想要更流畅的协作效果,绝对值得探索一下 `功能分支工作流` 的收益。 360 | 通过为一个功能分配一个专门的分支,能够做到一个新增功能集成到正式项目之前对新功能进行深入讨论。 361 | 362 | ----------------- 363 | 364 | ## 2.2 功能分支工作流 365 | 366 | 功能分支工作流以集中式工作流为基础,不同的是为各个新功能分配一个专门的分支来开发。这样可以在把新功能集成到正式项目前,用`Pull Requests`的方式讨论变更。 367 | 368 | ![Git Workflows: Feature Branch](images/git-workflow-feature_branch.png) 369 | 370 | ![](images/git-workflow-feature-branch-1.png) 371 | 372 | 一旦你玩转了[集中式工作流](workflow-centralized.md),在开发过程中可以很简单地加上功能分支,用来鼓励开发者之间协作和简化交流。 373 | 374 | 功能分支工作流背后的核心思路是所有的功能开发应该在一个专门的分支,而不是在`master`分支上。 375 | 这个隔离可以方便多个开发者在各自的功能上开发而不会弄乱主干代码。 376 | 另外,也保证了`master`分支的代码一定不会是有问题的,极大有利于集成环境。 377 | 378 | 功能开发隔离也让[`pull requests`工作流](pull-request.md)成功可能, 379 | `pull requests`工作流能为每个分支发起一个讨论,在分支合入正式项目之前,给其它开发者有表示赞同的机会。 380 | 另外,如果你在功能开发中有问题卡住了,可以开一个`pull requests`来向同学们征求建议。 381 | 这些做法的重点就是,`pull requests`让团队成员之间互相评论工作变成非常方便! 382 | 383 | ### 2.2.1 工作方式 384 | 385 | 功能分支工作流仍然用中央仓库,并且`master`分支还是代表了正式项目的历史。 386 | 但不是直接提交本地历史到各自的本地`master`分支,开发者每次在开始新功能前先创建一个新分支。 387 | 功能分支应该有个有描述性的名字,比如`animated-menu-items`或`issue-#1061`,这样可以让分支有个清楚且高聚焦的用途。 388 | 389 | 对于`master`分支和功能分支,`Git`是没有技术上的区别,所以开发者可以用和集中式工作流中完全一样的方式编辑、暂存和提交修改到功能分支上。 390 | 391 | 另外,功能分支也可以(且应该)`push`到中央仓库中。这样不修改正式代码就可以和其它开发者分享提交的功能。 392 | 由于`master`是仅有的一个『特殊』分支,在中央仓库上存多个功能分支不会有任何问题。当然,这样做也可以很方便地备份各自的本地提交。 393 | 394 | ### 2.2.2 `Pull Requests` 395 | 396 | 功能分支除了可以隔离功能的开发,也使得通过[`Pull Requests`](pull-request.md)讨论变更成为可能。 397 | 一旦某个开发者完成一个功能,不是立即合并到`master`,而是`push`到中央仓库的功能分支上并发起一个`Pull Request`请求,将修改合并到`master`。 398 | 在修改成为主干代码前,这让其它的开发者有机会先去`Review`变更。 399 | 400 | `Code Review`是`Pull Requests`的一个重要的收益,而`Pull Requests`则是讨论代码的一个通用方式。 401 | 你可以把`Pull Requests`作为专门给某个分支的讨论。这意味着可以在更早的开发过程中就可以进行`Code Review`。 402 | 比如,一个开发者开发功能需要帮助时,要做的就是发起一个`Pull Request`,相关的人就会自动收到通知,在相关的提交旁边能看到需要帮助解决的问题。 403 | 404 | 一旦`Pull Request`被接受了,发布功能要做的就和集中式工作流就很像了。 405 | 首先,确定本地的`master`分支和上游的`master`分支是同步的。然后合并功能分支到本地`master`分支并`push`已经更新的本地`master`分支到中央仓库。 406 | 407 | 仓库管理的产品解决方案像[`Bitbucket`](http://bitbucket.org/)或[`Stash`](http://www.atlassian.com/stash),可以良好地支持`Pull Requests`。可以看看`Stash`的[`Pull Requests`文档](https://confluence.atlassian.com/display/STASH/Using+pull+requests+in+Stash)。 408 | 409 | ### 2.2.3 示例 410 | 411 | 下面的示例演示了如何把`Pull Requests`作为`Code Review`的方式,但注意`Pull Requests`可以用于很多其它的目的。 412 | 413 | #### 小红开始开发一个新功能 414 | 415 | ![](images/git-workflow-feature-branch-2.png) 416 | 417 | 在开始开发功能前,小红需要一个独立的分支。使用下面的命令[新建一个分支](https://www.atlassian.com/git/tutorial/git-branches#!checkout): 418 | 419 | ```bash 420 | git checkout -b marys-feature master 421 | ``` 422 | 423 | 这个命令检出一个基于`master`名为`marys-feature`的分支,`Git`的`-b`选项表示如果分支还不存在则新建分支。 424 | 这个新分支上,小红按老套路编辑、暂存和提交修改,按需要提交以实现功能: 425 | 426 | ```bash 427 | git status 428 | git add 429 | git commit 430 | ``` 431 | 432 | #### 小红要去吃个午饭 433 | 434 | ![](images/git-workflow-feature-branch-3.png) 435 | 436 | 早上小红为新功能添加一些提交。 437 | 去吃午饭前,`push`功能分支到中央仓库是很好的做法,这样可以方便地备份,如果和其它开发协作,也让他们可以看到小红的提交。 438 | 439 | ```bash 440 | git push -u origin marys-feature 441 | ``` 442 | 443 | 这条命令`push` `marys-feature`分支到中央仓库(`origin`),`-u`选项设置本地分支去跟踪远程对应的分支。 444 | 设置好跟踪的分支后,小红就可以使用`git push`命令省去指定推送分支的参数。 445 | 446 | #### 小红完成功能开发 447 | 448 | ![](images/git-workflow-feature-branch-4.png) 449 | 450 | 小红吃完午饭回来,完成整个功能的开发。[在合并到`master`之前](https://www.atlassian.com/git/tutorial/git-branches#!merge), 451 | 她发起一个`Pull Request`让团队的其它人知道功能已经完成。但首先,她要确认中央仓库中已经有她最近的提交: 452 | 453 | ```bash 454 | git push 455 | ``` 456 | 457 | 然后,在她的`Git` `GUI`客户端中发起`Pull Request`,请求合并`marys-feature`到`master`,团队成员会自动收到通知。 458 | `Pull Request`很酷的是可以在相关的提交旁边显示评注,所以你可以对某个变更集提问。 459 | 460 | #### 小黑收到`Pull Request` 461 | 462 | ![](images/git-workflow-feature-branch-5.png) 463 | 464 | 小黑收到了`Pull Request`后会查看`marys-feature`的修改。决定在合并到正式项目前是否要做些修改,且通过`Pull Request`和小红来回地讨论。 465 | 466 | #### 小红再做修改 467 | 468 | ![](images/git-workflow-feature-branch-6.png) 469 | 470 | 要再做修改,小红用和功能第一个迭代完全一样的过程。编辑、暂存、提交并`push`更新到中央仓库。小红这些活动都会显示在`Pull Request`上,小黑可以断续做评注。 471 | 472 | 如果小黑有需要,也可以把`marys-feature`分支拉到本地,自己来修改,他加的提交也会一样显示在`Pull Request`上。 473 | 474 | #### 小红发布她的功能 475 | 476 | ![](images/git-workflow-feature-branch-7.png) 477 | 478 | 一旦小黑可以的接受`Pull Request`,就可以合并功能到稳定项目代码中(可以由小黑或是小红来做这个操作): 479 | 480 | ```bash 481 | git checkout master 482 | git pull 483 | git pull origin marys-feature 484 | git push 485 | ``` 486 | 487 | 无论谁来做合并,首先要检出`master`分支并确认是它是最新的。然后执行`git pull origin marys-feature`合并`marys-feature`分支到和已经和远程一致的本地`master`分支。 488 | 你可以使用简单`git merge marys-feature`命令,但前面的命令可以保证总是最新的新功能分支。 489 | 最后更新的`master`分支要重新`push`回到`origin`。 490 | 491 | 这个过程常常会生成一个合并提交。有些开发者喜欢有合并提交,因为它像一个新功能和原来代码基线的连通符。 492 | 但如果你偏爱线性的提交历史,可以在执行合并时`rebase`新功能到`master`分支的顶部,这样生成一个快进(`fast-forward`)的合并。 493 | 494 | 一些`GUI`客户端可以只要点一下『接受』按钮执行好上面的命令来自动化`Pull Request`接受过程。 495 | 如果你的不能这样,至少在功能合并到`master`分支后能自动关闭`Pull Request`。 496 | 497 | #### 与此同时,小明在做和小红一样的事 498 | 499 | 当小红和小黑在`marys-feature`上工作并讨论她的`Pull Request`的时候,小明在自己的功能分支上做完全一样的事。 500 | 501 | 通过隔离功能到独立的分支上,每个人都可以自主的工作,当然必要的时候在开发者之间分享变更还是比较繁琐的。 502 | 503 | 到了这里,但愿你发现了功能分支可以很直接地在 `集中式工作流` 的仅有的`master`分支上完成多功能的开发。 504 | 另外,功能分支还使用了`Pull Request`,使得可以在你的版本控制`GUI`客户端中讨论某个提交。 505 | 506 | 功能分支工作流是开发项目异常灵活的方式。问题是,有时候太灵活了。对于大型团队,常常需要给不同分支分配一个更具体的角色。 507 | `Gitflow`工作流是管理功能开发、发布准备和维护的常用模式。 508 | 509 | ----------------- 510 | 511 | 512 | ## 2.3 `Gitflow`工作流 513 | 514 | `Gitflow`工作流通过为功能开发、发布准备和维护分配独立的分支,让发布迭代过程更流畅。严格的分支模型也为大型项目提供了一些非常必要的结构。 515 | 516 | ![Git Workflows: Gitflow Cycle](images/git-workflows-gitflow.png) 517 | 518 | 这节介绍的[`Gitflow`工作流](http://nvie.com/posts/a-successful-git-branching-model/)借鉴自在[nvie](http://nvie.com/)的*Vincent Driessen*。 519 | 520 | `Gitflow`工作流定义了一个围绕项目发布的严格分支模型。虽然比[功能分支工作流](workflow-feature-branch.md)复杂几分,但提供了用于一个健壮的用于管理大型项目的框架。 521 | 522 | `Gitflow`工作流没有用超出功能分支工作流的概念和命令,而是为不同的分支分配一个明确的角色,并定义分支之间如何和什么时候进行交互。 523 | 除了使用功能分支,在做准备、维护和记录发布时,也定义了各自的分支。 524 | 当然你可以用上功能分支工作流所有的好处:`Pull Requests`、隔离实验性开发和更高效的协作。 525 | 526 | ### 2.3.1 工作方式 527 | `Gitflow`工作流仍然用中央仓库作为所有开发者的交互中心。和其它的工作流一样,开发者在本地工作并`push`分支到要中央仓库中。 528 | 529 | ### 2.3.2 历史分支 530 | 531 | 相对于使用仅有的一个`master`分支,`Gitflow`工作流使用两个分支来记录项目的历史。`master`分支存储了正式发布的历史,而`develop`分支作为功能的集成分支。 532 | 这样也方便`master`分支上的所有提交分配一个版本号。 533 | 534 | ![](images/git-workflow-release-cycle-1historical.png) 535 | 536 | 剩下要说明的问题围绕着这2个分支的区别展开。 537 | 538 | ### 2.3.3 功能分支 539 | 540 | 每个新功能位于一个自己的分支,这样可以[`push`到中央仓库以备份和协作](https://www.atlassian.com/git/tutorial/remote-repositories#!push)。 541 | 但功能分支不是从`master`分支上拉出新分支,而是使用`develop`分支作为父分支。当新功能完成时,[合并回`develop`分支](https://www.atlassian.com/git/tutorial/git-branches#!merge)。 542 | 新功能提交应该从不直接与`master`分支交互。 543 | 544 | ![](images/git-workflow-release-cycle-2feature.png) 545 | 546 | 注意,从各种含义和目的上来看,功能分支加上`develop`分支就是功能分支工作流的用法。但`Gitflow`工作流没有在这里止步。 547 | 548 | ### 2.3.4 发布分支 549 | 550 | ![](images/git-workflow-release-cycle-3release.png) 551 | 552 | 一旦`develop`分支上有了做一次发布(或者说快到了既定的发布日)的足够功能,就从`develop`分支上`checkout`一个发布分支。 553 | 新建的分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分支上—— 554 | 这个分支只应该做`Bug`修复、文档生成和其它面向发布任务。 555 | 一旦对外发布的工作都完成了,发布分支合并到`master`分支并分配一个版本号打好`Tag`。 556 | 另外,这些从新建发布分支以来的做的修改要合并回`develop`分支。 557 | 558 | 使用一个用于发布准备的专门分支,使得一个团队可以在完善当前的发布版本的同时,另一个团队可以继续开发下个版本的功能。 559 | 这也打造定义良好的开发阶段(比如,可以很轻松地说,『这周我们要做准备发布版本4.0』,并且在仓库的目录结构中可以实际看到)。 560 | 561 | 常用的分支约定: 562 | 563 | ``` 564 | 用于新建发布分支的分支: develop 565 | 用于合并的分支: master 566 | 分支命名: release-* 或 release/* 567 | ``` 568 | 569 | ### 2.3.5 维护分支 570 | 571 | ![](images/git-workflow-release-cycle-4maintenance.png) 572 | 573 | 维护分支或说是热修复(`hotfix`)分支用于给产品发布版本(`production releases`)快速生成补丁,这是唯一可以直接从`master`分支`fork`出来的分支。 574 | 修复完成,修改应该马上合并回`master`分支和`develop`分支(当前的发布分支),`master`分支应该用新的版本号打好`Tag`。 575 | 576 | 为`Bug`修复使用专门分支,让团队可以处理掉问题而不用打断其它工作或是等待下一个发布循环。 577 | 你可以把维护分支想成是一个直接在`master`分支上处理的临时发布。 578 | 579 | ### 2.3.6 示例 580 | 下面的示例演示本工作流如何用于管理单个发布循环。假设你已经创建了一个中央仓库。 581 | 582 | #### 创建开发分支 583 | 584 | ![](images/git-workflow-release-cycle-5createdev.png) 585 | 586 | 第一步为`master`分支配套一个`develop`分支。简单来做可以[本地创建一个空的`develop`分支](https://www.atlassian.com/git/tutorial/git-branches#!branch),`push`到服务器上: 587 | 588 | ```bash 589 | git branch develop 590 | git push -u origin develop 591 | ``` 592 | 593 | 以后这个分支将会包含了项目的全部历史,而`master`分支将只包含了部分历史。其它开发者这时应该[克隆中央仓库](https://www.atlassian.com/git/tutorial/git-basics#!clone),建好`develop`分支的跟踪分支: 594 | 595 | ```bash 596 | git clone ssh://user@host/path/to/repo.git 597 | git checkout -b develop origin/develop 598 | ``` 599 | 600 | 现在每个开发都有了这些历史分支的本地拷贝。 601 | 602 | #### 小红和小明开始开发新功能 603 | 604 | ![](images/git-workflow-release-cycle-6maryjohnbeginnew.png) 605 | 606 | 这个示例中,小红和小明开始各自的功能开发。他们需要为各自的功能创建相应的分支。新分支不是基于`master`分支,而是应该[基于`develop`分支](https://www.atlassian.com/git/tutorial/git-branches#!checkout): 607 | 608 | ```bash 609 | git checkout -b some-feature develop 610 | ``` 611 | 612 | 他们用老套路添加提交到各自功能分支上:编辑、暂存、提交: 613 | ```bash 614 | git status 615 | git add 616 | git commit 617 | ``` 618 | 619 | #### 小红完成功能开发 620 | 621 | ![](images/git-workflow-release-cycle-7maryfinishes.png) 622 | 623 | 添加了提交后,小红觉得她的功能OK了。如果团队使用`Pull Requests`,这时候可以发起一个用于合并到`develop`分支。 624 | 否则她可以直接合并到她本地的`develop`分支后`push`到中央仓库: 625 | 626 | ```bash 627 | git pull origin develop 628 | git checkout develop 629 | git merge some-feature 630 | git push 631 | git branch -d some-feature 632 | ``` 633 | 634 | 第一条命令在合并功能前确保`develop`分支是最新的。注意,功能决不应该直接合并到`master`分支。 635 | 冲突解决方法和[集中式工作流](workflow-centralized.md)一样。 636 | 637 | #### 小红开始准备发布 638 | 639 | ![](images/git-workflow-release-cycle-8maryprepsrelease.png) 640 | 641 | 这个时候小明正在实现他的功能,小红开始准备她的第一个项目正式发布。 642 | 像功能开发一样,她用一个新的分支来做发布准备。这一步也确定了发布的版本号: 643 | 644 | ```bash 645 | git checkout -b release-0.1 develop 646 | ``` 647 | 648 | 这个分支是清理发布、执行所有测试、更新文档和其它为下个发布做准备操作的地方,像是一个专门用于改善发布的功能分支。 649 | 650 | 只要小红创建这个分支并`push`到中央仓库,这个发布就是功能冻结的。任何不在`develop`分支中的新功能都推到下个发布循环中。 651 | 652 | #### 小红完成发布 653 | 654 | ![](images/git-workflow-release-cycle-9maryfinishes.png) 655 | 656 | 一旦准备好了对外发布,小红合并修改到`master`分支和`develop`分支上,删除发布分支。合并回`develop`分支很重要,因为在发布分支中已经提交的更新需要在后面的新功能中也要是可用的。 657 | 另外,如果小红的团队要求`Code Review`,这是一个发起`Pull Request`的理想时机。 658 | 659 | ```bash 660 | git checkout master 661 | git merge release-0.1 662 | git push 663 | git checkout develop 664 | git merge release-0.1 665 | git push 666 | git branch -d release-0.1 667 | ``` 668 | 669 | 发布分支是作为功能开发(`develop`分支)和对外发布(`master`分支)间的缓冲。只要有合并到`master`分支,就应该打好`Tag`以方便跟踪。 670 | 671 | ```bash 672 | git tag -a 0.1 -m "Initial public release" master 673 | git push --tags 674 | ``` 675 | 676 | `Git`有提供各种勾子(`hook`),即仓库有事件发生时触发执行的脚本。 677 | 可以配置一个勾子,在你`push`中央仓库的`master`分支时,自动构建好版本,并对外发布。 678 | 679 | #### 最终用户发现`Bug` 680 | 681 | ![](images/git-workflow-gitflow-enduserbug.png) 682 | 683 | 对外版本发布后,小红小明一起开发下一版本的新功能,直到有最终用户开了一个`Ticket`抱怨当前版本的一个`Bug`。 684 | 为了处理`Bug`,小红(或小明)从`master`分支上拉出了一个维护分支,提交修改以解决问题,然后直接合并回`master`分支: 685 | 686 | ```bash 687 | git checkout -b issue-#001 master 688 | # Fix the bug 689 | git checkout master 690 | git merge issue-#001 691 | git push 692 | ``` 693 | 694 | 就像发布分支,维护分支中新加这些重要修改需要包含到`develop`分支中,所以小红要执行一个合并操作。然后就可以安全地[删除这个分支](https://www.atlassian.com/git/tutorial/git-branches#!branch)了: 695 | 696 | ```bash 697 | git checkout develop 698 | git merge issue-#001 699 | git push 700 | git branch -d issue-#001 701 | ``` 702 | 703 | 到了这里,但愿你对[集中式工作流](workflow-centralized.md)、[功能分支工作流](workflow-feature-branch.md)和`Gitflow`工作流已经感觉很舒适了。 704 | 你应该也牢固的掌握了本地仓库的潜能,`push`/`pull`模式和`Git`健壮的分支和合并模型。 705 | 706 | 记住,这里演示的工作流只是可能用法的例子,而不是在实际工作中使用`Git`不可违逆的条例。 707 | 所以不要畏惧按自己需要对工作流的用法做取舍。不变的目标就是让`Git`为你所用。 708 | 709 | ----------------- 710 | 711 | ## 2.4 `Forking`工作流 712 | 713 | `Forking`工作流是分布式工作流,充分利用了`Git`在分支和克隆上的优势。可以安全可靠地管理大团队的开发者(`developer`),并能接受不信任贡献者(`contributor`)的提交。 714 | 715 | `Forking`工作流和前面讨论的几种工作流有根本的不同,这种工作流不是使用单个服务端仓库作为『中央』代码基线,而让各个开发者都有一个服务端仓库。这意味着各个代码贡献者有2个`Git`仓库而不是1个:一个本地私有的,另一个服务端公开的。 716 | 717 | ![](images/git-workflows-forking.png) 718 | 719 | `Forking`工作流的一个主要优势是,贡献的代码可以被集成,而不需要所有人都能`push`代码到仅有的中央仓库中。 720 | 开发者`push`到自己的服务端仓库,而只有项目维护者才能`push`到正式仓库。 721 | 这样项目维护者可以接受任何开发者的提交,但无需给他正式代码库的写权限。 722 | 723 | 效果就是一个分布式的工作流,能为大型、自发性的团队(包括了不受信的第三方)提供灵活的方式来安全的协作。 724 | 也让这个工作流成为开源项目的理想工作流。 725 | 726 | ### 2.4.1 工作方式 727 | 728 | 和其它的`Git`工作流一样,`Forking`工作流要先有一个公开的正式仓库存储在服务器上。 729 | 但一个新的开发者想要在项目上工作时,不是直接从正式仓库克隆,而是`fork`正式项目在服务器上创建一个拷贝。 730 | 731 | 这个仓库拷贝作为他个人公开仓库 —— 732 | 其它开发者不允许`push`到这个仓库,但可以`pull`到修改(后面我们很快就会看这点很重要)。 733 | 在创建了自己服务端拷贝之后,和之前的工作流一样,开发者执行[`git clone`命令](https://www.atlassian.com/git/tutorial/git-basics#!clone)克隆仓库到本地机器上,作为私有的开发环境。 734 | 735 | 要提交本地修改时,`push`提交到自己公开仓库中 —— 而不是正式仓库中。 736 | 然后,给正式仓库发起一个`pull request`,让项目维护者知道有更新已经准备好可以集成了。 737 | 对于贡献的代码,`pull request`也可以很方便地作为一个讨论的地方。 738 | 739 | 为了集成功能到正式代码库,维护者`pull`贡献者的变更到自己的本地仓库中,检查变更以确保不会让项目出错, 740 | [合并变更到自己本地的`master`分支](https://www.atlassian.com/git/tutorial/git-branches#!merge), 741 | 然后[`push`](https://www.atlassian.com/git/tutorial/remote-repositories#!push)`master`分支到服务器的正式仓库中。 742 | 到此,贡献的提交成为了项目的一部分,其它的开发者应该执行`pull`操作与正式仓库同步自己本地仓库。 743 | 744 | ### 2.4.2 正式仓库 745 | 746 | 在`Forking`工作流中,『官方』仓库的叫法只是一个约定,理解这点很重要。 747 | 从技术上来看,各个开发者仓库和正式仓库在`Git`看来没有任何区别。 748 | 事实上,让正式仓库之所以正式的唯一原因是它是项目维护者的公开仓库。 749 | 750 | ### 2.4.3 `Forking`工作流的分支使用方式 751 | 752 | 所有的个人公开仓库实际上只是为了方便和其它的开发者共享分支。 753 | 各个开发者应该用分支隔离各个功能,就像在[功能分支工作流](workflow-feature-branch.md)和[`Gitflow`工作流](workflow-forking.md)一样。 754 | 唯一的区别是这些分支被共享了。在`Forking`工作流中这些分支会被`pull`到另一个开发者的本地仓库中,而在功能分支工作流和`Gitflow`工作流中是直接被`push`到正式仓库中。 755 | 756 | ### 2.4.4 示例 757 | 758 | #### 项目维护者初始化正式仓库 759 | 760 | ![](images/git-workflows-forking-1.png) 761 | 762 | 和任何使用`Git`项目一样,第一步是创建在服务器上一个正式仓库,让所有团队成员都可以访问到。 763 | 通常这个仓库也会作为项目维护者的公开仓库。 764 | 765 | [公开仓库应该是裸仓库](https://www.atlassian.com/git/tutorial/git-basics#!init),不管是不是正式代码库。 766 | 所以项目维护者会运行像下面的命令来搭建正式仓库: 767 | 768 | ```bash 769 | ssh user@host 770 | git init --bare /path/to/repo.git 771 | ``` 772 | 773 | `Bitbucket`和`Stash`提供了一个方便的`GUI`客户端以完成上面命令行做的事。 774 | 这个搭建中央仓库的过程和前面提到的工作流完全一样。 775 | 如果有现存的代码库,维护者也要`push`到这个仓库中。 776 | 777 | #### 开发者`fork`正式仓库 778 | 779 | ![](images/git-workflows-forking-2.png) 780 | 781 | 其它所有的开发需要`fork`正式仓库。 782 | 可以用`git clone`命令[用`SSH`协议连通到服务器](https://confluence.atlassian.com/display/BITBUCKET/Set+up+SSH+for+Git), 783 | 拷贝仓库到服务器另一个位置 —— 是的,`fork`操作基本上就只是一个服务端的克隆。 784 | `Bitbucket`和`Stash`上可以点一下按钮就让开发者完成仓库的`fork`操作。 785 | 786 | 这一步完成后,每个开发都在服务端有一个自己的仓库。和正式仓库一样,这些仓库应该是裸仓库。 787 | 788 | #### 开发者克隆自己`fork`出来的仓库 789 | 790 | ![](images/git-workflows-forking-3.png) 791 | 792 | 下一步,各个开发者要克隆自己的公开仓库,用熟悉的`git clone`命令。 793 | 794 | 在这个示例中,假定用`Bitbucket`托管了仓库。记住,如果这样的话各个开发者需要有各自的`Bitbucket`账号, 795 | 使用下面命令克隆服务端自己的仓库: 796 | 797 | ```bash 798 | git clone https://user@bitbucket.org/user/repo.git 799 | ``` 800 | 801 | 相比前面介绍的工作流只用了一个`origin`远程别名指向中央仓库,`Forking`工作流需要2个远程别名 —— 802 | 一个指向正式仓库,另一个指向开发者自己的服务端仓库。别名的名字可以任意命名,常见的约定是使用`origin`作为远程克隆的仓库的别名 803 | (这个别名会在运行`git clone`自动创建),`upstream`(上游)作为正式仓库的别名。 804 | 805 | ```bash 806 | git remote add upstream https://bitbucket.org/maintainer/repo 807 | ``` 808 | 809 | 需要自己用上面的命令创建`upstream`别名。这样可以简单地保持本地仓库和正式仓库的同步更新。 810 | 注意,如果上游仓库需要认证(比如不是开源的),你需要提供用户: 811 | 812 | ```bash 813 | git remote add upstream https://user@bitbucket.org/maintainer/repo.git 814 | ``` 815 | 816 | 这时在克隆和`pull`正式仓库时,需要提供用户的密码。 817 | 818 | #### 开发者开发自己的功能 819 | 820 | ![](images/git-workflows-forking-4.png) 821 | 822 | 在刚克隆的本地仓库中,开发者可以像其它工作流一样的编辑代码、[提交修改](https://www.atlassian.com/git/tutorial/git-basics#!commit)和[新建分支](https://www.atlassian.com/git/tutorial/git-branches#!branch): 823 | 824 | ```bash 825 | git checkout -b some-feature 826 | # Edit some code 827 | git commit -a -m "Add first draft of some feature" 828 | ``` 829 | 830 | 所有的修改都是私有的直到`push`到自己公开仓库中。如果正式项目已经往前走了,可以用[`git pull`命令](https://www.atlassian.com/git/tutorial/remote-repositories#!pull)获得新的提交: 831 | 832 | ```bash 833 | git pull upstream master 834 | ``` 835 | 836 | 由于开发者应该都在专门的功能分支上工作,`pull`操作结果会都是[快进合并](https://www.atlassian.com/git/tutorial/git-branches#!merge)。 837 | 838 | #### 开发者发布自己的功能 839 | 840 | ![](images/git-workflows-forking-5.png) 841 | 842 | 一旦开发者准备好了分享新功能,需要做二件事。 843 | 首先,通过`push`他的贡献代码到自己的公开仓库中,让其它的开发者都可以访问到。 844 | 他的`origin`远程别名应该已经有了,所以要做的就是: 845 | 846 | ```bash 847 | git push origin feature-branch 848 | ``` 849 | 850 | 这里和之前的工作流的差异是,`origin`远程别名指向开发者自己的服务端仓库,而不是正式仓库。 851 | 852 | 第二件事,开发者要通知项目维护者,想要合并他的新功能到正式库中。 853 | `Bitbucket`和`Stash`提供了[`Pull Request`](https://confluence.atlassian.com/display/STASH/Using+pull+requests+in+Stash)按钮,弹出表单让你指定哪个分支要合并到正式仓库。 854 | 一般你会想集成你的功能分支到上游远程仓库的`master`分支中。 855 | 856 | #### 项目维护者集成开发者的功能 857 | 858 | ![](images/git-workflows-forking-6.png) 859 | 860 | 当项目维护者收到`pull request`,他要做的是决定是否集成它到正式代码库中。有二种方式来做: 861 | 862 | 1. 直接在`pull request`中查看代码 863 | 1. `pull`代码到他自己的本地仓库,再手动合并 864 | 865 | 第一种做法更简单,维护者可以在`GUI`中查看变更的差异,做评注和执行合并。 866 | 但如果出现了合并冲突,需要第二种做法来解决。这种情况下,维护者需要从开发者的服务端仓库中[`fetch`](https://www.atlassian.com/git/tutorial/remote-repositories#!fetch)功能分支, 867 | 合并到他本地的`master`分支,解决冲突: 868 | 869 | ```bash 870 | git fetch https://bitbucket.org/user/repo feature-branch 871 | # 查看变更 872 | git checkout master 873 | git merge FETCH_HEAD 874 | ``` 875 | 876 | 变更集成到本地的`master`分支后,维护者要`push`变更到服务器上的正式仓库,这样其它的开发者都能访问到: 877 | 878 | ```bash 879 | git push origin master 880 | ``` 881 | 882 | 注意,维护者的`origin`是指向他自己公开仓库的,即是项目的正式代码库。到此,开发者的贡献完全集成到了项目中。 883 | 884 | #### 开发者和正式仓库做同步 885 | 886 | ![](images/git-workflows-forking-7.png) 887 | 888 | 由于正式代码库往前走了,其它的开发需要和正式仓库做同步: 889 | 890 | ```bash 891 | git pull upstream master 892 | ``` 893 | 894 | 如果你之前是使用`SVN`,`Forking`工作流可能看起来像是一个激进的范式切换(paradigm shift)。 895 | 但不要害怕,这个工作流实际上就是在[功能分支工作流](workflow-feature-branch.md)之上引入另一个抽象层。 896 | 不是直接通过单个中央仓库来分享分支,而是把贡献代码发布到开发者自己的服务端仓库中。 897 | 898 | 示例中解释了,一个贡献如何从一个开发者流到正式的`master`分支中,但同样的方法可以把贡献集成到任一个仓库中。 899 | 比如,如果团队的几个人协作实现一个功能,可以在开发之间用相同的方法分享变更,完全不涉及正式仓库。 900 | 901 | 这使得`Forking`工作流对于松散组织的团队来说是个非常强大的工具。任一开发者可以方便地和另一开发者分享变更,任何分支都能有效地合并到正式代码库中。 902 | 903 | ----------------- 904 | 905 | ## 2.5 `Pull Requests` 906 | 907 | `Pull requests`是`Bitbucket`提供的让开发者更方便地进行协作的功能,提供了友好的`Web`界面可以在提议的修改合并到正式项目之前对修改进行讨论。 908 | 909 | ![](images/pull-request-bitbucket.png) 910 | 911 | 开发者向团队成员通知功能开发已经完成,`Pull Requests`是最简单的用法。 912 | 开发者完成功能开发后,通过`Bitbucket`账号发起一个`Pull Request`。 913 | 这样让涉及这个功能的所有人知道要去做`Code Review`和合并到`master`分支。 914 | 915 | 但是,`Pull Request`远不止一个简单的通知,而是为讨论提交的功能的一个专门论坛。 916 | 如果变更有任何问题,团队成员反馈在`Pull Request`中,甚至`push`新的提交微调功能。 917 | 所有的这些活动都直接跟踪在`Pull Request`中。 918 | 919 | ![](images/pull-request-overview.png) 920 | 921 | 相比其它的协作模型,这种分享提交的形式有助于打造一个更流畅的工作流。 922 | `SVN`和`Git`都能通过一个简单的脚本收到通知邮件;但是,讨论变更时,开发者通常只能去回复邮件。 923 | 这样做会变得杂乱,尤其还要涉及后面的几个提交时。 924 | `Pull Requests`把所有相关功能整合到一个和`Bitbucket`仓库界面集成的用户友好`Web`界面中。 925 | 926 | ### 2.5.1 解析`Pull Request` 927 | 928 | 当要发起一个`Pull Request`,你所要做的就是请求(`Request`)另一个开发者(比如项目的维护者) 929 | 来`pull`你仓库中一个分支到他的仓库中。这意味着你要提供4个信息以发起`Pull Request`: 930 | 源仓库、源分支、目的仓库、目的分支。 931 | 932 | ![](images/pull-request-anatomy.png) 933 | 934 | 这几值多数`Bitbucket`都会设置上合适的缺省值。但取决你用的协作工作流,你的团队可能会要指定不同的值。 935 | 上图显示了一个`Pull Request`请求合并一个功能分支到正式的`master`分支上,但可以有多种不同的`Pull Request`用法。 936 | 937 | ### 2.5.2 工作方式 938 | 939 | `Pull Request`可以和[功能分支工作流](workflow-feature-branch.md)、[`Gitflow`工作流](workflow-gitflow.md)或[`Forking`工作流](workflow-forking.md)一起使用。 940 | 但一个`Pull Request`要求要么分支不同要么仓库不同,所以不能用于[集中式工作流](workflow-centralized.md)。 941 | 在不同的工作流中使用`Pull Request`会有一些不同,但基本的过程是这样的: 942 | 943 | 1. 开发者在本地仓库中新建一个专门的分支开发功能。 944 | 2. 开发者`push`分支修改到公开的`Bitbucket`仓库中。 945 | 3. 开发者通过`Bitbucket`发起一个`Pull Request`。 946 | 4. 团队的其它成员`review` `code`,讨论并修改。 947 | 5. 项目维护者合并功能到官方仓库中并关闭`Pull Request`。 948 | 949 | 本文后面内容说明,`Pull Request`在不同协作工作流中如何应用。 950 | 951 | ### 2.5.3 在功能分支工作流中使用`Pull Request` 952 | 953 | 功能分支工作流用一个共享的`Bitbucket`仓库来管理协作,开发者在专门的分支上开发功能。 954 | 但不是立即合并到`master`分支上,而是在合并到主代码库之前开发者应该开一个`Pull Request`发起功能的讨论。 955 | 956 | ![](images/pull-request-feature-branch.png) 957 | 958 | 功能分支工作流只有一个公开的仓库,所以`Pull Request`的目的仓库和源仓库总是同一个。 959 | 通常开发者会指定他的功能分支作为源分支,`master`分支作为目的分支。 960 | 961 | 收到`Pull Request`后,项目维护者要决定如何做。如果功能没问题,就简单地合并到`master`分支,关闭`Pull Request`。 962 | 但如果提交的变更有问题,他可以在`Pull Request`中反馈。之后新加的提交也会评论之后接着显示出来。 963 | 964 | 在功能还没有完全开发完的时候,也可能发起一个`Pull Request`。 965 | 比如开发者在实现某个需求时碰到了麻烦,他可以发一个包含正在进行中工作的`Pull Request`。 966 | 其它的开发者可以在`Pull Request`提供建议,或者甚至直接添加提交来解决问题。 967 | 968 | ### 2.5.4 在`Gitflow`工作流中使用`Pull Request` 969 | 970 | `Gitflow`工作流和功能分支工作流类似,但围绕项目发布定义一个严格的分支模型。 971 | 在`Gitflow`工作流中使用`Pull Request`让开发者在发布分支或是维护分支上工作时, 972 | 可以有个方便的地方对关于发布分支或是维护分支的问题进行交流。 973 | 974 | ![](images/gitflow-workflow-pull-request.png) 975 | 976 | `Gitflow`工作流中`Pull Request`的使用过程和上一节中完全一致: 977 | 当一个功能、发布或是热修复分支需要`Review`时,开发者简单发起一个`Pull Request`, 978 | 团队的其它成员会通过`Bitbucket`收到通知。 979 | 980 | 新功能一般合并到`develop`分支,而发布和热修复则要同时合并到`develop`分支和`master`分支上。 981 | `Pull Request`可能用做所有合并的正式管理。 982 | 983 | ### 2.5.5 在`Forking`工作流中使用`Pull Request` 984 | 985 | 在`Forking`工作流中,开发者`push`完成的功能到他自己的仓库中,而不是共享仓库。 986 | 然后,他发起一个`Pull Request`,让项目维护者知道他的功能已经可以`Review`了。 987 | 988 | 在这个工作流,`Pull Request`的通知功能非常有用, 989 | 因为项目维护者不可能知道其它开发者在他们自己的仓库添加了提交。 990 | 991 | ![](images/pull-request-forking-workflow-1.png) 992 | 993 | 由于各个开发有自己的公开仓库,`Pull Request`的源仓库和目标仓库不是同一个。 994 | 源仓库是开发者的公开仓库,源分支是包含了修改的分支。 995 | 如果开发者要合并修改到正式代码库中,那么目标仓库是正式仓库,目标分支是`master`分支。 996 | 997 | `Pull Request`也可以用于正式项目之外的其它开发者之间的协作。 998 | 比如,如果一个开发者和一个团队成员一起开发一个功能,他们可以发起一个`Pull Request`, 999 | 用团队成员的`Bitbucket`仓库作为目标,而不是正式项目的仓库。 1000 | 然后使用相同的功能分支作为源和目标分支。 1001 | 1002 | ![](images/pull-request-forking-workflow-2.png) 1003 | 1004 | 2个开发者之间可以在`Pull Request`中讨论和开发功能。 1005 | 完成开发后,他们可以发起另一个`Pull Request`,请求合并功能到正式的`master`分支。 1006 | 在`Forking`工作流中,这样的灵活性让`Pull Request`成为一个强有力的协作工具。 1007 | 1008 | ### 2.5.6 示例 1009 | 1010 | 下面的示例演示了`Pull Request`如何在在`Forking`工作流中使用。 1011 | 也同样适用于小团队的开发协作和第三方开发者向开源项目的贡献。 1012 | 1013 | 在示例中,小红是个开发,小明是项目维护者。他们各自有一个公开的`Bitbucket`仓库,而小明的仓库包含了正式工程。 1014 | 1015 | #### 小红`fork`正式项目 1016 | 1017 | ![](images/pull-request-1.png) 1018 | 1019 | 小红先要`fork`小明的`Bitbucket`仓库,开始项目的开发。她登陆`Bitbucket`,浏览到小明的仓库页面, 1020 | 点`Fork`按钮。 1021 | 1022 | ![](images/pull-request-2.png) 1023 | 1024 | 然后为`fork`出来的仓库填写名字和描述,这样小红就有了服务端的项目拷贝了。 1025 | 1026 | #### 小红克隆她的`Bitbucket`仓库 1027 | 1028 | ![](images/pull-request-3.png) 1029 | 1030 | 下一步,小红克隆自己刚才`fork`出来的`Bitbucket`仓库,以在本机上准备出工作拷贝。命令如下: 1031 | 1032 | ```bash 1033 | git clone https://user@bitbucket.org/user/repo.git 1034 | ``` 1035 | 1036 | 请记住,`git clone`会自动创建`origin`远程别名,是指向小红`fork`出来的仓库。 1037 | 1038 | #### 小红开发新功能 1039 | 1040 | ![](images/pull-request-4.png) 1041 | 1042 | 在开始改代码前,小红要为新功能先新建一个新分支。她会用这个分支作为`Pull Request`的源分支。 1043 | 1044 | ```bash 1045 | git checkout -b some-feature 1046 | # 编辑代码 1047 | git commit -a -m "Add first draft of some feature" 1048 | ``` 1049 | 1050 | 在新功能分支上,小红按需要添加提交。甚至如果小红觉得功能分支上的提交历史太乱了,她可以用[交互式`rebase`](https://www.atlassian.com/git/tutorial/rewriting-git-history#!rebase-i)来删除或压制提交。 1051 | 对于大型项目,整理功能分支的历史可以让项目维护者更容易看出在`Pull Request`中做了什么内容。 1052 | 1053 | #### 小红`push`功能到她的`Bitbucket`仓库中 1054 | 1055 | ![](images/pull-request-5.png) 1056 | 1057 | 小红完成了功能后,`push`功能到她自己的`Bitbucket`仓库中(不是正式仓库),用下面简单的命令: 1058 | 1059 | ```bash 1060 | git push origin some-branch 1061 | ``` 1062 | 1063 | 这时她的变更可以让项目维护者看到了(或者任何想要看的协作者)。 1064 | 1065 | #### 小红发起`Pull Request` 1066 | 1067 | ![](images/example-6.png) 1068 | 1069 | `Bitbucket`上有了她的功能分支后,小红可以用她的`Bitbucket`账号浏览到她的`fork`出来的仓库页面, 1070 | 点右上角的【`Pull Request`】按钮,发起一个`Pull Request`。 1071 | 弹出的表单自动设置小红的仓库为源仓库,询问小红以指定源分支、目标仓库和目标分支。 1072 | 1073 | 小红想要合并功能到正式仓库,所以源分支是她的功能分支,目标仓库是小明的公开仓库, 1074 | 而目标分支是`master`分支。另外,小红需要提供`Pull Request`的标题和描述信息。 1075 | 如果需要小明以外的人审核批准代码,她可以把这些人填在【Reviewers】文本框中。 1076 | 1077 | ![](images/pull-request-7.png) 1078 | 1079 | 创建好了`Pull Request`,通知会通过`Bitbucket`系统消息或邮件(可选)发给小明。 1080 | 1081 | #### 小明review `Pull Request` 1082 | 1083 | ![](images/pull-request-8.png) 1084 | 1085 | 在小明的`Bitbucket`仓库页面的【`Pull Request`】Tab可以看到所有人发起的`Pull Request`。 1086 | 点击小红的`Pull Request`会显示出`Pull Request`的描述、功能的提交历史和每个变更的差异(`diff`)。 1087 | 1088 | 如果小明想要合并到项目中,只要点一下【`Merge`】按钮,就可以同意`Pull Request`并合并到`master`分支。 1089 | 1090 | 但如果像这个示例中一样小明发现了在小红的代码中的一个小`Bug`,要小红在合并前修复。 1091 | 小明可以在整个`Pull Request`上加上评注,或是选择历史中的某个提交加上评注。 1092 | 1093 | ![](images/pull-request-9.png) 1094 | 1095 | #### 小红补加提交 1096 | 1097 | 如果小红对反馈有任何疑问,可以在`Pull Request`中响应,把`Pull Request`当作是她功能讨论的论坛。 1098 | 1099 | 小红在她的功能分支新加提交以解决代码问题,并`push`到她的`Bitbucket`仓库中,就像前一轮中的做法一样。 1100 | 这些提交会进入的`Pull Request`,小明在原来的评注旁边可以再次`review`变更。 1101 | 1102 | #### 小明接受`Pull Request` 1103 | 1104 | 最终,小明接受变更,合并功能分支到`Master`分支,并关闭`Pull Request`。 1105 | 至此,功能集成到项目中,其它的项目开发者可以用标准的`git pull`命令`pull`这些变更到自己的本地仓库中。 1106 | 1107 | 1108 | 到了这里,你应该有了所有需要的工具来集成`Pull Request`到你自己的工作流。 1109 | 请记住,`Pull Request`并不是为了替代任何 `基于`Git`的协作工作流`, 1110 | 而是它们的一个便利的补充,让团队成员间的协作更轻松方便。 1111 | 1112 | ----------------- 1113 | 1114 | # 三、企业日常开发模式探索 1115 | 1116 | 在看这部分前,请先回顾阅读业界认可的成功的 Git Branch Work Flow 模型 [A Successful Git Branching Model](http://nvie.com/posts/a-successful-git-branching-model/) ,了解日常开发中的场景,有助于熟悉下面的使用过程。 1117 | 1118 | 在企业开发中,使用 Git 作为版本控制软件最看重的还是结合公司自己搭建的 [Gitlab](https://about.gitlab.com/),将 Code Review 加入打包部署持续集成的流程中,这样,代码开发完成,提交测试前,便可以对开发人员提交的代码进行 Review,发现潜在的问题,及时指导,对于新人来讲,也能更快更好的学习。 1119 | 1120 | 解决的需求场景如下: 1121 | 1122 | - 能支持日常迭代开发、紧急线上bug修复、多功能并行开发 1123 | - 大概50人左右的团队,平日迭代项目较多,且周期短(1~2周一个迭代) 1124 | - 能够通过tag重建整个系统 1125 | - 支持code review 1126 | - 所有上线的代码必须都是经过测试保证,且能自动同步到下一次的迭代中 1127 | - 能和公司的项目管理/持续集成系统整合 1128 | 1129 | ![图片](images/branch_module.png) 1130 | 1131 | 上图就是 xirong 团队在日常开发中总结出来的适合企业开发的模式,下面进行简单的介绍,方便大家学习了解,欢迎提交 Issue 进行讨论。(本模式适合敏捷开发流程,小迭代上线,传统的瀑布开发模型并没有进行测试) 1132 | 1133 | 1. 迭代需求会、冲刺会后确定本次迭代的目标后,将迭代内容视为一个项目,在 Gitlab 上创建一个 Repository,初始化工程代码结构,根据上线日期,比如20150730上线,开出分支 release20150730、dev20150730 两个分支,dev 分支作为日常开发主干分支,release 分支作为提测打包、Code Review 的分支。 1134 | 2. 迭代开始,日常开发进行中,开发人员在 dev 分支上进行 Commit、Push 代码,并且解决掉日常协同开发中的冲突等问题,等到达到提测条件的时候,提测者,首先 Merge Master 分支上的最新代码 `git merge --no-ff origin/master` ,使得 Master 分支上的变更更新到迭代开发分支dev上面,之后,在 Gitlab 上面发起 `pull request` 请求,并指定 Code Review 人,请求的分支选择本次上线的 release 分支,即 release20150730。 1135 | 3. 被指定 Code Review 的人,对发起者的代码 Review 后,决定是否可以提交测试,若有问题,评论注释代码后,提交者对代码进行进行修改,重复步骤2,直到代码 Review 者认为 Ok。之后便可以借助自己公司的打包部署,对这些代码发布到测试环境验证。 1136 | 4. 步骤2-3重复多次后,就会达到一个稳定可发布的版本,即上线版本,上线后,将 release 版本上面最后的提交(图中0.2.4上线对应处)合并到 Master 分支上面,并打 Tag0.3。至此,一次完整的迭代开发完成。 1137 | 5. 若此次上线后,不久发现生产环境有 Bug 需要修复,则从 Tag 处新开分支 release_bugfix_20150731、dev_bugfix_20150731 ,开发人员从 dev_bugfix_20150731分支上进行开发,提测code review在 release_bugfix_20150731 分支上,具体步骤参考2-3,测试环境验证通过后,发布到线上,验证OK,合并到 Master 分支,并打 Tag0.2.3,此次 Bug 修复完毕,专为解 Bug 而生的这两个分支可以退伍了,删除release_bugfix_20150731、dev_bugfix_20150731两分支即可。(所有的历史 Commit 信息均已经提交到了 Master 分支上,不用担心丢失) 1138 | 1139 | 这样经过上面的1-5步骤,企业日常迭代开发中的代码版本控制基本上就 Ok 了,有问题欢迎 Issue 讨论。 1140 | 1141 | 2016-11月 更新 **Git 分支开发部署模型** 的一些使用原则如下: 1142 | 1143 | ![](_image/2016-09-22-20-57-27.jpg) 1144 | 1145 | - master:master永远是线上代码,最稳定的分支,存放的是随时可供在生产环境中部署的代码,当开发活动告一段落,产生了一份新的可供部署的代码时,发布成功之后,代码才会由 aone2 提交到 master,master 分支上的代码会被更新。应用上 aone2 后禁掉所有人的 master的写权限 1146 | - develop:保存当前最新开发成果的分支。通常这个分支上的代码也是可进行每日夜间发布的代码,只对开发负责人开放develop权限。 1147 | - feature: 功能特性分支,每个功能特性一个 feature/ 分支,开发完成自测通过后合并入 develop 分支。可以从 master 或者develop 中拉出来。 1148 | - hotfix: 紧急bug分支修复分支。修复上线后,可以直接合并入master。 1149 | 1150 | ![](_image/2016-07-19-19-58-15.jpg) 1151 | 1152 | Git-Develop 分支模式是基于 Git 代码库设计的一种需要严格控制发布质量和发布节奏的开发模式。develop 作为固定的持续集成和发布分支,并且分支上的代码必须经过 CodeReview 后才可以提交到 Develop 分支。它的基本流程如下: 1153 | - 每一个需求/变更都单独从Master上创建一条Branch分支; 1154 | - 用户在这个Branch分支上进行Codeing活动; 1155 | - 代码达到发布准入条件后aone上提交Codereview,Codereview通过后代码自动合并到Develop分支; 1156 | - 待所有计划发布的变更分支代码都合并到Develop后,系统再 rebase master 代码到Develop 分支,然后自行构建,打包,部署等动作。 1157 | - 应用发布成功后Aone会基于Develop分支的发布版本打一个“当前线上版本Tag”基线; 1158 | - 应用发布成功后Aone会自动把Develop分支的发布版本合并回master; 1159 | 1160 | # 四、开发工作流的讨论 1161 | 几篇业界的讨论文章 1162 | - [Gitflow 有害论](http://insights.thoughtworkers.org/gitflow-consider-harmful/) 作者对 Gitflow 流程的使用过程中的吐槽,文章留言引起了强烈的讨论,可以关注下。 1163 | - [GitHub Flow](http://scottchacon.com/2011/08/31/github-flow.html) scottchacon 讲述在 GitHub 工作中日常流程以及对每一点进行详细的介绍。 1164 | - [谷歌的代码管理](http://www.ruanyifeng.com/blog/2016/07/google-monolithic-source-repository.html) 谷歌和 Facebook 都只有一个代码仓库,全公司的代码都放在这个库里,这里是阮一峰老师写的文章。 1165 | - [Why Google Stores Billions of Lines of Code in a Single Repository](http://cacm.acm.org/magazines/2016/7/204032-why-google-stores-billions-of-lines-of-code-in-a-single-repository/fulltext) 1166 | -------------------------------------------------------------------------------- /how-to-use-github.md: -------------------------------------------------------------------------------- 1 | 2 | 说明 3 | ============== 4 | 作为一名开发者,GitHub上面有很多东西值得关注学习,可是刚刚接触GitHub,怎样一步步学习使用GitHub?怎样更高效的利用GitHub? 5 | 在这里搜集整理网络上面的资料,汇总成这么一篇repo 《GitHub使用指南》,供大家一起学习。 :octocat: 6 | 7 | - [GitHub 入门使用教程-图文并茂](http://developer.51cto.com/art/201407/446249_all.htm) 很简洁的说明如何使用,看图即可明白。 8 | - [GitHub help](https://help.github.com/) Sometimes you just need a little help. 中文翻译版在此[GitHub 帮助文档](https://github.com/waylau/github-help)。 9 | - [GitHub 之 fork 简介指南](https://linux.cn/article-4292-1.html) 帮你理解清楚什么是fork,fork 的工作流有哪些。 10 | - [GitHub-cheat-sheet](https://github.com/tiimgreen/github-cheat-sheet) 关于使用 git 和 GitHub 的一些技巧汇总,中文版在此[GitHub秘籍](https://github.com/tiimgreen/github-cheat-sheet/blob/master/README.zh-cn.md) 11 | - [The GitHub Blog](https://github.com/blog) GitHub 官方博客,关注最新动态。 12 | - [How to Build a GitHub](http://zachholman.com/talk/how-to-build-a-github/) GitHub一名早期员工介绍GitHub的历史,5年108名员工无人离职。 13 | - [阳志平:如何高效利用GitHub](http://www.yangzhiping.com/tech/github.html) 介绍的挺全,以及一些用法,如怎样利用GitHub来学习、演讲找工作等。 14 | - [GitHub 支持的 emoji表情 emoji-cheat-sheet](http://www.emoji-cheat-sheet.com/) :v: :clap: 感觉不好找到需要的表情?试试[Emoji Searcher](http://emoji.muan.co/) 15 | - [x] [GitHub guides](https://guides.github.com/) 从`Contributing to Open Source on GitHub`、`Hello World`、`Forking Projects`、`Be Social`、`Making Your Code Citable`、`Mastering Issues`、`Mastering Markdown`、`Mastering Wikis`、`Getting Started with GitHub Pages` 等9个方面图文详细讲解每一步如何使用,以及能做哪些功能。 16 | - [fork-me-on-GitHub](https://github.com/blog/273-github-ribbons) 个人博客、技术博客等如果需要添加GitHub 的彩带,可以使用此方法。 17 | - [蒋鑫-GotGitHub](GotGitHub.md) 《Git权威指南》的作者,对GitHub有很深的了解。(由于首页打开太慢,放到了本文目录中,下面的文章既是) 18 | 19 | # GitHub Skills 20 | 21 | - [Using Git blame to trace changes in a file](https://help.github.com/articles/using-git-blame-to-trace-changes-in-a-file/) 如果你想看某一个文件中每一行是谁修改的,为什么修改?那么尽情的使用 `blame` 按钮,发现文件的历史。 22 | - [GitHub 搜索技巧](https://help.github.com/categories/search/) 23 | - [Closing issues via commit messages - 通过提交信息关闭Issues](https://help.github.com/articles/closing-issues-via-commit-messages/) 24 | - [Update your forked code from original repository - 如何更新自己 Fork 的代码](https://github.com/ysc/APDPlat/wiki/%E5%A6%82%E4%BD%95%E6%9B%B4%E6%96%B0%E8%87%AA%E5%B7%B1Fork%E7%9A%84%E4%BB%A3%E7%A0%81) 25 | 26 | 更多关于 GitHub 的内容请查看:[GitHubHelp](https://help.github.com/) 查找需要的信息。 27 | 28 | -------- 29 | 30 | 原文地址:http://www.worldhello.net/gotgithub/index.html 31 | 32 |

GotGitHub

33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
Author:Jiang Xin
Version:v0.9.1-13-g5075479
Copyright:Creative Commons BY-NC-SA
45 |
46 |

前言

47 |

动笔写GitHub不是因为我对其了解,恰恰是对其太不了解。

48 |

在我的《Git权威指南》 [1] 一书中,涉及到GitHub的只有区区三页纸,这显然回答不了读者对于GitHub的诸多疑问。 49 | 记得在《Git权威指南》刚刚完稿之际,机械工业出版社华章公司的杨福川编辑就鼓动我写一本关于GitHub的书,我用了好多理由推辞了。 50 | 头条理由就是我真的累着了。在每一章节开始动笔之时,都好像是坐在了中学语文考试的考堂上写作文,时间快到了可仍然动不了笔, 51 | 再写一本书无疑要重复这一痛苦的经历。 52 | 第二个理由是我更喜欢编程,而不是写文档,尤其写GitHub会有大量截图、图像处理的琐碎工作。 53 | 第三个理由彻底让编辑投降,那就是GitHub是一个国外网站,也许书一出,【此句已被原作者删除】。

54 |

让我最终决定动笔,是源于CSDN蒋总在美国拜访GitHub总部后告诉我的一些见闻,我对GitHub如此成功运作产生了兴趣,于是开始研究GitHub的博客,愈发发现GitHub是一群有趣的人在做的有趣的事,如果只把GitHub当作一个Git服务器,实在是暴殄天物。GitHub已经并将继续获得成功,若真能凭借此书把GitHub尽量全面地展现,让每一个Git使用者用好GitHub也是一件幸事。

55 |

这本书将采用GitHub的方式进行撰写和发布 [2] ,任何人都可以看到本书(包括源码),更可以用GitHub的方法参与本书的撰写和纠错。网络出版对于我和杨福川编辑都是一个全新的体验。感谢Git,让我在一年内拥有了两种不同的出版体验。

56 |

– 蒋鑫, 2011.12

57 |
58 | 59 | 60 | 61 | 62 | 63 |
[1]http://www.worldhello.net/gotgit/
64 | 65 | 66 | 67 | 68 | 69 |
[2]https://github.com/gotgit/gotgithub
70 |
71 |
72 |

目录

73 |
74 | 199 |
200 | 201 | -------------------------------------------------------------------------------- /images/branch_module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/branch_module.png -------------------------------------------------------------------------------- /images/example-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/example-6.png -------------------------------------------------------------------------------- /images/git-workflow-feature-branch-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-feature-branch-1.png -------------------------------------------------------------------------------- /images/git-workflow-feature-branch-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-feature-branch-2.png -------------------------------------------------------------------------------- /images/git-workflow-feature-branch-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-feature-branch-3.png -------------------------------------------------------------------------------- /images/git-workflow-feature-branch-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-feature-branch-4.png -------------------------------------------------------------------------------- /images/git-workflow-feature-branch-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-feature-branch-5.png -------------------------------------------------------------------------------- /images/git-workflow-feature-branch-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-feature-branch-6.png -------------------------------------------------------------------------------- /images/git-workflow-feature-branch-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-feature-branch-7.png -------------------------------------------------------------------------------- /images/git-workflow-feature_branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-feature_branch.png -------------------------------------------------------------------------------- /images/git-workflow-forking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-forking.png -------------------------------------------------------------------------------- /images/git-workflow-gitflow-enduserbug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-gitflow-enduserbug.png -------------------------------------------------------------------------------- /images/git-workflow-release-cycle-1historical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-release-cycle-1historical.png -------------------------------------------------------------------------------- /images/git-workflow-release-cycle-2feature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-release-cycle-2feature.png -------------------------------------------------------------------------------- /images/git-workflow-release-cycle-3release.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-release-cycle-3release.png -------------------------------------------------------------------------------- /images/git-workflow-release-cycle-4maintenance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-release-cycle-4maintenance.png -------------------------------------------------------------------------------- /images/git-workflow-release-cycle-5createdev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-release-cycle-5createdev.png -------------------------------------------------------------------------------- /images/git-workflow-release-cycle-6maryjohnbeginnew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-release-cycle-6maryjohnbeginnew.png -------------------------------------------------------------------------------- /images/git-workflow-release-cycle-7maryfinishes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-release-cycle-7maryfinishes.png -------------------------------------------------------------------------------- /images/git-workflow-release-cycle-8maryprepsrelease.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-release-cycle-8maryprepsrelease.png -------------------------------------------------------------------------------- /images/git-workflow-release-cycle-9maryfinishes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-release-cycle-9maryfinishes.png -------------------------------------------------------------------------------- /images/git-workflow-svn-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-1.png -------------------------------------------------------------------------------- /images/git-workflow-svn-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-2.png -------------------------------------------------------------------------------- /images/git-workflow-svn-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-3.png -------------------------------------------------------------------------------- /images/git-workflow-svn-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-4.png -------------------------------------------------------------------------------- /images/git-workflow-svn-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-5.png -------------------------------------------------------------------------------- /images/git-workflow-svn-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-6.png -------------------------------------------------------------------------------- /images/git-workflow-svn-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-7.png -------------------------------------------------------------------------------- /images/git-workflow-svn-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-8.png -------------------------------------------------------------------------------- /images/git-workflow-svn-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-9.png -------------------------------------------------------------------------------- /images/git-workflow-svn-clone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-clone.png -------------------------------------------------------------------------------- /images/git-workflow-svn-initialize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-initialize.png -------------------------------------------------------------------------------- /images/git-workflow-svn-managingconflicts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-managingconflicts.png -------------------------------------------------------------------------------- /images/git-workflow-svn-push-local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn-push-local.png -------------------------------------------------------------------------------- /images/git-workflow-svn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflow-svn.png -------------------------------------------------------------------------------- /images/git-workflows-forking-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflows-forking-1.png -------------------------------------------------------------------------------- /images/git-workflows-forking-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflows-forking-2.png -------------------------------------------------------------------------------- /images/git-workflows-forking-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflows-forking-3.png -------------------------------------------------------------------------------- /images/git-workflows-forking-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflows-forking-4.png -------------------------------------------------------------------------------- /images/git-workflows-forking-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflows-forking-5.png -------------------------------------------------------------------------------- /images/git-workflows-forking-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflows-forking-6.png -------------------------------------------------------------------------------- /images/git-workflows-forking-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflows-forking-7.png -------------------------------------------------------------------------------- /images/git-workflows-forking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflows-forking.png -------------------------------------------------------------------------------- /images/git-workflows-gitflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git-workflows-gitflow.png -------------------------------------------------------------------------------- /images/git_workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/git_workflow.png -------------------------------------------------------------------------------- /images/gitflow-workflow-pull-request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/gitflow-workflow-pull-request.png -------------------------------------------------------------------------------- /images/pull-request-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-1.png -------------------------------------------------------------------------------- /images/pull-request-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-2.png -------------------------------------------------------------------------------- /images/pull-request-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-3.png -------------------------------------------------------------------------------- /images/pull-request-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-4.png -------------------------------------------------------------------------------- /images/pull-request-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-5.png -------------------------------------------------------------------------------- /images/pull-request-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-7.png -------------------------------------------------------------------------------- /images/pull-request-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-8.png -------------------------------------------------------------------------------- /images/pull-request-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-9.png -------------------------------------------------------------------------------- /images/pull-request-anatomy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-anatomy.png -------------------------------------------------------------------------------- /images/pull-request-bitbucket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-bitbucket.png -------------------------------------------------------------------------------- /images/pull-request-feature-branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-feature-branch.png -------------------------------------------------------------------------------- /images/pull-request-forking-workflow-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-forking-workflow-1.png -------------------------------------------------------------------------------- /images/pull-request-forking-workflow-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-forking-workflow-2.png -------------------------------------------------------------------------------- /images/pull-request-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request-overview.png -------------------------------------------------------------------------------- /images/pull-request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xirong/my-git/5b7e2339bacab835b8fdd3459506653fdf33edc8/images/pull-request.png -------------------------------------------------------------------------------- /ixirong.com.md: -------------------------------------------------------------------------------- 1 | 原文出自:http://ixirong.com/2014/11/19/the-way-to-learn-git/ 2 | 3 | ## 一、什么是git? 4 | 5 | > Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. 6 | 7 | [git维基百科](http://zh.wikipedia.org/wiki/Git)上详细介绍了git的资料,包括git的创建、使用以及一些参考资料,已经挺全了,记住一点,最高效的学习方式就是**读文档**,找官方文档去阅读学习是最快的掌握git的方法。 8 | 9 | 既然是分布式版本管理,那么和我们平常使用的svn有什么区别? 10 | 1. 分布式 vs 集中管理 (多份版本库 vs 一份版本库,设想下版本服务器挂了?) 11 | 2. 无需网络,随时随地进行版本控制,在没有网络的情况下你想回退到某个版本svn基本没戏; 12 | 3. 分支的新建、合并非常方便、快速,没有任何成本,基本不耗时,svn的版本基本上等同于又复制了一份代码; 13 | 14 | **stackoverflow** 上关于svn和git的区别的讨论,说的很详细,请参考 [Why is Git better than Subversion?](http://stackoverflow.com/questions/871/why-is-git-better-than-subversion) 15 | **github** 上通过版本库结构、历史、子项目(submudle)的不同来对比两者,请参考 [What are the differences between SVN and Git?](https://help.github.com/articles/what-are-the-differences-between-svn-and-git/) 16 | 17 | ## 二、git 安装 18 | 《pro git》一书中已经写明白了[各个平台上怎么安装git](http://git-scm.com/book/zh/v1/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git),如果感觉晦涩,就看这个[廖雪峰安装git](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137396287703354d8c6c01c904c7d9ff056ae23da865a000) 19 | 20 | ## 三、git 初使用 21 | - 对于已经熟悉svn的用户可以直接查看此文档 [Git - SVN Crash Course](http://git.or.cz/course/svn.html),通过对比两个工具对同样的操作采取不同的命令来快速认识git的一些常用命令 22 | 23 | - 对于一个新手来说,我不需要知道git的原理,不需要知道git那么多的命令,我只想用git完成一次仓库的从初始化、commit、push、branch、tag等一个流程,越简单越好,图文教程,以window下使用git为例,一步步走完整个流程,推荐 [手把手教你使用Git](http://blog.jobbole.com/78960/) 24 | 25 | - 比较全面讲述的git的系列文章 [号称史上最浅显易懂的Git教程!](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) 26 | 27 | - 看完上面的几步内容,想你习对git基本上可以使用了,要掌握还得多多练习,熟能生巧,你是不是想去看看关于git的全部内容 ,[官方中文电子版书籍](http://git-scm.com/book/zh/v1)即可满足你,当然你可以查看最新[V2版英文](http://git-scm.com/book/en/v2)或者下载epub pdf等本地阅读; 28 | 29 | ## 四、git 分支、tag 30 | git 最帅气的就是对分支的处理,方便快速,你只需要一个简单的 31 | ``` bash 32 | git branch branch-name 33 | ``` 34 | 就能开出一个叫branch-name的分支,毫秒钟搞定,但也正是因为方便,如果使用不合理就会造成**分支混乱,分不清脉络**, 推荐看一下阮一峰写的文章 [Git分支管理策略](http://www.ruanyifeng.com/blog/2012/07/git.html) ,最原始的文章就是这篇老外写的[A successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/),[@萌面大叔的乌托邦]()提到开源中国已经翻译成了中文,感兴趣的可以去看看[介绍一个成功的 Git 分支模型](http://www.oschina.net/translate/a-successful-git-branching-model) 35 | 36 | ![杂乱的分支](http://static.ixirong.com/pic/git/git-branchs-messy.webp) 37 | 38 | ## 五、git 常见命令 39 | 一个比较好的汇总了git的一些基本命令的pdf,可以经常看看,或者当成命令手册,推荐 [Git Cheat Sheet](http://www.cheat-sheets.org/saved-copy/git-cheat-sheet.pdf) ,还有一张图片 [Git常用命令](http://www.cnblogs.com/1-2-3/archive/2010/07/18/git-commands.html) 也不错;最近我整理了一份xmind的导图,将**这两份**资料都放到了画布里面,[百度网盘](http://pan.baidu.com/s/1c052yVu) 密码:`6x7u` 存储了,不断更新,有需要的可以下载,预览图片如下: 40 | 41 | ![Git常用xmind导图整理](http://static.ixirong.com/pic/git/git-xmind.webp) 42 | 43 | 最强大的**命令手册**还得属于终端,* man git * 或者 * man git 命令 * 或者 * git --help * 或者 * git 命令 --help *,在这里可以找到任何你想要的。 44 | 45 | ## 六、git 书籍资料 46 | -《[Pro Git](http://git-scm.com/book/zh/v1)》 作者Scott Chacon是github的员工,git的布道者,这本书被誉为git学习圣经,中间有好多插图描述的浅显易懂,挺适合详细学习下的,最新英文第二版《[pro git (Editon 2)](http://git-scm.com/book/en/v2)》; 47 | 48 | -《[Git Community Book](http://gitbook.liuhui998.com/)》汇聚了Git社区的很多精华, 并对git的对象模型原理等做了解释,可以深入的了解下git原理; 49 | 50 | 2015-01-22 增加 51 | - 推荐的工作流程 [git workflow](http://documentup.com/skwp/git-workflows-book) 52 | 53 | 2015-04-05 增加 git flow 工具 54 | - [git flow 工具](https://github.com/nvie/gitflow) 55 | - [git flow 中文备忘清单](http://danielkummer.github.io/git-flow-cheatsheet/index.zh_CN.html) 56 | - 一个很有意思的学习 git 的小游戏 http://pcottle.github.io/learnGitBranching/ 57 | - [图解 git](http://marklodato.github.io/visual-git-guide/index-zh-cn.html) 将书籍中很多术语用图片的方式进行讲解,很容易就懂了 58 | - [图文并茂-猴子都能懂的git入门教程](http://backlogtool.com/git-guide/cn/) 全面,生动形象,图文并茂,简单易懂,强烈推荐! 59 | 60 | 61 | 62 | 关于日常中使用git来版本管理的流程写的很不错的一本书,日常工作模式、流程怎样更合理的工作! 63 | ** 最后,当你开始使用git的时候,学会用终端,比如你想看关于branch,那么大胆的时候 *git branch --help * 查看相应的命令! ** 64 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 这整个 Repository 是关于分布式版本管理工具 Git 及托管商 Github 的使用,大部分都是网友写的内容,在这里只是做一个资源的汇总和合理的安排,希望能成为最好的学习 Git 的资源,从开始入门使用,到慢慢的提高,再到理解各种原理,希望能够达成这个目标。 3 | 4 | 网络上面已经有了那么多的关于 Git 的文章,为什么还要弄一个repo来专门记录?网上的文章都是片面的,稍微全点的讲解的不够全面、深入,没能满足我对于文章的想象,所以决定自己来写。 5 | 6 | 如果你要有一些资源,希望和我一起,把这个搞起来,很简单,`Fork-修改- Pull Request` 就 ok。 7 | 8 | # 新手入门 9 | - [为什么开始使用 Git 版本管理,Git VS Svn 有哪些区别?](https://github.com/xirong/my-git/blob/master/why-git.md) 10 | - [开篇:一篇适合入门学习git的资料汇总](https://github.com/xirong/my-git/blob/master/ixirong.com.md) 本人的拙笔,欢迎吐槽! 11 | - [Github-cheat-sheet](https://github.com/tiimgreen/github-cheat-sheet) 关于使用 Git 和 Github 的一些技巧汇总,中文版在此[GitHub秘籍](https://github.com/tiimgreen/github-cheat-sheet/blob/master/README.zh-cn.md) 12 | - [Git for beginners: The definitive practical guide - from stackoverflow.com](http://stackoverflow.com/questions/315911/git-for-beginners-the-definitive-practical-guide?rq=1) It's so useful to a beginner ,just open the url , read and practice . 13 | - [Visual Git Cheat Sheet](http://ndpsoftware.com/git-cheatsheet.html) 通过 Git 的几个工作区 Stash、Workspace、Index、Local Repository、Upstream Repository 来汇总日常使用的 Git 命令,备忘推荐。 14 | 15 | # Git 客户端 16 | 17 | Mac 和 Linux 系统推荐使用终端即可,Git 一开始的命令的确很多,别无它法,熟能生巧,多练习即可能够掌握日常使用的一些命令,再配合[`常用命令的alias`](https://git-scm.com/book/tr/v2/Git-Basics-Git-Aliases)或者强大的 [`zsh 终端`](http://www.ixirong.com/2015/04/27/strong-bash-use-oh-my-zsh/)都能显著的提升效率,当然如果非得寻找图形化客户端,也不是没有;Windows下还是尽快熟悉客户端的使用吧,因为win下面的bash太难用了: 18 | 19 | - [GUI Clients](https://git-scm.com/downloads/guis) 官方推荐图形客户端,罗列的包括了Mac、Windows、Linux下的客户端,免费及付费的都有,你可以在这里面挑选一个就ok。 20 | - [Git for windows](https://msysgit.github.io/) 针对 Window 系统发布的客户端,集成了 Shell 窗口,方便在 Win 下面使用命令操作。 21 | - [TortoiseGit - The coolest Interface to Git Version Control](https://code.google.com/p/tortoisegit/) 在window下使用git,那就不得不提“乌龟”,安装了 Tortoise 后,右键图形化操作根本分辨不出来哪是 Git,哪是 Svn,很方便使用 Svn 的用户过度过来。 22 | - [Tower2](http://www.git-tower.com/) 号称最好的 Git 客户端,只有 Mac 版本,收费,集成 Github、Gitlab、Xcode等服务。 23 | - [SourceTree](https://www.sourcetreeapp.com/) 免费,功能齐全,Mac+Window 版本,集成 Github 等服务。 24 | - [SmartGit](http://www.syntevo.com/smartgit/) 非商业用途免费,全平台支持,集成 Github服务。内置 SSH client ,文件比较与合并工具。 25 | - [Fork](https://git-fork.com) 免费,Mac+Window 版本,功能齐全,轻便流畅。 26 | 27 | # Git branch 28 | - [A successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/) 介绍日常推荐的分支开发模型,基于此模型可以通过这个小游戏来进行学习 [Learn Git Branch](http://pcottle.github.io/learnGitBranching/) 29 | - [Git工作流指南](https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md)完整的对比目前使用的集中式(Svn)工作流、功能分支工作流、Gitflow 工作流、Forking 工作流、Pull Request 等几种不同的模式,通俗易懂,强烈推荐看一看,如果觉的排版不好,请查看原分页文章 [Git-workflow-translations](https://github.com/oldratlee/translations/tree/master/git-workflows-and-tutorials) 30 | - 熟悉的工作流后,你是否也想要在 Github 上与他人一起协同工作?那么问题来了,[Github全程指南-如何高效使用?](how-to-use-github.md) 31 | - [Understanding the GitHub Flow](https://guides.github.com/introduction/flow/index.html) This guide explains how and why GitHub Flow works 简单实用,更好的理解Github的模式。 32 | - [Github 协同开发流程](http://www.ruanyifeng.com/blog/2015/08/git-use-process.html) 图片很赞,简洁易懂。 33 | 34 | # Git expert 35 | - 项目依赖其他项目,比如公共 Css、Dll 等等,强大的 Git-submodule 优雅的解决这类问题。理解阅读 [Git Tools - Submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) ,备忘或者查看命令阅读 [Git Submodule Tutorial](https://git.wiki.kernel.org/index.php/GitSubmoduleTutorial) 或者 [Git Submodule 使用完整教程](http://www.kafeitu.me/git/2012/03/27/git-submodule.html) 36 | - [Git Submodule 的一些注意事项](http://blog.devtang.com/blog/2013/05/08/git-submodule-issues/) 一些需要理解并注意的操作 37 | 38 | # Git 书籍 39 | - [Pro Git](http://git-scm.com/book/zh/v1) 作者Scott Chacon是 Github 的员工,Git 的布道者,这本书被誉为 Git 学习圣经,中间有好多插图描述的浅显易懂,挺适合详细学习下的,最新英文第二版《[Pro Git (Editon 2)](http://git-scm.com/book/en/v2)》; 40 | - [Git-internals-pdf](https://github.com/pluralsight/git-internals-pdf) 老外写的,很给力,从目录上面包括安装使用以及设计原理都有讲解,有机会看看。Pdf 电子版本直接下载地址 [Git-internals.pdf](ebooks/git-internals.pdf) 41 | - [Git Community Book](http://gitbook.liuhui998.com/) 汇聚了 Git 社区的很多精华, 并对 Git 的对象模型原理等做了解释,可以深入的了解下 Git 原理。pdf电子版本直接下载地址 [Git Community Book.pdf](ebooks/Git Community Book.pdf) 42 | - [Git权威指南](http://book.douban.com/subject/6526452/) 国内版本控制咨询顾问蒋鑫先生的原创书籍,原生中文叙述,更容易理解,查看[作者写书的缘由](http://www.worldhello.net/gotgit/) 43 | - [Git Reference](http://gitref.org/) [中文](http://gitref.org/zh/index.html) 为学习与记忆 Git 使用中最重要、最普遍的命令提供快速翻阅,可作为参考资料。 44 | - [Git Magic - a guide from standord](https://github.com/blynn/gitmagic) 斯坦福大学Git学习指南,适合快速入门。 45 | 46 | # Git 效率提升 47 | - [Git flow 工具](https://github.com/petervanderdoes/gitflow) 48 | - [Git flow 中文备忘清单](http://danielkummer.github.io/git-flow-cheatsheet/index.zh_CN.html) 49 | - 一个很有意思的学习 Git 的小游戏 http://pcottle.github.io/learnGitBranching/ 50 | - [Git completion](https://github.com/git/git/tree/master/contrib/completion) 终端 Git 命令的 Tab 键补全功能,比如打开终端,输入`git che`,按 Tab 键,则会出现`check-attr\check-ignore\checkout`等等的选项,支持 Bash、Zsh 等 Shell,使用方法(以 Bash Shell 为例):下载链接中相应的版本到用户目录下,修改`~/.bashrc`文件 ,加入`source ~/git-completion.bash` ,使得每次打开终端时都执行一次`git-completion.bash`脚本,来完成git 命令的 Tab 补全。或者采用这种方法[Quick Tip: Autocomplete Git Commands and Branch Names in Bash](http://code-worrier.com/blog/autocomplete-git/) 51 | - [.gitignore template](https://github.com/github/gitignore) 各种语言、各种编辑器的`.gitignore`文件模板,当你进行某些语言的开发时候,直接使用相应的模板即可,省去自己写的时间(还不全),当然你也可以去贡献自己的模板,不知道`.gitignore`? 简单讲就是不让git跟踪某些文件,详情阅读:http://git-scm.com/docs/gitignore 52 | **PS:** 推荐使用 `.gitignore_global` 文件进行全局过滤,比如mac下的 `.DS_Store` 文件,省去在每个 Repo 下进行设置 `.gitignore`文件了。全局模板参考:https://github.com/github/gitignore/tree/master/Global 53 | 54 | # Git extensions 55 | - Git 的大文件支持[Git LFS](https://github.com/github/git-lfs) : Git在对大文件进行版本管理的时候,速度上是很慢的,一个帮助处理大文件的扩展插件,在 GithubHelp [Working with large files](https://help.github.com/articles/working-with-large-files/) 中提到,不建议对大文件如日志、database等使用Git进行版本控制,如果非要有这种需求,则建议使用 Git LFS 。 56 | 57 | 58 | # 实践备忘 59 | - 常用命令手册 [Git 日常开发常用命令整理](useful-git-command.md),日常开发中的利器,可以当做备忘录来使用,推荐👍。 60 | - 总是使用 `git merge --no-ff` 而不是 `git merge` ,记录下分支的变更历史。 详情 http://stackoverflow.com/questions/9069061/what-is-the-difference-between-git-merge-and-git-merge-no-ff 61 | - 恰当的使用 `git pull --rebase` 避免不必要的merge记录。 详情 http://stackoverflow.com/questions/2472254/when-should-i-use-git-pull-rebase 「You should use `git pull --rebase` when your changes do not deserve a separate branch」 62 | 63 | - [Git-flight-rules](https://github.com/k88hudson/git-flight-rules) 一些日常使用中的场景,比如提交错了分支、提交时的用户名邮箱不对、丢弃某些提交、未提交的代码直接提交到另外一个分支等等,很实用。 64 | - [How to undo (almost) anything with Git](https://github.com/blog/2019-how-to-undo-almost-anything-with-git) 撤销一切,汇总各种回滚撤销的场景,加强学习。 65 | - [怎样在一台电脑上同时使用公司 GitLab 和 Github 的服务?](use-gitlab-github-together.md) 由于公司团队使用 GitLab 来托管代码,同时,个人在 Github 上还有一些代码仓库,可公司邮箱与个人邮箱是不同的,由此产生的 SSH key 也是不同的,这就造成了冲突 ,文章提供此类问题的解决方案。 66 | - [如何书写提交信息](http://chris.beams.io/posts/git-commit/) 当项目越来越大,提交信息越来越复杂的时候,如何书写好提交信息就变得至关重要,这篇文章的作者总结出7条准则。 67 | - [Commit message 和 change log编写规范-阮一峰](http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html) 良好的 commit log 好处大大的多。 [AngularJS Git Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.uyo6cb12dt6w) 68 | - [git-recipes](https://github.com/geeeeeeeeek/git-recipes/wiki) @童仲毅 整理翻译的一些优秀文章。 69 | - [githug](https://github.com/Gazler/githug) Git your game on. 使用通关游戏的形式来练习git的一些命令,非常有趣。 70 | -------------------------------------------------------------------------------- /use-gitlab-github-together.md: -------------------------------------------------------------------------------- 1 | 2 | 说明 3 | ==================== 4 | 5 | 由于公司团队使用 GitLab 来托管代码,同时,个人在 Github 上还有一些代码仓库,可公司邮箱与个人邮箱是不同的,由此产生的 SSH key 也是不同的,这就造成了冲突 ,文章提供此类问题的解决方案:**如何在一台机器上面同时使用 Github 与 Gitlab 的服务?** 6 | 7 | # 问题产生场景 8 | ------------- 9 | 10 | ## 无密码与远程服务器交互的秘密 - SSH 11 | 如果采用`ssh 协议`或者`git 协议`通过终端命令对远程仓库进行`push`操作的时候,大概的过程如下:(前提在 Github 上已经配置的本机的 SSH Public Key) 12 | 13 | 1. 客户端发起一个 Public Key 的认证请求,并发送RSA Key的模数作为标识符。(关于 RSA Key 详细 [维基百科](https://en.wikipedia.org/wiki/RSA_(algorithm))) 14 | 2. 服务端检查是否存在请求帐号的公钥(Linux中存储在~/.ssh/authorized_keys文件中),以及其拥有的访问权限。 15 | 3. 服务端使用对应的公钥对一个随机的256位的字符串进行加密,并发送给客户端。 16 | 4. 客户端使用私钥对字符串进行解密,并将其结合session id生成一个MD5值发送给服务端。 结合session id的目的是为了避免攻击者采用重放攻击(replay attack)。 17 | 5. 服务端采用同样的方式生成MD5值与客户端返回的MD5值进行比较,完成对客户端的认证。 18 | 6. 将push的内容进行加密与服务端传输数据。 19 | 20 | 关于 SSH,请查看 [SSH原理简介](http://erik-2-blog.logdown.com/posts/74081-ssh-principle) ,更通俗易懂的文章请查看[阮一峰-SSH原理与运用(一):远程登录](http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html) 。 21 | 22 | ## 具体场景 23 | 无论使用哪种代码托管服务商,对于 Git 而言,`邮箱` 是识别用户的唯一手段,所以对于不同的服务商,由于邮箱不同,那么通过邮件名创建的 SSH Key 自然是不同的,这时候在不同的服务商之间进行 `push` 命令的时候,Git 是不知道使用哪个 SSH Key ,自然导致 `push` 的失败。场景如下: 24 | 25 | 1. 在公司团队使用搭建的 Gitlab 服务,提交邮箱`xirong.liu@corp.xx.com`, 个人 Github 服务,提交邮箱 `ixirong.liu@gmail.com` (Bitbucket 同理)。 26 | 2. 有两个Github账户,不同的账户提交不同的仓库内容。 27 | 28 | # 解决方案 29 | 30 | ## 方案一:同一个邮箱 31 | 由于`邮箱`是识别的唯一手段,那么自然的,这两者采用同一个邮箱,生成的 public key 也会是同一个,上传到 Github 或者 Gitlab 上面,在 Git 的配置中 ,设置好 Global 的配置 :` git config --global user.name 'xirong.liu' && git config --global user.email 'xirong.liu@corp.xx.com'` 进行日常的开发是没有问题的。 32 | 33 | 实际生活中采用同一个邮箱的可能性并不是太大,这就引出了方案二 34 | 35 | ## 方案二:基于config文件 36 | 37 | 所谓的方案二,原理上就是对 SSH 协议配置 config 文件,对不同的域名采用不同的认证密钥。 38 | 39 | #### git config 介绍 40 | Git有一个工具被称为git config,它允许你获得和设置配置变量;这些变量可以控制Git的外观和操作的各个方面。这些变量可以被存储在三个不同的位置: 41 | 42 | 1. /etc/gitconfig 文件:包含了适用于系统所有用户和所有库的值。如果你传递参数选项’`--system`’ 给 git config,它将明确的读和写这个文件。 43 | 2. ~/.gitconfig 文件 :具体到你的用户。你可以通过传递 ‘`--global`’ 选项使Git 读或写这个特定的文件。 44 | 3. 位于 Git 目录的 config 文件 (也就是 .git/config) :无论你当前在用的库是什么,特定指向该单一的库。每个级别重写前一个级别的值。因此,在 .git/config 中的值覆盖了在/etc/gitconfig中的同一个值,可以通过传递‘`--local`’选项使Git 读或写这个特定的文件。 45 | 46 | 由于采用了不同的邮箱,对不同的服务商进行提交,所以此时我们经常配置的 `git config --global` 就不能常用了,必须在每个仓库的目录下进行配置自己的用户名、邮箱。(嫌麻烦?xirong 是这么解决的,由于个人的 Github 上有较多的仓库,而自己团队的代码基本上都是稳定的,有数的几个,所以在 `git config --global user.email 'ixirong.liu@gmail.com'` 中全局配置的是个人邮箱,在团队的项目中配置) 47 | 48 | ### 1. 配置 Git 用户名、邮箱 49 | 50 | 如刚才所说,xirong 的配置如下: 51 | 52 | ``` bash 53 | # 全局配置,Github仓库中默认使用此配置 54 | git config --global user.name 'xirong' && git config --global user.email 'ixirong.liu@gmail.com' 55 | 56 | # 团队项目配置,每次新创建一个项目,需要执行下 57 | git config --local user.name 'xirong.liu' && git config --local user.email 'xirong.liu@corp.example.com' 58 | ``` 59 | 60 | ### 2. 生成 ssh key 上传到 Github/Gitlab 61 | 62 | ssh key 默认生成后保存在 `~/.ssh/`目录下 ,默认为 `id_rsa 和 id_rsa.pub` 两个文件,由于我们需要分开配置,所以这么做: 63 | 64 | ``` bash 65 | # 生成公钥、密钥的同时指定文件名,Gitlab使用 66 | ssh-keygen -t rsa -f ~/.ssh/id_rsa.gitlab -C "xirong.liu@corp.example.com" 67 | 68 | # 生成默认,Github使用 69 | ssh-keygen -t rsa -C "ixirong.liu@gmail.com" 70 | ``` 71 | 72 | 命令执行完成后,这时`~/.ssh`目录下会多出`id_rsa.gitlab`和`id_rsa.gitlab.pub`两个文件,`id_rsa.gitlab.pub` 里保存的就是我们要使用的key,这个key就是用来上传到 Gitlab上的。 73 | 74 | ### 3. 配置 config 文件 75 | 在 `~/.ssh`目录下,如果不存在,则新建 `touch ~/.ssh/config`文件 ,文件内容添加如下: 76 | 77 | ``` bash 78 | Host corp.example.com 79 | HostName git.corp.example.com 80 | IdentityFile ~/.ssh/id_rsa.gitlab 81 | User xirong.liu 82 | ``` 83 | 84 | - `Host`参数是命令行给出的主机名,比如`ssh -T git@corp.example.com`,那么此时的主机(`Host`)就是`corp.example.com` 85 | - 只有`Host`匹配之后,`SSH`把`git@corp.example.com`转换成`git.corp.example.com` 86 | - `Host`不支持`*`和主机名混用,即`*.example.com`;单独`*`表示匹配所有主机,也就是默认规则 87 | - `HostName`应该是必须填写的内容,根据你使用的命令行内容来填写 88 | 89 | 配置完成后,符合`git.corp.example.com`的 Git 仓库,均采取` ~/.ssh/id_rsa.gitlab` 密钥进行验证,其它的采取默认的。 90 | 91 | ### 4. 上传public key 到 Github/Gitlab 92 | 93 | 以Github为例,过程如下: 94 | 95 | 1. 登录github 96 | 2. 点击右上方的Accounting settings图标 97 | 3. 选择 SSH key 98 | 4. 点击 Add SSH key 99 | 100 | 在出现的界面中填写SSH key的名称,填一个你自己喜欢的名称即可,然后将上面拷贝的`~/.ssh/id_rsa.pub`文件内容粘帖到`key`一栏,在点击“`add key`”按钮就可以了。 101 | 102 | 添加过程github会提示你输入一次你的github密码 ,确认后即添加完毕。 上传Gitlab的过程一样,请自己操作。 103 | 104 | ### 5. 验证是否OK 105 | 由于每个托管商的仓库都有唯一的后缀,比如 Github的是 `git@github.com:*`,所以可以这样测试: 106 | 107 | ``` bash 108 | ➜ ~ ssh -T git@github.com 109 | Hi xirong! You've successfully authenticated, but GitHub does not provide shell access. 110 | ➜ ~ ssh -T git@gitlab.dev 111 | Welcome to GitLab, xirong.liu! 112 | ``` 113 | 114 | 看到这些 `Welcome` 信息,说明就是 OK的了。 115 | 116 | 以后,如果还有任何的需求,都可以这么解决,看下 xirong 的几个托管仓库: 117 | 118 | ``` bash 119 | ➜ ~ ll ~/.ssh 120 | total 40 121 | -rw-r--r-- 1 xirong staff 264 Jul 10 14:42 config 122 | -rw------- 1 xirong staff 3243 Jul 10 14:09 id_rsa 123 | -rw------- 1 xirong staff 1675 Jan 28 20:39 id_rsa.gitlab 124 | -rw-r--r-- 1 xirong staff 407 Jan 28 20:39 id_rsa.gitlab.pub 125 | -rw-r--r-- 1 xirong staff 747 Jul 10 14:09 id_rsa.pub 126 | -rw------- 1 xirong staff 1679 Jun 22 11:42 id_rsa_gitcafe 127 | -rw-r--r-- 1 xirong staff 407 Jun 22 11:42 id_rsa_gitcafe.pub 128 | -rw-r--r-- 1 xirong staff 9139 Jul 29 15:08 known_hosts 129 | ``` 130 | -------------------------------------------------------------------------------- /useful-git-command.md: -------------------------------------------------------------------------------- 1 | 说明 2 | 3 | Git 常用、不常用、实用的命令,这些命令都是在日常使用过程中遇到过整理下来的,留作备忘,如果对这些命令还不明白什么意思,请参考学习:[Git 新手入门](https://github.com/xirong/my-git#新手入门) 。 4 | 5 | 在日常开发中,由于采用 Git 作为版本控制,经常跟命令行打交道,记录整理下使用到的一些命令,方便回顾。 6 | 7 | [TOC] 8 | # Concept 9 | ``` 10 | master : default development branch 11 | origin : default upstream repository 12 | HEAD : current branch and commit 13 | HEAD^ : parent of HEAD 14 | HEAD~4 : the great-great grandparent of HEAD 15 | ``` 16 | # Alias 17 | 下面的只是例子,想改成什么跟随自己的意愿即可。 18 | ``` bash 19 | git config --global alias.st status //status 缩写成 st 20 | git config --global alias.co checkout //checkout 缩写成 co 21 | git config --global alias.br branch //branch 缩写成 br 22 | git config --global alias.ci commit //commit 缩写成 ci 23 | git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" 24 | ``` 25 | 如果不想使用了,删除掉的话,直接删除 conf 配置文件中的行即可,global 的在当前用户下`vim ~/.gitconfig` 删除` alias`下你配置的内容接口;若是当前仓库则在 `.git/config` 中。 26 | # Git Config 27 | Git 配置文件分为三级,系统级(--system)、用户级(--global)和目录级(--local),三者的使用优先级以离目录 (repository)最近为原则,如果三者的配置不一样,则生效优先级 **目录级>用户级>系统级**,可以通过 `git config --help` 查看更多内容。 28 | + 系统级配置存储在 `/etc/gitconfig` 文件中,可以使用 `git config --system user.name "jim"` ,`git config --sytem user.email "jim.jim@gmail.com"` 来进行配置,该配置对系统上所有用户及他们所拥有的仓库都生效的配置值。 29 | + 用户级存储在每个用户的 `~/.gitconfig` 中,可以使用 `git config --global user.name "jim"` ,`git config --global user.email "jim.jim@gmail.com"` 来进行配置,该配置对当前用户上所有的仓库有效。 30 | + 目录级存储在每个仓库下的 `.git/config` 中,可以使用 `git config --local user.name "jim"` , `git config --local user.email "jim.jim@gmail.com"` 来进行配置,只对当前仓库生效。 31 | 32 | # Basic Usage 33 | - 添加文件到暂存区(staged):`git add filename` / `git stage filename` 34 | - 将所有修改文件添加到暂存区(staged): `git add --all` / `git add -A` 35 | - 提交修改到暂存区(staged):`git commit -m 'commit message'` / `git commit -a -m 'commit message'` 注意理解 -a 参数的意义 36 | - 从Git仓库中删除文件:`git rm filename` 37 | - 从Git仓库中删除文件,但本地文件保留:`git rm --cached filename` 38 | - 重命名某个文件:`git mv filename newfilename` 或者直接修改完毕文件名 ,进行`git add -A && git commit -m 'commit message'` Git会自动识别是重命名了文件 39 | - 获取远程最新代码到本地:`git pull (origin branchname)` 可以指定分支名,也可以忽略。pull 命令自动 fetch 远程代码并且 merge,如果有冲突,会显示在状态栏,需要手动处理。更推荐使用:`git fetch` 之后 `git merge --no-ff origin branchname` 拉取最新的代码到本地仓库,并手动 merge 。 40 | 41 | # Repository 42 | - 检出(clone)仓库代码:`git clone repository-url` / `git clone repository-url local-directoryname` 43 | + 例如,clone jquery 仓库到本地: `git clone git://github.com/jquery/jquery.git` 44 | + clone jquery 仓库到本地,并且重命名为 my-jquery :`git clone git://github.com/jquery/jquery.git my-jquery` 45 | - 查看远程仓库:`git remote -v` 46 | - 添加远程仓库:`git remote add [name] [repository-url]` 47 | - 删除远程仓库:`git remote rm [name]` 48 | - 修改远程仓库地址:`git remote set-url origin new-repository-url` 49 | - 拉取远程仓库: `git pull [remoteName] [localBranchName]` 50 | - 推送远程仓库: `git push [remoteName] [localBranchName]` 例: `git push -u orgin master ` 将当前分支推送到远端master分支 51 | - 将本地 test 分支提交到远程 master 分支: `git push origin test:master` (把本地的某个分支 test 提交到远程仓库,并作为远程仓库的 master 分支) 提交本地 test 分支作为远程的 test 分支 :`git push origin test:test ` 52 | 53 | # Checkout 54 | checkout命令用于从历史提交(或者暂存区域)中拷贝文件到工作目录,也可用于切换分支。 55 | ![](./_image/2016-07-14 21-26-37.jpg?r=49) ![](./_image/2016-07-14 21-15-47.jpg?r=49&f=2) 56 | **匿名分支**:如果既没有指定文件名,也没有指定分支名,而是一个标签、远程分支、SHA-1值或者是像 master~3 类似的东西,就得到一个匿名分支,称作 detached HEAD(被分离的 HEAD 标识)。 57 | 58 | ![](./_image/2016-07-14 21-44-06.jpg?r=56) 59 | 60 | 当HEAD处于分离状态(不依附于任一分支)时,提交操作可以正常进行,但是不会更新任何已命名的分支。(你可以认为这是在更新一个匿名分支。)一旦此后你切换到别的分支,比如说 master,那么这个提交节点(可能)再也不会被引用到,然后就会被丢弃掉了。注意这个命令之后就不会有东西引用 2eecb。详细查看:[visual-git-guide#detached](http://marklodato.github.io/visual-git-guide/index-zh-cn.html#detached) 61 | 但是,如果你想保存这个状态,可以用命令 `git checkout -b name` 来创建一个新的分支。 62 | ![](./_image/2016-07-14 21-45-50.jpg?r=56) 63 | 64 | # Log 65 | > Description : Shows the commit logs. 66 | The command takes options applicable to the git rev-list command to control what is shown and how, and options applicable to the git diff-* commands to control how the changes each commit introduces are shown. 67 | > git log [options] [revision range] [path] 68 | 69 | 常用命令整理如下: 70 | - 查看日志:`git log` 71 | - 查看日志,并查看每次的修改内容:`git log -p` 72 | - 查看日志,并查看每次文件的简单修改状态:`git log --stat` 73 | - 一行显示日志:`git log --pretty=oneline` / `git log --pretty='format:"%h - %an, %ar : %s'` 74 | - 查看日志范围: 75 | + 查看最近10条日志:`git log -10` 76 | + 查看2周前:`git log --until=2week` 或者指定2周的明确日期,比如:`git log --until=2015-08-12` 77 | + 查看最近2周内:`git log --since=2week` 或者指定2周明确日志,比如:`git log --since=2015-08-12` 78 | + 只查看某个用户的提交:`git log --committer=user.name` / `git log --author=user.name` 79 | + 只查看提交msg中包含某个信息的历史,比如包含'测试'两个字的:`git log --grep '测试'` 80 | + 试试这个 : `git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit` 感觉好用就加成 alias ,方便日后用,方法:`git config --global alias.aliasname 'alias-content'` 81 | + 更多用法:[Viewing the History -- 《Pro Git2》](http://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History) 82 | 83 | `log` 的目的就是为了查看改动点来排查问题,除了 ` git log` 还可以使用 `git show` 、`git blame` 来查看文件的改动。 84 | - Who changed what and when in a file : `git blame $file` 85 | - 查看一次 commit 中修改了哪些文件: `git show --pretty="" --name-only ` 或者 `git diff-tree --no-commit-id --name-only -r ` 86 | 87 | 88 | # Undo things 89 | - 上次提交 msg 错误/有未提交的文件应该同上一次一起提交,需要重新提交备注:`git commit --amend -m 'new msg'` 90 | - 修改上次提交的 author、email :`git commit --amend --author="newName "` 91 | - 修改整个历史记录中的某些错误的 author、email: `git rebase 或者 git filter-branch` 92 | ``` bash 93 | # git rebase 模式 94 | git rebase -i -p 76892625a7b126f4772f8d7e331ada3552c11ce1 95 | # 弹出编辑器,在需要修改的 commit 处 由 picked 改变为 edit ,然后 wq 退出 vim; 96 | git commit --amend --author 'newName ' 97 | # 执行后即变更了相应的 author 和 email 98 | git rebase --continue 99 | ################################################################ 100 | # git filter-branch 模式 https://help.github.com/articles/changing-author-info/ 101 | git filter-branch --env-filter ' 102 | OLD_EMAIL="your-old-email@example.com" 103 | CORRECT_NAME="Your Correct Name" 104 | CORRECT_EMAIL="your-correct-email@example.com" 105 | if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ] 106 | then 107 | export GIT_COMMITTER_NAME="$CORRECT_NAME" 108 | export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL" 109 | fi 110 | if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ] 111 | then 112 | export GIT_AUTHOR_NAME="$CORRECT_NAME" 113 | export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL" 114 | fi 115 | ' --tag-name-filter cat -- --branches --tags 116 | ``` 117 | ![](./_image/2017-06-02-11-51-27.jpg?r=54) 118 | 119 | - 一次`git add -A`后,需要将某个文件撤回到工作区,即:某个文件不应该在本次commit中:`git reset HEAD filename` 120 | - 撤销某些文件的修改内容:`git checkout -- filename` 注意:一旦执行,所有的改动都没有了,谨慎!谨慎!谨慎! 121 | - 将工作区内容回退到远端的某个版本:`git reset --hard ` 122 | 123 | # Reset 124 | reset命令把当前分支指向另一个位置,并且有选择的变动工作目录和索引,也用来在从历史仓库中复制文件到索引,而不动工作目录。 125 | 126 | ![](./_image/2016-07-14 20-31-39.png?r=64&f=1) 127 | 将工作区内容回退到远端的某个版本:`git reset --hard ` 128 | - `git reset --hard HEAD^` reset index and working directory , 以来所有的变更全部丢弃,并将 HEAD 指向 129 | * `git reset --soft HEAD^` nothing changed to index and working directory ,仅仅将 HEAD 指向 ,所有变更显示在 “changed to be committed”中 130 | * `git reset --mixed HEAD^` default,reset index ,nothing to working directory 默认选项,工作区代码不改动,添加变更到index区 131 | 132 | # Revert 133 | > `git revert` will create a new commit that's the opposite (or inverse) of the given SHA. If the old commit is "matter", the new commit is "anti-matter"—anything removed in the old commit will be added in the new commit and anything added in the old commit will be removed in the new commit. 134 | > This is Git's safest, most basic "undo" scenario, because it doesn't alter history—so you can now git push the new "inverse" commit to undo your mistaken commit. 135 | 136 | ```bash 137 | git revert [--[no-]edit] [-n] [-m parent-number] [-s] [-S[]] …​ 138 | git revert --continue 139 | git revert --quit 140 | git revert --abort 141 | ``` 142 | 143 | 回滚撤销一系列 commit 中的一条,并且不影响后续提交的功能 ,```git revert c2``` 144 | 145 | (https://blog.csdn.net/u013066244/article/details/79920012) https://blog.csdn.net/u013066244/article/details/79920012 146 | 147 | # Restore 148 | 分离 checkout 的功能,之前 checkout 可以切换分支,也可以恢复工作区的修改内容,现在这部分恢复修改内容由命令 restore来实现; 149 | git-restore[1] is about restoring files in the working tree from either the index or another commit. This command does not update your branch. The command can also be used to restore files in the index from another commit. 150 | 151 | 152 | ## Revert VS Reset VS Restore 153 | 154 | 想象一个简单的场景,分支 A,有 c1,c2,c3,c4,c5 五次 commit 提交,后来发现 c2 提交是有问题的,需要回滚,这个时候怎么解决? 155 | 方案一 使用 reset 命令 156 | 拉个新分支 A_bak ,复制现有分支, git reset --hard c2 , c3,c4,c5 都没有了。 git cherry-pick c3,c4,c5 到 A 分支。 157 | 158 | 方案二 使用 revert 命令 159 | ```git revert c2``` 可能会出现冲突,解决冲突即可。 也可能 revert 的 commit 是个合并 merge 的分支,则需要多做个操作,即 ```git revert c2 -m 1 , git revert c2 -m 2``` ,详情参考:https://blog.csdn.net/u013066244/article/details/79920012 160 | 161 | 现象:会创建一个新的 commit,即 c6 ,在 c6 的提交中,将 c2 里面的内容 反转掉 ,若有冲突,会展示冲突解决的文件内容。 162 | 163 | revert 可以说是就是为了这种场景而产生的,也应该是我们日常工作中经常使用的命令。 164 | 165 | 166 | # Diff 167 | - 查看工作区(working directory)和暂存区(staged)之间差异:`git diff` 168 | - 查看工作区(working directory)与当前仓库版本(repository)HEAD版本差异:`git diff HEAD` 169 | - 查看暂存区(staged)与当前仓库版本(repository)差异:`git diff --cached` / `git diff --staged` 170 | - 不查看具体改动,只查看改动了哪些类:`git diff --stat` 171 | 172 | # Merge 173 | ![](./_image/2016-07-14 20-53-25.jpg?r=80) 174 | 175 | 176 | - 解决冲突后/获取远程最新代码后合并代码:`git merge branchname` ,将 branchname 分支上面的代码合并到当前分支 177 | - 保留该存在版本合并log:`git merge --no-ff branchname` 参数 `--no-ff` 防止 fast-forward 的提交,详情参考:[the difference](http://stackoverflow.com/questions/9069061/what-is-the-difference-between-git-merge-and-git-merge-no-ff),fast-forward:分支内容一致,指针直接移动,并未能看出分支信息 178 | 179 | # Rebase 180 | Rebase 同 Merge 的结果是一样的,就是合并本地、远程的改动,但过程中还有区别。 181 | ``` bash 182 | git checkout mywork 183 | git rebase origin 184 | ``` 185 | 这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁 放到".git/rebase"目录中),然后把"mywork"分支更新 到最新的"origin"分支,最后把保存的这些补丁应用 到"mywork"分支上。 186 | 一张图分清 rebase 和 merge 的区别 187 | 188 | ![](./_image/2016-07-19 20-35-30.jpg?r=56) 189 | 在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决冲突;在解决完冲突后,用 `git-add` 命令去更新这些内容的索引(index), 然后,你无需执行 git-commit,只要执行: `git rebase --continue` 这样git会继续应用(apply)余下的补丁。在任何时候,你可以用 --abort 参数来终止rebase的行动,并且"mywork" 分支会回到rebase开始前的状态。 `git rebase --abort` 190 | 191 | # Cherry Pick 192 | cherry-pick 命令"复制"一个提交节点并在当前分支做一次完全一样的新提交。 193 | 194 | ![](./_image/2016-07-14 20-57-04.jpg?r=65) 195 | 196 | # Branch workflow 197 | Aone2 Git 分支开发部署模型详细解读 [http://docs.alibaba-inc.com:8090/pages/viewpage.action?pageId=194872297](http://docs.alibaba-inc.com:8090/pages/viewpage.action?pageId=194872297) 198 | 199 | 分支情况 origin 200 | - master 201 | - develop 202 | - release 203 | - 20161129163217010_r_release_yingyongming 204 | - 20161029163217010_r_release_yingyongming 205 | - feature 206 | - 20161129_163448_newfeature_1 207 | - 20161129_163448_newfeature_2 208 | - hotfix 209 | - 20161129_163448_hotfix_1 210 | - tags 211 | - 20161129163217010_r_release_newfeature_yingyongming 212 | 创建分支的时候直接操作: `git checkout -b feature/20161129_163448_newfeature_1` 213 | 214 | ![](./_image/2016-09-22-20-57-27.jpg) 215 | 216 | - master:master永远是线上代码,最稳定的分支,存放的是随时可供在生产环境中部署的代码,当开发活动告一段落,产生了一份新的可供部署的代码时,发布成功之后,代码才会由 aone2 提交到 master,master 分支上的代码会被更新。应用上 aone2 后禁掉所有人的 master的写权限 217 | - develop:保存当前最新开发成果的分支。通常这个分支上的代码也是可进行每日夜间发布的代码,只对开发负责人开放develop权限。 218 | - feature: 功能特性分支,每个功能特性一个 feature/ 分支,开发完成自测通过后合并入 develop 分支。可以从 master 或者develop 中拉出来。 219 | - hotfix: 紧急bug分支修复分支。修复上线后,可以直接合并入master。 220 | 221 | ![](./_image/2016-07-19 19-58-15.jpg?r=60) 222 | 223 | Git-Develop 分支模式是基于 Git 代码库设计的一种需要严格控制发布质量和发布节奏的开发模式。develop 作为固定的持续集成和发布分支,并且分支上的代码必须经过 CodeReview 后才可以提交到 Develop 分支。它的基本流程如下: 224 | - 每一个需求/变更都单独从Master上创建一条Branch分支; 225 | - 用户在这个Branch分支上进行Codeing活动; 226 | - 代码达到发布准入条件后aone上提交Codereview,Codereview通过后代码自动合并到Develop分支; 227 | - 待所有计划发布的变更分支代码都合并到Develop后,系统再 rebase master 代码到Develop 分支,然后自行构建,打包,部署等动作。 228 | - 应用发布成功后Aone会基于Develop分支的发布版本打一个“当前线上版本Tag”基线; 229 | - 应用发布成功后Aone会自动把Develop分支的发布版本合并回master; 230 | 231 | 232 | ## Branch 命令 233 | - 查看分支:`git branch` 、`git branch -v`、`git branch -vv` (查看当前分支 tracking 哪个远端分支)、`git branch --merged`、`git branch --no-merged` 234 | - 创建分支:`git branch branchname` 235 | 236 | + 例: 基于 master 分支新建 dev 分支 : `git branch dev` 237 | - 基于之前的某个 Commit 新开分支: `git branch branchname ` 238 | + 例: 基于上线的的提交 a207a38d634cc10441636bc4359cd8a18c502dea 创建 hotfix 分支 : `git branch hotfix a207a38` 239 | + 例: 基于 remoteBranch、localBranch、commitId、tag 创建分支均可以 `git checkout -b newbranch localBranch/remoteBranch/commitId/tag` 240 | + 例: 创建一个空的分支 241 | ``` bash 242 | git checkout --orphan gh-pages # 创建一个orphan的分支,这个分支是独立的 243 | Switched to a new branch \'gh-pages\' 244 | git rm -rf . # 删除原来代码树下的所有文件 245 | rm \'.gitignore\' 246 | #注意这个时候你用git branch命令是看不见当前分支的名字的,除非你进行了第一次commit。添加新的文件,并且 commit 掉,就能看到分支了。 247 | ```` 248 | - 切换分支: `git checkout branchname` 249 | 250 | + 例: 由分支 master 切换到 dev 分支:`git checkout dev` 251 | - 创建新分支并切换到下面:`git checkout -b branchname` 或者 `git branch branchname && git checkout branchname` 252 | 253 | + 例:基于 master 分支新建 dev 分支,并切换到 dev 分支上: `git checkout -b dev` 或 `git branch dev && git checkout dev ` 254 | - 查看分支代码不同:`git diff branchname` 比较 branchname 分支与当前分支的差异点,若只看文件差异,不看差异内容:`git diff branchName --stat` 255 | - 合并分支:`git merge branchname` 将 branchname 分支代码合并到当前分支 256 | - 删除分支:`git branch -d branchname` 强制删除未合并过的分支:`git branch -D branchname` 257 | - 重命名分支: `git branch -m dev development` 将分支 dev 重命名为 development 258 | - 查看远程分支:`git branch -r` 或 `git branch -r -v` 259 | - 获取远程分支到本地:`git checkout -b local-branchname origin/remote-branchname` 260 | - 推送本地分支到远程:`git push origin remote-branchname` 或 `git push origin local-branchname:remote-branchname` 261 | + 将本地 dev 代码推送到远程 dev 分支: `git push (-u) origin dev` 或 `git push origin dev:dev` 262 | + (技巧)将本地 dev 分支代码推送到远程 master 分支: `git push origin dev:master` 263 | - 删除远程分支:`git push origin :remote-branchname` 或 `git push origin --delete remote-branchname` 264 | - 手动跟踪分支,master分支追踪origin/next分支: `git branch --track master origin/next` 或者 `git branch --set-upstream-to=origin/master` 看 git 的版本是否支持。 265 | - TrackingBranch,可以通过 `git branch -vv` 来查看当前 track 的分支情况。新建立分支时会自动 track 相应远程分支,`git checkout -b sf origin/serverfix` (Branch sf set up to track remote branch serverfix from origin. Switched to a new branch 'sf'). 也可以手动 track: `git branch -u origin/serverfix` (Branch serverfix set up to track remote branch serverfix from origin). 等同于命令 `git checkout --track origin/serverfix` 266 | 267 | > “Checking out a local branch from a remote branch automatically creates what is called a “tracking branch” (or sometimes an “upstream branch”). Tracking branches are local branches that have a direct relationship to a remote branch. If you’re on a tracking branch and type git pull, Git automatically knows which server to fetch from and branch to merge into. 268 | When you clone a repository, it generally automatically creates a master branch that tracks origin/master. However, you can set up other tracking branches if you wish – ones that track branches on other remotes, or don’t track the master branch. The simple case is the example you just saw, running git checkout -b [branch] [remotename]/[branch]. This is a common enough operation that git provides the --track shorthand:” 269 | 270 | 271 | # Tag 272 | - 查看 tag:`git tag` 273 | - 查找指定 tag,比如查找 V1.0.* :`git tag -l 'V1.0.*'` 会列出匹配到的,比如 V1.0.1,V1.0.1.1,V1.0.2 等 274 | - 创建轻量级 tag(lightweight tags):`git tag tag-name` ,例如: `git tag v1.0` 275 | - 创建 tag(annotated tags):`git tag -a tag-name -m 'msg'` ,例如:`git tag -a v1.0.0 -m '1.0.0版本上线完毕打tag'` 276 | + annotated tags VS lightweight tags 可以通过命令真实查看下:`git show v1.0` / `git show v1.0.0` 277 | + “A lightweight tag is very much like a branch that doesn’t change – it’s just a pointer to a specific commit. 278 | Annotated tags, however, are stored as full objects in the Git database. They’re checksummed; contain the tagger name, e-mail, and date; have a tagging message; and can be signed and verified with GNU Privacy Guard (GPG). ” 279 | - 查看指定 tag 信息:`git show tag-name` 280 | - 基于历史某次提交(commit)创建 tag :`git tag -a tagname ` 281 | + 例:基于上线时的提交 a207a38d634cc10441636bc4359cd8a18c502dea 创建tag:`git tag -a v1.0.0 a207a38` 282 | - 删除 tag :`git tag -d tagname` 283 | - 拉取远程 tag 到本地:`git pull remotename --tags` 例如:`git pull origin --tags` 284 | - 推送 tag 到远程服务器:`git push remotename tagname` 例如:`git push origin v1.0.0` 285 | - 将本地所有 tag 推送到远程:`git push remotename --tags` 例如:`git push origin --tags` 286 | - 删除远程 tag :`git push origin :tagname` 或者 `git push origin --delete tagname` 或者 `git push origin :refs/tags/v0.9` 287 | 288 | # Submodule 289 | 添加子模块:$ git submodule add [url] [path] 290 | 如:$ git submodule add git://github.com/soberh/ui-libs.git src/main/webapp/ui-libs 291 | 初始化子模块:$ git submodule init ----只在首次检出仓库时运行一次就行 292 | 更新子模块:$ git submodule update ----每次更新或切换分支后都需要运行一下 293 | 删除子模块:(分4步走哦) 294 | 1) $ git rm --cached [path] 295 | 2) 编辑“.gitmodules”文件,将子模块的相关配置节点删除掉 296 | 3) 编辑“ .git/config”文件,将子模块的相关配置节点删除掉 297 | 4) 手动删除子模块残留的目录 298 | 299 | # Stash 300 | 经常有这样的事情发生,当你正在进行项目中某一部分的工作,里面的东西处于一个比较杂乱的状态,而你想转到其他分支上进行一些工作。问题是,你不想提交进行了一半的工作,否则以后你无法回到这个工作点。解决这个问题的办法就是 `git stash` 命令。 301 | `stash` 可以获取你工作目录的中间状态,也就是你修改过的被追踪的文件和暂存的变更,并将它保存到一个未完结变更的堆栈中,随时可以重新应用。 302 | 303 | ``` 304 | usage: git stash list [] 查看当前 stash 的列表 305 | or: git stash show [] 查看某一个版本的详细内容 306 | or: git stash drop [-q|--quiet] [] 删除 stash 中内容 307 | or: git stash ( pop | apply ) [--index] [-q|--quiet] [] 将 stash 中的代码应用到工作区中 308 | or: git stash branch [] 309 | or: git stash [save [--patch] [-k|--[no-]keep-index] [-q|--quiet] 310 | [-u|--include-untracked] [-a|--all] []] 311 | or: git stash clear 清空 stash 中所有内容 312 | ``` 313 | 314 | # oh-my-zsh 常用命令 315 | ``` 316 | alias g='git' 317 | alias ga='git add' 318 | alias gco='git checkout' 319 | alias gcb='git checkout -b' 320 | alias gcm='git checkout master' 321 | alias gcd='git checkout develop' 322 | alias gd='git diff' 323 | alias gf='git fetch' 324 | alias gfo='git fetch origin' 325 | alias gl='git pull' 326 | alias gp='git push' 327 | ``` 328 | -------------------------------------------------------------------------------- /using-svn.md: -------------------------------------------------------------------------------- 1 | 说明 2 | =========== 3 | 在日常开发中使用的 Svn 相关的概念以及技巧方法整理 …… 4 | 5 | [TortoiseSvn 使用](http://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/index.html) -------------------------------------------------------------------------------- /video: -------------------------------------------------------------------------------- 1 | https://www.youtube.com/watch?v=BCQHnlnPusY&t=2s 2 | -------------------------------------------------------------------------------- /why-git.md: -------------------------------------------------------------------------------- 1 | 使用svn用的好好的,为什么要用git?git有哪些优势?又有哪些劣势?在日常使用中两者明显的差异是什么? 2 | 3 | (关于 svn 的使用,一起来回顾一下 [How To Use Svn in Daily Work](using-svn.md)) 4 | 5 | - [Why is Git better than Subversion?](http://stackoverflow.com/questions/871/why-is-git-better-than-subversion) stackoverflow 上关于svn和git的区别的讨论,说的很详细。 6 | - [What are the differences between SVN and Git? ](https://help.github.com/articles/what-are-the-differences-between-svn-and-git/) github 上通过版本库结构、历史、子项目(submudle)的不同来对比两者。 7 | - [蒋鑫:为什么 Git 比 SVN 好?](http://www.worldhello.net/2012/04/12/why-git-is-better-than-svn.html "蒋鑫 - Why `Git` is better than `SVN`") 8 | 9 | 以下内容出自 [@oldratlee](https://github.com/oldratlee) 的 [repo](https://github.com/oldratlee/software-practice-miscellany/blob/master/git/README.md)。 10 | 11 | SVN 和 Git 在日常使用中的明显差异 12 | ========================= 13 | 14 | ![git vs svn](http://static.ixirong.com/pic/mygit/why-git.png) 15 | 16 | :point_right: 自己在使用`git`过程中相对`svn`的感受强烈的变化。 17 | 18 | :beer: 合并对提交过程的保留 19 | ------------------- 20 | 21 | - `git`:合并操作保留原有的提交过程(即保留了合并来源的作者、提交次数、分离提交的内容)。 22 | - `svn`:合并操作把来源多个提交合并成了一个合并提交,即在提交历史中Crash了自然的提交过程。 23 | 24 | 保留原有的提交过程,可以无需繁琐追踪历史就方便的 25 | 26 | 1. 跟踪修改过程。 27 | 1. 直接从提交中就可以看到原提交的作者信息,体现了对作者的尊重。 28 | 1. 自然的提交过程。这极大方便了代码细节演进过程的查看。 29 | 1. 极大方便查出那行提交是什么时间、谁做出的。 30 | `svn`因为合并Crash了自然的提交过程,要追踪很痛苦。 31 | 32 | :beer: 修正提交 33 | ------------------- 34 | 35 | - `git`:可以修正提交。 36 | 使用功能分支工作流,在自己的分支可以方便修正提交而不会影响大家。 37 | - `svn`:一旦提交就到服务器上,实际使用中就是不能修改。 38 | (`svn`可以在服务器上修改,因为过程复杂需要权限实际上从不会这样做。) 39 | 40 | 实际使用中会有误提交的情况(如提交了一个不该提交的日志文件),对于`svn`来说,就是让大家一遍又一遍看到这个垃圾文件。 41 | 42 | 没有干净的提交,严重影响了`Code Review`,增加成本。 43 | 44 | 另外对于想了解演进过程的同学,垃圾提交影响了了解效果。 45 | 46 | :beer: 廉价好用的本地分支 47 | ------------------- 48 | 49 | - `git`:有本地分支 50 | - `svn`:无本地分支 51 | 52 | `git`可以方便创建本地分支,且创建分支的时间是`O(1)`,即瞬间就创建好了。由于分支可以是本地的,也就不存在`svn`目录权限的问题。 53 | 54 | 可以从想要工作点闪电般创建本地分支,本地实验不确定的修改,创建分支如此之廉价,`git`推荐创建分支来隔离修改。 55 | 56 | :beer: 更强大智能的合并能力 57 | ---------------- 58 | 59 | - `git`:重命名(无论文件还有目录)提交 可以合并上 文件重命名前的这些文件的提交。 60 | - `svn`:重命名(无论文件还有目录)提交后,你本地/或是分支上 有文件重命名前的这些文件的修改或提交,在做合并操作时,恭喜:see_no_evil:,你会碰上传说中难搞的***树冲突***! 61 | 62 | 因为惧怕`svn`***树冲突***,在包名调整(重命名目录)或类名调整(重命名文件)前,我不得不先向一起开发的组员广播: 63 | 64 | 1. 提交你的修改 65 | 1. 暂停相关类的修改 66 | 1. 我开始做调整 67 | 1. 等我修改好后:scream:,你再开始修改 68 | 69 | OMG~ :confounded:~~ 70 | 71 | 因为这个过程烦琐,结果就是影响了大家去做这样重构操作的积极性,进而影响项目的代码质量改进! 72 | 73 | 别忘了,如果你的项目是开源的,全球的人可以给你提交,可没有办法向全球的同学广播 :kissing: 74 | 75 | :beer: 一等公民支持`tag` 76 | ------------------- 77 | 78 | - `svn`在模型上是没有分支和`tag`的。`tag`是通过目录权限限制(对开发只读)来保证不变。 79 | - `git`模型上一等公民支持`tag`,保证只读。 80 | 81 | 内心是不是有强烈的安全感? :sparkles: 82 | 83 | :beer: 完整配套的开发过程设施 84 | ------------------- 85 | 86 | 与`git`配套的`github`、`gitlab`(我们公司搭建了)提供了: 87 | 88 | - `Markdown`:高效的文档编写和查看。 89 | - `Issue` & `Milestone`:问题记录&跟踪,任务分配,版本规划&管理 90 | - `Wiki`系统:体系的文档 91 | - 评论:可以对代码提交(即是Code Review)& Issue做评论。 92 | 这个有记录交流的过程。 93 | 94 | 记住,上面的一切和代码一起集中管理,是以代码为中心的,可以方便的工程中的代码。 95 | 96 | 可运行并完成功能的代码(且叫目标代码) 才是整体项目真正生效的产出。 97 | 98 | 一切不为 目标代码 服务 的东东都是 **流氓**! 99 | \# 是不是想到很多东西(比如下压式的排期计划)会觉得自己是生效的产出,好像剩下的事就是 码农搬砖一样把代码码好。 100 | 101 | :beer: 热操作有闪电般的速度 102 | ------------------- 103 | 104 | ### 提交 105 | 106 | - `git`提交是个本地操作,相对`svn`闪电一般。 107 | - `git`提供了暂存区,可以方便指定提交内容,而不是全部。 108 | PS: `git`可以只提交一个文件修改的一部分而非全部(`git add –p`),使用相对繁琐些。(实际上开发中我很少这么做 :grin:) 109 | 110 | 这让开发者更愿意整理提交,让每个提交更内聚自包含。进而有利于 111 | 112 | - `Code Review` 113 | - 线上`Bug`的快速准确的回滚式修复 114 | 115 | ### 查看日志 116 | 117 | 查看日志是个频繁的操作。 118 | 119 | - `git`:本地包含了完整的日志,闪电的速度(并且无需网络)。 120 | - `svn`:需要从服务拉取。 121 | 122 | 一旦用了`git`后,等待`svn`日志(包括查看2个版本间的`diff`)过程简直让我发狂。 123 | duide 124 | --------------------------------------------------------------------------------