diff --git a/docs/git/git-flow.md b/docs/git/git-flow.md new file mode 100644 index 0000000..9a47a12 --- /dev/null +++ b/docs/git/git-flow.md @@ -0,0 +1,232 @@ +--- +title: git-flow 工作流 +date: 2017-12-06 +categories: +- linux +tags: +- linux +- vcs +- git +--- + +# git-flow 工作流 + +## git-flow 模型 + +[@nvie](http://twitter.com/nvie) 同学发表了博客 [“一种有效的Git分支模型”](http://nvie.com/git-model), 文章讲解了他是如何让自己的[Git](http://www.oschina.net/p/git)仓库保持整洁,除此之外,他发布了git-flow; 一个可以轻松实现该模型的Git扩展。 + +![git-flow.png](http://oyz7npk35.bkt.clouddn.com//image/linux/git/git-flow.png) + +`Gitflow`工作流仍然用中央仓库作为所有开发者的交互中心。和其它的工作流一样,开发者在本地工作并`push`分支到要中央仓库中。 + +### 历史分支 + +相对使用仅有的一个`master`分支,`Gitflow`工作流使用2个分支来记录项目的历史。`master`分支存储了正式发布的历史,而`develop`分支作为功能的集成分支。这样也方便`master`分支上的所有提交分配一个版本号。 + +![img](https://raw.githubusercontent.com/quickhack/translations/master/git-workflows-and-tutorials/images/git-workflow-release-cycle-1historical.png) + +剩下要说明的问题围绕着这2个分支的区别展开。 + +### 功能分支 + +每个新功能位于一个自己的分支,这样可以[`push`到中央仓库以备份和协作](https://www.atlassian.com/git/tutorial/remote-repositories#!push)。但功能分支不是从`master`分支上拉出新分支,而是使用`develop`分支作为父分支。当新功能完成时,[合并回`develop`分支](https://www.atlassian.com/git/tutorial/git-branches#!merge)。新功能提交应该从不直接与`master`分支交互。 + +![img](https://raw.githubusercontent.com/quickhack/translations/master/git-workflows-and-tutorials/images/git-workflow-release-cycle-2feature.png) + +注意,从各种含义和目的上来看,功能分支加上`develop`分支就是功能分支工作流的用法。但`Gitflow`工作流没有在这里止步。 + +### 发布分支 + +![img](https://raw.githubusercontent.com/quickhack/translations/master/git-workflows-and-tutorials/images/git-workflow-release-cycle-3release.png) + +一旦`develop`分支上有了做一次发布(或者说快到了既定的发布日)的足够功能,就从`develop`分支上`fork`一个发布分支。新建的分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分支上 —— 这个分支只应该做`Bug`修复、文档生成和其它面向发布任务。一旦对外发布的工作都完成了,发布分支合并到`master`分支并分配一个版本号打好`Tag`。另外,这些从新建发布分支以来的做的修改要合并回`develop`分支。 + +使用一个用于发布准备的专门分支,使得一个团队可以在完善当前的发布版本的同时,另一个团队可以继续开发下个版本的功能。 +这也打造定义良好的开发阶段(比如,可以很轻松地说,『这周我们要做准备发布版本4.0』,并且在仓库的目录结构中可以实际看到)。 + +常用的分支约定: + +`用于新建发布分支的分支: develop用于合并的分支: master分支命名: release-* 或 release/*` + +### 维护分支 + +![img](https://raw.githubusercontent.com/quickhack/translations/master/git-workflows-and-tutorials/images/git-workflow-release-cycle-4maintenance.png) + +维护分支或说是热修复(`hotfix`)分支用于生成快速给产品发布版本(`production releases`)打补丁,这是唯一可以直接从`master`分支`fork`出来的分支。修复完成,修改应该马上合并回`master`分支和`develop`分支(当前的发布分支),`master`分支应该用新的版本号打好`Tag`。 + +为`Bug`修复使用专门分支,让团队可以处理掉问题而不用打断其它工作或是等待下一个发布循环。你可以把维护分支想成是一个直接在`master`分支上处理的临时发布。 + +## 安装 + +- 你需要有一个可以工作的 git 作为前提。 +- Git flow 可以工作在 OSX, Linux 和 Windows之下 + +### OSX Homebrew + +``` +$ brew install git-flow + +``` + +### OSX Macports + +``` +$ port install git-flow + +``` + +### Linux + +``` +$ apt-get install git-flow + +``` + +### Windows (Cygwin): + +安装 git-flow, 你需要 wget 和 util-linux。 + +``` +$ wget -q -O - --no-check-certificate https://github.com/nvie/gitflow/raw/develop/contrib/gitflow-installer.sh | bash +``` +## Git Flow代码示例 + +![git-flow-commands.png](http://oyz7npk35.bkt.clouddn.com//image/linux/git/git-flow-commands.png) + +### 开始 + +- 为了自定义你的项目,Git flow 需要初始化过程。 +- 使用 git-flow,从初始化一个现有的 git 库内开始。 +- 初始化,你必须回答几个关于分支的命名约定的问题。建议使用默认值。 + +``` +git flow init + +``` + +### 特性 + +- 为即将发布的版本开发新功能特性。 +- 这通常只存在开发者的库中。 + +##### 创建一个新特性: + +下面操作创建了一个新的feature分支,并切换到该分支 + +``` +git flow feature start MYFEATURE + +``` + +##### 完成新特性的开发: + +完成开发新特性。这个动作执行下面的操作: + +1. 合并 MYFEATURE 分支到 'develop' +2. 删除这个新特性分支 +3. 切换回 'develop' 分支 + +``` +git flow feature finish MYFEATURE + +``` + +##### 发布新特性: + +你是否合作开发一项新特性? 发布新特性分支到远程服务器,所以,其它用户也可以使用这分支。 + +``` +git flow feature publish MYFEATURE + +``` + +##### 取得一个发布的新特性分支: + +取得其它用户发布的新特性分支。 + +``` +git flow feature pull origin MYFEATURE + +``` + +##### 追溯远端上的特性: + +通过下面命令追溯远端上的特性 + +``` +git flow feature track MYFEATURE + +``` + +### 做一个release版本 + +- 支持一个新的用于生产环境的发布版本。 +- 允许修正小问题,并为发布版本准备元数据。 + +##### 开始创建release版本: + +- 开始创建release版本,使用 git flow release 命令。 +- 'release' 分支的创建基于 'develop' 分支。 +- 你可以选择提供一个 [BASE]参数,即提交记录的 sha-1 hash 值,来开启动 release 分支。 +- 这个提交记录的 sha-1 hash 值必须是'develop' 分支下的。 + +``` +git flow release start RELEASE [BASE] + +``` + +创建 release 分支之后立即发布允许其它用户向这个 release 分支提交内容是个明智的做法。命令十分类似发布新特性: + +``` +git flow release publish RELEASE + +``` + +(你可以通过 `git flow release track RELEASE` 命令追溯远端的 release 版本) + +##### 完成 release 版本: + +完成 release 版本是一个大 git 分支操作。它执行下面几个动作: + +1. 归并 release 分支到 'master' 分支。 +2. 用 release 分支名打 Tag +3. 归并 release 分支到 'develop' +4. 移除 release 分支。 + +``` +git flow release finish RELEASE + +``` + +不要忘记使用`git push --tags`将tags推送到远端 + +### 紧急修复 + +紧急修复来自这样的需求:生产环境的版本处于一个不预期状态,需要立即修正。有可能是需要修正 master 分支上某个 TAG 标记的生产版本。 + +##### 开始 git flow 紧急修复: + +像其它 git flow 命令一样, 紧急修复分支开始自: + +``` +$ git flow hotfix start VERSION [BASENAME] + +``` + +VERSION 参数标记着修正版本。你可以从 `[BASENAME]开始,`[BASENAME]`为finish release时填写的版本号 + +##### 完成紧急修复: + +当完成紧急修复分支,代码归并回 develop 和 master 分支。相应地,master 分支打上修正版本的 TAG。 + +``` +git flow hotfix finish VERSION +``` + +## 资料 + +[git 官网](https://git-scm.com/) | [git 官方 Github](https://github.com/git/git) + +[廖雪峰的 git 教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) + +[https://github.com/arslanbilal/git-cheat-sheet/blob/master/other-sheets/git-cheat-sheet-zh.md](https://github.com/arslanbilal/git-cheat-sheet/blob/master/other-sheets/git-cheat-sheet-zh.md) diff --git a/docs/git/git.md b/docs/git/git.md new file mode 100644 index 0000000..0487443 --- /dev/null +++ b/docs/git/git.md @@ -0,0 +1,583 @@ +--- +title: git 快速指南 +date: 2017-12-06 +categories: +- linux +tags: +- linux +- vcs +- git +--- + +## 简介 + +### Git 是什么? + +Git 是一个开源的分布式版本控制系统。 + +### 为什么使用 Git? + +Git 是分布式的。这是 Git 和其它非分布式的版本控制系统,例如 svn,cvs 等,最核心的区别。分布式带来以下好处: + +**工作时不需要联网** + +首先,分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。 + +**更加安全** + +集中式版本控制系统,一旦中央服务器出了问题,所有人都无法工作。 + +分布式版本控制系统,每个人电脑中都有完整的版本库,所以某人的机器挂了,并不影响其它人。 + +### 原理 + +![git-theory.png](http://oyz7npk35.bkt.clouddn.com//image/linux/git/git-theory.png) + +先介绍几个核心概念,介绍概念过程中的命令具体用法会在后面详述,这里暂不做介绍: + +#### 版本库 + +当你一个项目到本地或创建一个 git 项目,项目目录下会有一个隐藏的 `.git` 子目录。这个目录是 git 用来跟踪管理版本库的,千万不要手动修改。 + +#### 工作区(WORKING) + +当你 `git clone` 一个项目到本地,本地的项目目录相当于一个工作副本,这就是工作区。 + +#### 暂存区(STAGING) + +当你在工作区上执行增删改操作,致使文件状态发生变化,可以通过 `git add` 暂存,存储的区域就是暂存区。 + +#### 本地仓库(LOCAL) + +通过 `git commit` 命令,可以将所有暂存的记录提交到当前分支,这时内容被保存在了本地仓库。此时,工作区相当于是清空了。 + +#### REMOTE(远程仓库) + +以上的所有版本控制都是在你的本地完成,远程仓库并没有保存你的修改,换句话说,其他人并不知道你的工作。为了让所以人都能看到你的修改,你需要使用 `git push` 将自己的修改推送到远程仓库上。 + +同理,如果你想知道别人在远程仓库上做了什么修改,你可以使用 `git fetch` 或 `git pull` 同步别人的修改。 + +## 安装 + +### Linux + +#### Debian/Ubuntu + +如果你使用的系统是 Debian/Ubuntu , 安装命令为: + +```sh +$ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \ +> libz-dev libssl-dev +$ apt-get install git-core +$ git --version +git version 1.8.1.2 +``` + +#### Centos/RedHat + +如果你使用的系统是 Centos/RedHat ,安装命令为: + +``` +$ yum install curl-devel expat-devel gettext-devel \ +> openssl-devel zlib-devel +$ yum -y install git-core +$ git --version +git version 1.7.1 +``` + +### Windows + +在[Git 官方下载地址](https://git-scm.com/downloads)下载 exe 安装包。按照安装向导安装即可。 + +建议安装 Git Bash 这个 git 的命令行工具。 + +### Mac + +在[Git 官方下载地址](https://git-scm.com/downloads)下载 mac 安装包。按照安装向导安装即可。 + +## 使用 + +国外网友制作了一张 Git Cheat Sheet,总结很精炼,各位不妨收藏一下。 + +![git-cheat-sheet.png](http://oyz7npk35.bkt.clouddn.com//image/linux/git/git-cheat-sheet.png) + +### 创建 + +##### 复制一个已创建的仓库: + +``` +# 通过 SSH +$ git clone ssh://user@domain.com/repo.git + +#通过 HTTP +$ git clone http://domain.com/user/repo.git +``` + +##### 创建一个新的本地仓库: + +``` +$ git init +``` + +### 本地修改 + +##### 显示工作路径下已修改的文件: + +``` +$ git status +``` + +##### 显示与上次提交版本文件的不同: + +``` +$ git diff +``` + +##### 把当前所有修改添加到下次提交中: + +``` +$ git add . +``` + +##### 把对某个文件的修改添加到下次提交中: + +``` +$ git add -p +``` + +##### 提交本地的所有修改: + +``` +$ git commit -a +``` + +##### 提交之前已标记的变化: + +``` +$ git commit +``` + +##### 附加消息提交: + +``` +$ git commit -m 'message here' +``` + +##### 提交,并将提交时间设置为之前的某个日期: + +``` +git commit --date="`date --date='n day ago'`" -am "Commit Message" +``` + +##### 修改上次提交 + +*请勿修改已发布的提交记录!* + +``` +$ git commit --amend +``` + +##### 修改上次提交的committer date: + +``` +GIT_COMMITTER_DATE="date" git commit --amend +``` + +##### 修改上次提交的author date: + +``` +git commit --amend --date="date" +``` + +##### 把当前分支中未提交的修改移动到其他分支: + +``` +git stash +git checkout branch2 +git stash pop +``` + +##### 将 stashed changes 应用到当前分支: + +``` +git stash apply +``` + +##### 删除最新一次的 stashed changes: + +``` +git stash drop +``` + +### 搜索 + +##### 从当前目录的所有文件中查找文本内容: + +``` +$ git grep "Hello" + +``` + +##### 在某一版本中搜索文本: + +``` +$ git grep "Hello" v2.5 +``` + +### 提交历史 + +##### 从最新提交开始,显示所有的提交记录(显示hash, 作者信息,提交的标题和时间): + +``` +$ git log + +``` + +##### 显示所有提交(仅显示提交的hash和message): + +``` +$ git log --oneline + +``` + +##### 显示某个用户的所有提交: + +``` +$ git log --author="username" + +``` + +##### 显示某个文件的所有修改: + +``` +$ git log -p + +``` + +##### 仅显示远端分支与远端分支提交记录的差集: + +``` +$ git log --oneline .. --left-right + +``` + +##### 谁,在什么时间,修改了文件的什么内容: + +``` +$ git blame + +``` + +##### 显示reflog: + +``` +$ git reflog show + +``` + +##### 删除reflog: + +``` +$ git reflog delete +``` + +### 分支与标签 + +##### 列出所有的分支: + +``` +$ git branch + +``` + +##### 列出所有的远端分支: + +``` +$ git branch -r + +``` + +##### 切换分支: + +``` +$ git checkout + +``` + +##### 创建并切换到新分支: + +``` +$ git checkout -b + +``` + +##### 基于当前分支创建新分支: + +``` +$ git branch + +``` + +##### 基于远程分支创建新的可追溯的分支: + +``` +$ git branch --track + +``` + +##### 删除本地分支: + +``` +$ git branch -d + +``` + +##### 强制删除一个本地分支: + +*将会丢失未合并的修改!* + +``` +$ git branch -D + +``` + +##### 给当前版本打标签: + +``` +$ git tag + +``` + +##### 给当前版本打标签并附加消息: + +``` +$ git tag -a +``` + +### 更新与发布 + +##### 列出当前配置的远程端: + +``` +$ git remote -v + +``` + +##### 显示远程端的信息: + +``` +$ git remote show + +``` + +##### 添加新的远程端: + +``` +$ git remote add + +``` + +##### 下载远程端版本,但不合并到HEAD中: + +``` +$ git fetch + +``` + +##### 下载远程端版本,并自动与HEAD版本合并: + +``` +$ git remote pull + +``` + +##### 将远程端版本合并到本地版本中: + +``` +$ git pull origin master + +``` + +##### 以rebase方式将远端分支与本地合并: + +``` +git pull --rebase + +``` + +##### 将本地版本发布到远程端: + +``` +$ git push remote + +``` + +##### 删除远程端分支: + +``` +$ git push : (since Git v1.5.0) +or +git push --delete (since Git v1.7.0) + +``` + +##### 发布标签: + +``` +$ git push --tags +``` + +### 合并与重置 + +合并与重置(Rebase) + +##### 将分支合并到当前HEAD中: + +``` +$ git merge + +``` + +##### 将当前HEAD版本重置到分支中: + +*请勿重置已发布的提交!* + +``` +$ git rebase + +``` + +##### 退出重置: + +``` +$ git rebase --abort + +``` + +##### 解决冲突后继续重置: + +``` +$ git rebase --continue + +``` + +##### 使用配置好的merge tool 解决冲突: + +``` +$ git mergetool + +``` + +##### 在编辑器中手动解决冲突后,标记文件为`已解决冲突`: + +``` +$ git add + +``` + +``` +$ git rm + +``` + +##### 合并提交: + +``` +$ git rebase -i + +``` + +把上面的内容替换为下面的内容: + +原内容: + +``` +pick +pick +pick + +``` + +替换为: + +``` +pick +squash +squash +``` + +### 撤销 + +##### 放弃工作目录下的所有修改: + +``` +$ git reset --hard HEAD + +``` + +##### 移除缓存区的所有文件(i.e. 撤销上次`git add`): + +``` +$ git reset HEAD + +``` + +##### 放弃某个文件的所有本地修改: + +``` +$ git checkout HEAD + +``` + +##### 重置一个提交(通过创建一个截然不同的新提交) + +``` +$ git revert + +``` + +##### 将HEAD重置到指定的版本,并抛弃该版本之后的所有修改: + +``` +$ git reset --hard + +``` + +##### 用远端分支强制覆盖本地分支: + +``` +git reset --hard e.g., upstream/master, origin/my-feature + +``` + +##### 将HEAD重置到上一次提交的版本,并将之后的修改标记为未添加到缓存区的修改: + +``` +$ git reset + +``` + +##### 将HEAD重置到上一次提交的版本,并保留未提交的本地修改: + +``` +$ git reset --keep + +``` + +##### 删除添加`.gitignore`文件前错误提交的文件: + +``` +$ git rm -r --cached . +$ git add . +$ git commit -m "remove xyz file" +``` + +## 资料 + +[git 官网](https://git-scm.com/) | [git 官方 Github](https://github.com/git/git) + +[廖雪峰的 git 教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) + +[git-cheat-sheet](https://github.com/arslanbilal/git-cheat-sheet) + +[github-cheat-sheet](https://github.com/tiimgreen/github-cheat-sheet) \ No newline at end of file