Git哲学与使用

-- 故国神游,多情应笑我,早生华发。html

Git是什么?

Git是一个版本控制工具,代码管理工具,团队协做工具。它跟SVN等传统工具实现一样的目的;但从某种程度来讲,它更快,更灵活。我想绝大多数读者都已经在接触这个工具了,而且用于平常的项目中去了。个人这篇文章,不是做为一个Git入门教程,也不是做为一本大块头的教科书。(说到教科书,我推荐下面的这本。这本书确实好,很全面。个人这篇文章,其实就是这本书的读书笔记而已。)java

Pro Git -- http://git.oschina.net/progit/git

接着说。个人这篇文章,主旨在于启发你们超越平时的使用局限,从另外一种视角去看待Git和使用Git,让人有一种“啊哈,Git也能这么用“的感受。这有点王婆卖瓜的味道了,这我必须认可。程序员

Git最基本的用法

不少项目组,对于刚入职的程序员,会像下面这样对他们普及Git的知识:redis

#使用git clone克隆项目的代码
git clone https://your-project-address

#使用git add添加修改的文件
git add your-filename

#或者使用git add --all添加全部修改的文件
git add --all

#使用git commit提交代码到本地的代码库
git commit -m some-description-message

#使用git push提交代码到远程的代码库
git push

#使用git pull拉下远程代码库中更新的代码
git pull

仅使用这五个命令,确实就足够进行团队协做了。这是使用Git的一种模式,并且无可厚非。不过,这样作有种仅仅把Git当成了纯粹的代码共享库的感受,多多少少显得有点不大规范。其实,Git有更加丰富的能力,它能让你的项目开发有更加规范的流程,整个项目历史有更加清晰的追溯,分工协做上也更加井井有理。并发

Git的特点

Git的特点有哪些呢?app

本地代码库

Git的最大特点可能就是做为一款分布式代码管理工具了。Git的绝大部分操做都是在本地进行的,这使得Git更快,并且更灵活。更灵活是由于在你的改动被提交到远程代码库以前,你能够在本地进行任意的操做。另外一方面,这也意味着改动提交到远程被共享以后,就不方便再改动旧的提交历史了。因此,请慎重上传改动到远程。编辑器

历史

代码的提交历史是一个项目开发历程的记录。这其中不只仅是情怀的记录。更重要的是,提交历史给了咱们项目回溯的能力,从而让咱们可以找出问题代码的来源,并修正它。Git的提交历史很强大,咱们能够去翻看历史,还能附加上丰富的筛选条件;甚至能够修改有问题的历史。为了更好地利用Git的历史功能,咱们要时刻保持提交历史的细致与干净。这意味着,咱们要恰到好处地提交咱们的代码,以及给它一个恰到好处的描述。分布式

分支

Git的另外一特点就是分支了。简单地说,分支就是不一样的代码故事。它们相互区别又互有联系,渐行渐远又能在某一处汇合。使用分支,咱们可以控制代码的不一样走向,从而很好地安排咱们的开发工做。灵活使用分支能够简化咱们的不少工做。ide

简单

说Git简单,听起来有点怪怪的。若是你要了解Git 内部原理,那确实够复杂的。不过,Git的特点在于,即便你不了解这些原理,你仍然能够灵活运用它。只用去学Git的一些基本的概念就足够了,例如仓库,暂存,提交,历史,分支等。说实话,我到如今是说不出这些概念的具体定义的,并且也只是浅要地了解了下这些概念的原理。可是,这并不影响我去使用它。Git的特点在于,学些基本的概念和原理;剩下的,去用就够了。这让我想起了不少的Unix工具,如Vim,LaTex等,以及Unix哲学。

Git哲学

所谓Git哲学,是指使用Git的思惟方式。下面是我以为的Git哲学中最要紧的几点:

1. 保持细致清晰的提交历史

若是说提交历史是一个版本控制工具最核心的模块,我以为一点也不为过。代码的提交历史要涵盖到具体的每一次改动,而且要有清晰一致的描述。这要求咱们:

  1. 分红一个个小的提交,而不是一次大的提交
  2. 每次提交要给到一个简洁明了的描述

每次的提交得是一个具体的总体。所谓具体的,是指你的提交不能是一次笼统的或归纳的改动;所谓总体,是指你的提交是一个已经完成的改动,而不能是悬而未决的。其实,这两点能够从你的提交说明中检验出来:

  1. 若是你的提交说明出现了像”完成用户登陆以及实现网站首页布局“这样诸如以及、和这样的词汇,极可能就说明你的一次提交作了不止一件事情,应该分为两次提交。
  2. 若是你的提交说明出现了像”完成用户登陆(一)“、”完成用户登陆(二)“、”完成用户登陆(终)“等这样连续关联的几个提交,说明你的这几个提交都在作一件事情,应该压缩为一个提交。

其实作到这一点也很容易 --

尽量得多提交,尽量得早提交,当完成一个小的功能点时就提交。

描述应该简洁明了。简洁是指可以用一句话描述你作的事情,而且不要覆盖其余没必要要的信息;明了是指绝对不能含糊,不只你能看得懂,也要让局外人也能看得懂。我列了几个要点:

  1. 若是不能作到简洁,或者说不能用一句话描述你的提交,颇有可能说明你的提交在作不止一件事情。解决办法是分为屡次提交。
  2. 不要使用含糊的或者归纳的描述。像诸如”修复BUG“这样的描述是要不得的,得说清楚修复了什么BUG。例如说”修复用户登陆后无端崩溃的BUG“或者”修复ISSUE 553“。
  3. 不要附加多余的信息,例如Author,Date,Email这些信息不要附加在描述里面了,由于提交历史已经自动包含这些信息了。

因为每一个提交都是一个细致的改动单元,当项目进行到必定阶段,整个提交历史必定会显得很长。这时候你可能会以为提交不少很杂,会淹没一些重要的版本发布提交,例如上线的版本v1.0,v1.1。我想这是没必要要的担忧,认真地对待提交历史,会让整个提交历史显得多而不杂。并且,彻底能够为重要的提交打标签。请记住 git tag 命令,它能够为重要的提交打标签。

Git的提交历史是至关灵活的。你能够查看历史;更厉害的,你还能够去修改它。因此,你能够在任意时刻去修正你的历史。这里有个例外,就是你没法修改远程仓库的提交历史。一方面,有的远程代码仓库不支持提交历史的修改;另外一方面,即便支持修改历史,这样的修改也会对其余开发者形成混乱。关于远程提交的准则是:

  1. 万万不得修改远程仓库的提交历史
  2. 在将代码提交到远程仓库以前,再大概检查一下准备push的系列本地提交

2. 即便滥用,也好过从不使用多分支

-- 一个分支就是一个故事,一个剧情。使用分支是为了避免让第三者破坏完美的剧情。

要有意识地去使用多分支,而不是去忽略它。能够在下面的状况下考虑使用分支:

  1. 当在主线版本的基础上要加上一个实验性的特性的时候,为了避免影响主线的开发进程,能够独立地在另外一个分支上开发。这时分开的两个故事能够并行地发展,当实验分支稳定后,两分支能够合并为同一个分支。
  2. 当在主线版本的基础上修复一个BUG,为了避免影响主线的正常开发,能够独立地另开一个分支进行。这时分开的两个故事能够并行地发展,当BUG修复后,能够将BUG分支并到主线分支。

这两个使用分支的策略都是本地临时分支使用策略。不管是添加特性分支仍是BUG修复分支,它们都有存在周期短的特色,而且都只是为解决某个特定问题而存在的。当这个问题被解决之后,它们就要被并入到主分支,这样就完成了本身的历史使命。使用分支的一种状况是:当你要同时进行多个任务的时候。

不管是主分支,仍是上面的特性添加分支或者BUG修复分支,都是你本身一我的的任务。你要同时完成两个或者三个任务。这时候才是分支发挥它最大做用的时候。不要在一个分支里同时作这几件事情,这样会违反第一哲学。记住:

每次只作一个任务;若是不得已要临时切换到其余任务,请使用分支。

Git既存在本地分支也存在远程分支;擅用分支,实际指的是灵活运用本地分支,而不是滥用远程分支。你能够随意地建立本地分支,频繁地在多个分支的下来回工做。但不要把这一切牵扯进远程分支。通常来讲,远程分支是长期分支,是做为项目不一样的发展阶段或者发展路线而存在的。例如稳定版、开发版、激进版等。这通常是项目决策者操心的事情。

再啰嗦一句:若是分支再也不须要了,就删除它。

3. 开发过程尽量私有化

私有化意味着封装。相似于面向对象上的封装,团队协做上也有封装的概念。你能够在本地灵活地使用Git的各类操做,而不会对他人形成任何影响。不过这种灵活性应局限于本地,而不要将冗余公开给远程的共享库。这方面有些准则,其中有些是对上面两个哲学的总结,以下:

  1. 为了简化工做,要灵活使用Git的各类本地操做
  2. 本地提交历史能够适当地混乱;但在提交到远程仓库前,必定要整理好
  3. 不要修改远程仓库的提交历史;并且,虽然不大可能,不要随意将新建分支推送到远程

实践Git

体现Git哲学的最好方式就是实践它,用Git的方式去工做,学会使用Git思惟。接下来我会涉及到具体的Git操做。

基本操做

【这一部分纯当是复习。】

初始化一个新仓库:

git init

 

从现有仓库克隆:

git clone <your-project-address>

 

时刻检查目录状态:

git status

 

.gitignore 文件能够声明脱离版本控制的文件:

#haha

 

暂存修改:

git add <new-file-or-modified-file>

git add --all

 

若是不当心 git add 了某个文件,使用 git rm 从暂存区移除(附带--cached参数移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上):

git rm --cached <your-added-file>

 

想知道代码作了哪些改动(会精确到行),使用:

git diff <some-file>

git diff #这会显示全部文件的改动

 

上面的命令是显示工做目录中当前文件和暂存区域快照之间的差别;若是想知道暂存区域与最近一次提交之间的差别,附加 --cached 参数:

git diff --cached <some-file>

git diff --cached 

 

提交更新:

git commit #这会为你打开一个文本编辑器

git commit -m <your-commit-message>

 

提交历史

为了更好地说明用法,我使用了JFinal项目的Git源码做为例子。

查看提交历史

使用 git log 能够查看提交历史。你应该看到相似于下面的结果:

$ git log
commit 121e247032be9e4d6a3c7eb8035914f59857c43d Author: James
<jfinal@126.com> Date: Sun Jul 26 13:40:44 2015 +0800 修改变量名,actoin 改成 action commit d330532f9db493034578d5dac1ece43c65136569 Author: James <jfinal@126.com> Date: Sun Jul 26 11:00:55 2015 +0800 变量名修改

 

能够看到SHA-1 校验和,做者的信息,时间以及提交说明。Git使用校验和来指代每一次提交,例如输出第一行的 121e247032be9e4d6a3c7eb8035914f59857c43d 。另外,若是不产生歧义的话,能够用校验和的前几个字符来指代提交,例如 121e247032be9e4d6a3c 和 121e247032

若是想看某一次具体的提交,指明它的校验和便可:

$ git log d330532f9
commit d330532f9db493034578d5dac1ece43c65136569
Author: James <jfinal@126.com>
Date:   Sun Jul 26 11:00:55 2015 +0800

    变量名修改

commit cdec1c3ceaceecfa4297c72efd8d8095640757f8
Author: James <jfinal@126.com>
Date:   Thu Jul 16 10:10:49 2015 +0800

    修改 Cache.expireAt(...) 方法上的注释

 

这会显示从指定提交开始往前回溯的提交历史。若是只是想显示指定的这一个提交,用 -1 参数( -2 则显示两次提交,依次类推):

$ git log d330532f9 -1
commit d330532f9db493034578d5dac1ece43c65136569
Author: James <jfinal@126.com>
Date:   Sun Jul 26 11:00:55 2015 +0800

    变量名修改

 

使用 git log --pretty=oneline 能够显示更紧凑的提交信息,每次提交用一行来显示:

$ git log --pretty=oneline
121e247032be9e4d6a3c7eb8035914f59857c43d 修改变量名,actoin 改成 action
d330532f9db493034578d5dac1ece43c65136569 变量名修改
cdec1c3ceaceecfa4297c72efd8d8095640757f8 修改 Cache.expireAt(...) 方法上的注释
749fbe0d8e9da0e33fe2b30085f7467e86881e17 JFinal 2.0 release ^_^
52633ce2da704cf35a48aa9b8a1afe99d6c2ed1d JFinal 2.0 release ^_^
1e00c07348bd7b1ed16bb5c224e0a0de67b9b13b JFinal 2.0 release ^_^
0330d7ed5f3d742eaca201456927d9cecb40e215 JFinal 2.0 release ^_^
aa4a95af60a1dc12dfd649bd208de473dcfb369f jfinal 1.9 release ^_^
af6469eb6f49c23cba8215f2b0e9c8d51cd5f8c9 jfinal 1.9 release ^_^
4ab71ce41cca8b7d16bef89655b51e6de6548d30 jfinal 1.9 release ^_^
03a3c5a2bdb848ad2f9a30e29eba4f468176497f jfinal 1.9 release ^_^

 

使用 -p 选项展开每次提交所作的修改。例如咱们使用下面的命令展开哈希前缀为 d330532f9 的那次提交的修改:

$ git log d330532f9 -p -1
commit d330532f9db493034578d5dac1ece43c65136569
Author: James <jfinal@126.com>
Date:   Sun Jul 26 11:00:55 2015 +0800

    变量名修改

diff --git a/.gitignore b/.gitignore
index 416db66..b1e58ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@ integration-repo
 /build/
 
 # IDEA metadata and output dirs
+/.idea/^M
 *.iml
 *.ipr
 *.iws
diff --git a/src/com/jfinal/config/Routes.java b/src/com/jfinal/config/Routes.ja
index fab2604..8ad1b03 100644
--- a/src/com/jfinal/config/Routes.java
+++ b/src/com/jfinal/config/Routes.java
@@ -86,11 +86,11 @@ public abstract class Routes {

 

使用 --stat 选项仅显示代码修改的统计信息(仅显示简要的增删行数统计,特别适合做代码审查):

$ git log --stat
commit 121e247032be9e4d6a3c7eb8035914f59857c43d
Author: James <jfinal@126.com>
Date:   Sun Jul 26 13:40:44 2015 +0800

    修改变量名,actoin 改成 action

 src/com/jfinal/core/ActionMapping.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

commit d330532f9db493034578d5dac1ece43c65136569
Author: James <jfinal@126.com>
Date:   Sun Jul 26 11:00:55 2015 +0800

    变量名修改

 .gitignore                                             |  1 +
 src/com/jfinal/config/Routes.java                      |  6 +++---
 src/com/jfinal/plugin/activerecord/Sqls.java           |  4 ++--
 src/com/jfinal/plugin/activerecord/tx/TxByMethods.java | 14 +++++++-------
 src/com/jfinal/plugin/redis/RedisInterceptor.java      | 11 ++++++++++-
 5 files changed, 23 insertions(+), 13 deletions(-)

 

我从《Pro Git》中摘出了一些选项及说明:

选项 说明
-p 按补丁格式显示每一个更新之间的差别。
--stat 显示每次更新的文件修改统计信息。
--shortstat 只显示 --stat 中最后的行数修改添加移除统计。
--name-only 仅在提交信息后显示已修改的文件清单。
--name-status 显示新增、修改、删除的文件清单。
--abbrev-commit 仅显示 SHA-1 的前几个字符,而非全部的 40 个字符。
--relative-date 使用较短的相对时间显示(好比,“2 weeks ago”)。
--graph 显示 ASCII 图形表示的分支合并历史。
--pretty 使用其余格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。

 

Git提交历史的一大特点在于能够按照条件筛选历史。例如筛选出最近两周到最近一周的提交历史:

$ git log --since=2.weeks --until=1.weeks
commit cdec1c3ceaceecfa4297c72efd8d8095640757f8
Author: James <jfinal@126.com>
Date:   Thu Jul 16 10:10:49 2015 +0800

    修改 Cache.expireAt(...) 方法上的注释

 

我也列出了一些可以设置筛选条件的一些选项,一样来源于《Pro Git》:

选项 说明
-(n) 仅显示最近的 n 条提交
--since, --after 仅显示指定时间以后的提交。
--until, --before 仅显示指定时间以前的提交。
--author 仅显示指定做者相关的提交。
--committer 仅显示指定提交者相关的提交。
-- 命令的最后一个选项,后跟路径名表示只关心某一路径下的提交历史

 

修改提交历史

Git提交历史的另外一大特点在于你能够修改它。不过格外注意的是,不要修改那些已经推送到远程版本库的提交历史

 

首先介绍如何撤销。这多少与修改历史无关,由于此时的历史可能还未造成。

若是只是但愿将某个文件的改动从暂存区拿出来,而保持文件原有内容不变,使用命令:

git reset HEAD <your-file>

 

其中HEAD指代最近一次提交(*)。你可使用HEAD变量来避免使用哈希值。

下述命令会令整个项目的状态回退(保留修改):

git reset HEAD

 

若是想将文件恢复到最近一次提交的版本,使用命令 git checkout 。这会使得其从暂存区拿出来(若是已经存入暂存区),而且文件内容恢复到最近一次提交的状态:

git checkout <your-file>

 

若是想直接撤销全部改动(包括修改),使用命令:

git reset --hard HEAD    #恢复全部改动到最近一次提交

git reset --hard HEAD~1 #恢复全部改动到最近一次提交的上一次提交

git reset --hard HEAD~2 #恢复全部改动到最近一次提交的前两次提交

git reset --hard d330532 #恢复到指定提交

 

带有 --hard 选项的版本回退是一个不可恢复的操做,请谨慎用之。

 

当咱们完成提交后,发现漏掉了某些改动(例如忘记添加相应的API注释)。这时咱们固然能够将改动做为一次新的提交提交一发。不过,还有其余的方案,即将漏掉的改动从新补回到对应的历史提交中,毕竟漏掉的改动确实是那次提交的一部分。Git给了咱们修改提交的能力。

若是只是要修改最近的一次提交,使用 git add 命令暂存相应的改动,而后输入命令 git commit --amend 。这会把你代入修改提交说明的编辑器中。保存后退出,咱们就完成了咱们的提交修改。

若是只是想修改最近一次提交的提交说明,直接输入 git commit --amend ,而后进入编辑器修改提交说明并保存退出便可。

 

要修改历史中更早的提交,就要用到 git rebase -i 交互式的提交历史修改工具。我在命令行中输入:

git rebase -i HEAD~4

 

它会带我进入一个文本编辑器中(在个人系统里意外地是VIM)。关注前四行,会看到咱们能够修改最近的四次提交历史( HEAD~4 指定)。其中提交由早到晚地排列,与 git log 显示顺序相反。

1 pick 749fbe0 JFinal 2.0 release ^_^
2 pick cdec1c3 修改 Cache.expireAt(...) 方法上的注释
3 pick d330532 变量名修改
4 pick 121e247 修改变量名,actoin 改成 action

 

这时咱们能够修改某次提交,例如修改第2行的提交,只需将 pick 换成 edit 便可。而后保存并退出编辑器。

pick 749fbe0 JFinal 2.0 release ^_^
edit cdec1c3 修改 Cache.expireAt(...) 方法上的注释
pick d330532 变量名修改
pick 121e247 修改变量名,actoin 改成 action

 

像以前同样,使用 git commit --amend 修改提交;最后使用 git rebase --continue 完成修改任务。

咱们也能够删除某个提交,只需将相应的提交行删掉便可。例如删除第2行的提交:

pick 749fbe0 JFinal 2.0 release ^_^
pick d330532 变量名修改
pick 121e247 修改变量名,actoin 改成 action

 

从新排列提交也是OK的。只须要从新排列便可。例以下面的编辑把最近一次提交移到最前,最先的一次提交移到最近:

pick 121e247 修改变量名,actoin 改成 action
pick cdec1c3 修改 Cache.expireAt(...) 方法上的注释
pick d330532 变量名修改
pick 749fbe0 JFinal 2.0 release ^_^

 

一个有用的功能是压制提交,即把多个提交合并成一次提交。例以下面的编辑将多个描述都为”JFinal 2.0 release ^_^“的提交合并为一个提交:

pick 0330d7e JFinal 2.0 release ^_^
squash 1e00c07 JFinal 2.0 release ^_^
squash 52633ce JFinal 2.0 release ^_^
squash 749fbe0 JFinal 2.0 release ^_^
pick cdec1c3 修改 Cache.expireAt(...) 方法上的注释

 

相应地,能够拆分一个提交。它的技巧在于 edit 某次提交,而后调用 git reset HEAD^ 回到父提交,而后再屡次 git commit 便可。

git reset HEAD^
git add file1
git commit -m "add file1"
git add file2
git commit -m "add file2"
git rebase --continue

 

当准备进入交互式rebase工具时,若是当前的工做区存在修改而没有被提交,则会被禁止进入。此时咱们能够先将修改提交;有时又不但愿这么作,可能咱们的代码改动还不能构成一个完整的提交。咱们只但愿先保存本身的工做,而后在须要的时候释放出来。这时就用到 git stash 命令了。

咱们能够将改动保存在一个栈中,称之为储藏(Stashing)

git stash

 

而后查看栈状态:

$ git stash list
stash@{0}: WIP on master: 121e247 修改变量名,actoin 改成 action

 

由于是栈,能够屡次调用 git stash ,而后查看栈状态:

$ git stash list
stash@{0}: WIP on master: 121e247 修改变量名,actoin 改成 action
stash@{1}: WIP on master: 121e247 修改变量名,actoin 改成 action
stash@{2}: WIP on master: 121e247 修改变量名,actoin 改成 action

 

而后在适当的时候,释放一个储藏。既能够释放指定的储藏,例如 stash@{0}stash@{1} stash@{2},也能够默认释放最近的储藏(stash@{0}):

git stash apply    

git stash apply stash@{2}

 

当储藏再也不须要时,删除它:

git stash drop stash@{2}

 

或者当即释放最近的储藏并删除它:

git stash pop

 

储藏的典型应用场景是当工做区有未提交的修改时,要切回到旧提交去修改( git rebase -i )或者切换到其余分支( git checkout )。

 

分支

Git的分支是从某个分支引出的一个分叉。在Git中建立分支时,必定是以某个分支为基准,这个分支就是你当前工做的分支。

分支基本操做

要查看当前在哪一个分支下工做,输入命令:

git branch

 

此时会列出全部本地分支,行首标有*号的是当前工做分支。

建立分支:

git branch <new-branch-name>

 

切换到新分支:

git checkout <new-branch-name>

 

同时建立及切换分支:

git checkout -b <new-branch-name>

 

合并分支:

git checkout master
git merge <new-branch-name>

 

这能保证将新分支的改动合并到主分支。

删除分支:

git branch -d <new-branch-name>

 

只有已被合并的分支才能顺利删除,不然会提示错误。

若是要强制删除分支,使用命令:

git branch -D <new-branch-name>

 

分支思惟

以上只是分支的基本操做命令。要想活用这些命令,就要知道分支的使用思惟。分支的使用思惟,我以为就是一句话,重复以前的一句话:

当你要放下手中的任务,临时切换到其余任务时,使用分支。

我这里想举一个关于分支使用的简单的不能再简单的例子。

首先你在进行master上进行主线开发,实现功能点一。忽然你临时接到任务,完成功能点二,并立刻上线。此时你不得不放下手中的工做,投入到实现功能点二中去。

这时,你首先要作的是保存你正在进行的工做以便未来能够恢复。可使用储藏 git stash 或者临时提交你的代码以在未来经过 git commit --amend 修改你的历史。这里假设你使用的是储藏。

而后新建分支并切换到新分支工做:

git checkout -b feature2

 

当你完成功能点二的开发时,提交你的代码:

git add --all

git commit -m "finish feature 2"

 

以后切换到主分支,合并feature2分支:

git checkout master

git merge feature2

 

改动能够提交到远程上线:

git push

 

而后你可使用 git stash pop 恢复你的工做。

分支工做流程:

队伍中的长期分支控制了不一样的开发进度。通常来讲,应该有一个稳定分支和开发分支:你能够将master做为稳定分支,并配有一个develop分支;或者反过来,将master做为开发分支,并配有一个stable分支。这里假设master是稳定分支,而develop是开发分支。develop分支通常比master要超前,而且当测试稳定后才会并入到master分支发布。因此通常的工做流程就是:

在develop分支开发,测试稳定后并入到master分支发布

另外,若是已发布的版本遭遇到一个紧急BUG亟待修复,这时你应该保存develop分支的工做,而后切换到master分支去修复。由于要紧急发布,你应当切换到稳定的master分支完成BUG修复,而不是基于不稳定develop分支。当修复完毕并发布后,再回到develop分支恢复工做。

Git找bug的能力:

利用分支,咱们能够很好地分离了咱们的不一样工做,不让它们相互干扰,从而减小bug的来源;利用历史,咱们能够追踪代码的变化,为咱们找出问题代码提供了途径。其实Git也为咱们提供了其余的好用的工具,利于咱们调试。

git blame:谁动了个人代码

你是否会惊奇你的代码为何忽然变成这副模样?不要紧,使用 git blame 命令能够显示你的代码是谁最后修改的。命令格式:

git blame -L 12,22 simple.rb

 

能够显示文件simple.rb的第12至22行这块代码最后是谁、何时修改并提交的。

二分查找

还有一个有趣的命令是 git bisect 。它能够以二分查找的策略逐步逼近你在乎的坏代码的来源。

首先输入 git bisect start 来启动二分查找。

输入 git bisect bad 来告知当前的提交已是问题提交了。

而后输入 git bisect good <good-commit> 来告知你知道的最晚的正常提交。

接着就能够肯定坏代码的来源在<good-commit>和当前提交之间,二分查找策略就能够开启了,这时Git监测处于中间的一个提交。假设从<good-commit>到当前提交一共有12个提交,记编号为0、一、…、11. 这时咱们检出的提交应该是6.

你能够输入 git bisect good 来告知这个提交是正常的,这样它会舍弃编号为0、一、…、6的提交;也能够输入 git bisect bad 来告知问题依然存在,这样它会舍弃编号为七、八、…、11的提交。而后继续二分策略…一直到咱们只剩下一个问题提交的时候。这个提交就是咱们的问题提交的最初来源。

当你完成的时候,应该运行 git bisect reset 从新回到最初的地方。

Git使用总结:

  1.  在调用 git add --all 前,应该使用 git status 查看你要添加的改动,以避免添加进没必要要的改动。
  2.  要忽略的文件添加到 .gitignore 中去。
  3.  git commit 时要给到一个简洁明了的描述。
  4.  git push 前要用 git log 检查本身的提交历史。
  5.  必要时要修改本地提交历史,它们的命令是 git commit --amend 和 git rebase -i
  6.  不要修改远程提交历史,这每每意味着,你只能修改最近的几个历史。 
  7.  要灵活地使用本地分支。它们的命令主要是 git branch 、 git checkout 等。
  8.  切换分支前注意保存本身的工做,用到的工具是 git stash
  9.  不要随意将本地分支push到远程。

超越Git

Git是伟大的,但咱们依然要超越Git;毕竟Git只是一个工具,而咱们是使用工具的人。Git的功能是代码管理和版本控制,但Git的本质在于其重视团队,重视协做的开发精神。它重视协做,但又不束缚我的的创造。它使得每一个人均可以自由地编码,同时又保持整个项目开发的协调一致。

相关文章
相关标签/搜索