欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

2019.05.26 周日--《阿里巴巴 Java 开发手册》精华摘要

程序员文章站 2022-12-05 16:38:28
一、写在开头 Java作为一个编程界最流行的语言之一,有着很强的生命力。代码的编写规范也是不容忽视的,今天,我就把自己阅读的国内的互联网巨头阿里巴巴的《阿里巴巴 Java 开发手册》一些精彩内容摘录如下。以飨读者。《阿里巴巴Java开发手册 终极版v1.3.0.pdf》 下载地址 《阿里巴巴Java ......

一、写在开头

    java作为一个编程界最流行的语言之一,有着很强的生命力。代码的编写规范也是不容忽视的,今天,我就把自己阅读的国内的互联网巨头阿里巴巴的《阿里巴巴 java 开发手册》一些精彩内容摘录如下。以飨读者。《阿里巴巴java开发手册 终极版v1.3.0.pdf》 下载地址

 

2019.05.26  周日--《阿里巴巴 Java 开发手册》精华摘要
《阿里巴巴java开发手册 终极版v1.3.0.pdf》 

二、精彩摘录

    4.1)【命名风格】


【01 强制】抽象类命名使用 abstract 或 base 开头;异常类命名使用 exception 结尾;测试类 命名以它要测试的类的名称开始,以 test 结尾。

 【02 强制】中括号是数组类型的一部分,数组定义如下:string[] args; 反例:使用 string args[]的方式来定义。

【03强制】pojo 类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。 

==反例:定义为基本数据类型 boolean isdeleted;的属性,它的方法也是 isdeleted(), 框架在反向解析的时候,“以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异 常。

【04 强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用 单数形式,但是类名如果有复数含义,类名可以使用复数形式。 正例: 应用工具类包名为 com.alibaba.open.util、类名为 messageutils(此规则参考 spring 的框架结构)

【05 推荐】如果模块、接口、类、方法使用了设计模式,在命名时体现出具体模式

【06 推荐】接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁 性,并加上有效的 javadoc 注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是 与接口方法相关,并且是整个应用的基础常量。 正例:接口方法签名:void f(); 接口基础常量表示:string company = "alibaba"; 反例:接口方法定义:public abstract void f(); 说明:jdk8 中接口允许有默认实现,那么这个 default 方法,是对所有实现类都有价值的默 认实现。

【不是很理解--todo】接口和实现类的命名有两套规则:

1)【强制】对于 service 和 dao 类,基于 soa 的理念,暴露出来的服务一定是接口,内部 的实现类用 impl 的后缀与接口区别。 正例:cacheserviceimpl 实现 cacheservice 接口。 

2)【推荐】如果是形容能力的接口名称,取对应的形容词做接口名(通常是–able 的形式)。 正例:abstracttranslator 实现 translatable。

4.2)【常量定义】


【不是很理解--todo】【强制】不允许任何魔法值(即未经定义的常量)直接出现在代码中。 反例:string key = "id#taobao_" + tradeid; cache.put(key, value);

4.3)【代码格式】


【01 强制】大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果 是非空代码块则: 1) 左大括号前不换行。 2) 左大括号后换行。 3) 右大括号前换行。 4) 右大括号后还有 else 等代码则不换行;表示终止的右大括号后必须换行。

 【02 强制】if/for/while/switch/do 等保留字与括号之间都必须加空格。

 【03 强制】任何二目、三目运算符的左右两边都需要加一个空格。 说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。

【04 强制】注释的双斜线与注释内容之间有且仅有一个空格。 正例:// 注释内容,注意在//和注释内容之间有一个空格。

4.4)【oop规约】


【01 强制】object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。 

==正例:"test".equals(object); 反例:object.equals("test"); 说明:推荐使用 java.util.objects#equals(jdk7 引入的工具类)

【02 强制】所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较。

说明:对于 integer var = ? 在-128 至 127 范围内的赋值,integer 对象是在 integercache.cache 产生,会复用已有对象,这个区间内的 integer 值可以直接使用==进行 判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑, 推荐使用 equals 方法进行判断。

关于基本数据类型与包装数据类型的使用标准如下: 

1) 【强制】所有的 pojo 类属性必须使用包装数据类型。 

2) 【强制】rpc 方法的返回值和参数必须使用包装数据类型。 

3) 【推荐】所有的局部变量使用基本数据类型。 

==说明:pojo 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何 npe (即空指针异常)问题,或者入库检查,都由使用者来保证。 

==正例:数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 npe 风险。 

==反例:比如显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 rpc 服务,调用 不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线。所以包装 数据类型的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。

参考:java中基本数据类型和包装类

【03 强制】序列化类新增属性时,请不要修改 serialversionuid 字段,避免反序列失败;如 果完全不兼容升级,避免反序列化混乱,那么请修改 serialversionuid 值。 说明:注意 serialversionuid 不一致会抛出序列化运行时异常。

【04 强制】pojo 类必须写 tostring 方法。使用 ide 的中工具:source> generate tostring 时,如果继承了另一个 pojo 类,注意在前面加一下 super.tostring。 说明:在方法执行抛出异常时,可以直接调用 pojo 的 tostring()方法打印其属性值,便于排 查问题。

【05 推荐】当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起, 便于阅读,

【06 推荐】 类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter 方法。

【07 推荐】循环体内,字符串的连接方式,使用 stringbuilder 的 append 方法进行扩展。 

==说明:反编译出的字节码文件显示每次循环都会 new 出一个 stringbuilder 对象,然后进行 append 操作,最后通过 tostring 方法返回 string 对象,造成内存资源浪费。 

==反例: string str = "start"; for (int i = 0; i < 100; i++) { str = str + "hello"; }

【08 推荐】类成员与方法访问控制从严: 

1) 如果不允许外部直接通过 new 来创建对象,那么构造方法必须是 private。

2) 工具类不允许有 public 或 default 构造方法。

3) 类非 static 成员变量并且与子类共享,必须是 protected。 

4) 类非 static 成员变量并且仅在本类使用,必须是 private。

5) 类 static 成员变量如果仅在本类使用,必须是 private。

6) 若是 static 成员变量,必须考虑是否为 final。

7) 类成员方法只供类内部调用,必须是 private。 

8) 类成员方法只对继承类公开,那么限制为 protected。 

==说明:任何类、方法、参数、变量,严控访问范围。过于宽泛的访问范围,不利于模块解耦。 思考:如果是一个 private 的方法,想删除就删除,可是一个 public 的 service 方法,或者 一个 public 的成员变量,删除一下,不得手心冒点汗吗?变量像自己的小孩,尽量在自己的 视线内,变量作用域太大,无限制的到处跑,那么你会担心的。

4.5)【集合处理】


【01 强制】关于 hashcode 和 equals 的处理,遵循如下规则:

1) 只要重写 equals,就必须重写 hashcode。

2) 因为 set 存储的是不重复的对象,依据 hashcode 和 equals 进行判断,所以 set 存储的 对象必须重写这两个方法。

3) 如果自定义对象做为 map 的键,那么必须重写 hashcode 和 equals。 说明:string 重写了 hashcode 和 equals 方法,所以我们可以非常愉快地使用 string 对象 作为 key 来使用。

【02 强制】arraylist的sublist结果不可强转成arraylist,否则会抛出classcastexception 异常,即 java.util.randomaccesssublist cannot be cast to java.util.arraylist. 

==说明:sublist 返回的是 arraylist 的内部类 sublist,并不是 arraylist ,而是 arraylist 的一个视图,对于 sublist 子列表的所有操作最终会反映到原列表上。

== 例子:

【03 强制】在 sublist 场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、 删除均会产生 concurrentmodificationexception 异常。

【04 强制】使用集合转数组的方法,必须使用集合的 toarray(t[] array),传入的是类型完全 一样的数组,大小就是 list.size()。

【05 强制】使用工具类 arrays.aslist()把数组转换成集合时,不能使用其修改集合相关的方 法,它的 add/remove/clear 方法会抛出 unsupportedoperationexception 异常。

== 说明:aslist 的返回对象是一个 arrays 内部类,并没有实现集合的修改方法。arrays.aslist 体现的是适配器模式,只是转换接口,后台的数据仍是数组。 

==string[] str = new string[] { "you", "wu" }; list list = arrays.aslist(str); 第一种情况:list.add("yangguanbao"); 运行时异常。 第二种情况:str[0] = "gujin"; 那么 list.get(0)也会随之修改。

【06 强制】泛型通配符来接收返回的数据,此写法的泛型集合不能使用 add 方 法,而不能使用 get 方法,做为接口调用赋值时易出错。 

==说明:扩展说一下 pecs(producer extends consumer super)原则:第一、频繁往外读取内 容的,适合用<? extends t>。第二、经常往里插入的,适合用<? super t>。

【07 强制】c。remove 元素请使用 iterator 方式,如果并发操作,需要对 iterator 对象加锁。

【08 强制】 在 jdk7 版本及以上,comparator 要满足如下三个条件,不然 arrays.sort, collections.sort 会报 illegalargumentexception 异常。

== 说明:三个条件如下 1) x,y 的比较结果和 y,x 的比较结果相反。 2) x>y,y>z,则 x>z。 3) x=y,则 x,z 比较结果和 y,z 比较结果相同。

== 参考资料: : java comparator 接口排序用法

【09 推荐】集合初始化时,指定集合初始值大小。

==说明:hashmap 使用 hashmap(int initialcapacity) 初始化, 

==正例:initialcapacity = (需要存储的元素个数 / 负载因子) + 1。注意负载因子(即 loader factor)默认为 0.75,如果暂时无法确定初始值大小,请设置为 16(即默认值)。

== 反例:hashmap 需要放置 1024 个元素,由于没有设置容量初始大小,随着元素不断增加,容 量 7 次*扩大,resize 需要重建 hash 表,严重影响性能。

【10 推荐】使用 entryset 遍历 map 类集合 kv,而不是 keyset 方式进行遍历。

==说明:keyset 其实是遍历了 2 次,一次是转为 iterator 对象,另一次是从 hashmap 中取出 key 所对应的 value。而 entryset 只是遍历了一次就把 key 和 value 都放到了 entry 中,效 率更高。如果是 jdk8,使用 map.foreach 方法。 正例:values()返回的是 v 值集合,是一个 list 集合对象;keyset()返回的是 k 值集合,是 一个 set 集合对象;entryset()返回的是 k-v 值组合集合。

== 网络例子: 

【11 推荐】高度注意 map 类集合 k/v 能不能存储 null 值的情况,如下表格:

4.6)【集合处理】


【强制】获取单例对象需要保证线程安全,其中的方法也要保证线程安全。 说明:资源驱动类、工具类、单例工厂类都需要注意。

4.7)【控制语句】


【01 强制】在一个 switch 块内,每个 case 要么通过 break/return 等来终止,要么注释说明程 序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default 语句并且 放在最后,即使它什么代码也没有。

 【02 强制】在 if/else/for/while/do 语句中必须使用大括号。即使只有一行代码,避免采用 单行的编码方式:if (condition) statements;

【03 推荐】表达异常的分支时,少用 if-else 方式,这种方式可以改写成: if (condition) { ... return obj; } // 接着写 else 的业务逻辑代码;

==正例:超过 3 层的 if-else 的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现,

== 参考: 

【04 推荐】循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、 获取数据库连接,进行不必要的 try-catch 操作(这个 try-catch 是否可以移至循环体外)。

 

4.8)【注释规约】


【01 强制】类、类属性、类方法的注释必须使用 javadoc 规范,使用/**内容*/格式,不得使用 // xxx 方式。

【02 强制】所有的类都必须添加创建者和创建日期。

【03 强制】方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释 使用/* */注释,注意与代码对齐。

【04 参考】特殊注释标记,请注明标记人与标记时间。注意及时处理这些标记,通过标记扫描, 经常清理此类标记。线上故障有时候就是来源于这些标记处的代码。

== 1) 待办事宜(todo):( 标记人,标记时间,[预计处理时间]) 表示需要实现,但目前还未实现的功能。这实际上是一个 javadoc 的标签,目前的 javadoc 还没有实现,但已经被广泛使用。只能应用于类,接口和方法(因为它是一个 javadoc 标签)。

== 2) 错误,不能工作(fixme):(标记人,标记时间,[预计处理时间]) 在注释中用 fixme 标记某代码是错误的,而且不能工作,需要及时纠正的情况。

4.9)【其他】


【01 强制】后台输送给页面的变量必须加$!{var}——中间的感叹号。 说明:如果 var=null 或者不存在,那么${var}会直接显示在页面上。

【02 强制】注意 math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(能够 取到零值,注意除零异常),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后 取整,直接使用 random 对象的 nextint 或者 nextlong 方法。

【03 强制】获取当前毫秒数 system.currenttimemillis(); 而不是 new date().gettime(); 说明:如果想获取更加精确的纳秒级时间值,使用 system.nanotime()的方式。在 jdk8 中, 针对统计时间等场景,推荐使用 instant 类。

【04 推荐】任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存。

【05 推荐】及时清理不再使用的代码段或配置信息。 说明:对于垃圾代码或过时配置,坚决清理干净,避免程序过度臃肿,代码冗余。

== 正例:对于暂时被注释掉,后续可能恢复使用的代码片断,在注释代码上方,统一规定使用三 个斜杠(///)来说明注释掉代码的理由。

 

4.10)【异常处理】


【01 强制】对大段代码进行 try-catch,这是不负责任的表现。catch 时请分清稳定代码和非稳 定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的 catch 尽可能进行区分 异常类型,再做对应的异常处理。

【02 参考】在代码中使用“抛异常”还是“返回错误码”,对于公司外的 http/api 开放接口必须 使用“错误码”;而应用内部推荐异常抛出;跨应用间 rpc 调用优先考虑使用 result 方式,封 装 issuccess()方法、“错误码”、“错误简短信息”。

== 说明:关于 rpc 方法返回方式使用 result 方式的理由: 1)使用抛异常返回方式,调用方如果没有捕获到就会产生运行时错误。 2)如果不加栈信息,只是 new 自定义异常,加入自己的理解的 error message,对于调用 端解决问题的帮助不会太多。如果加了栈信息,在频繁调用出错的情况下,数据序列化和传输 的性能损耗也是问题。

 

4.11)【日志规约】


【强制】应用中不可直接使用日志系统(log4j、logback)中的 api,而应依赖使用日志框架 slf4j 中的 api,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。

【推荐】谨慎地记录日志。生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使 用 warn 来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘 撑爆,并记得及时删除这些观察日志。

4.12)【单元测试】


【01 强制】好的单元测试必须遵守 air 原则。 说明:单元测试在线上运行时,感觉像空气(air)一样并不存在,但在测试质量的保障上, 却是非常关键的。好的单元测试宏观上来说,具有自动化、独立性、可重复执行的特点。

 a:automatic(自动化)  i:independent(独立性)  r:repeatable(可重复)

【02 强制】保持单元测试的独立性。为了保证单元测试稳定可靠且便于维护,单元测试用例之间 决不能互相调用,也不能依赖执行的先后次序。

== 反例:method2 需要依赖 method1 的执行,将执行结果做为 method2 的输入。

【03 强制】对于单元测试,要保证测试粒度足够小,有助于精确定位问题。单测粒度至多是类级 别,一般是方法级别。

【04 推荐】单元测试的基本目标:语句覆盖率达到 70%;核心模块的语句覆盖率和分支覆盖率都 要达到 100%

【05 推荐】对于数据库相关的查询,更新,删除等操作,不能假设数据库里的数据是存在的, 或者直接操作数据库把数据插入进去,请使用程序插入或者导入数据的方式来准备数据。

【06 推荐】单元测试作为一种质量保障手段,不建议项目发布后补充单元测试用例,建议在项 目提测前完成单元测试。

 

4.13)【安全规约】


【01 强制】用户请求传入的任何参数必须做有效性验证。

== 说明:忽略参数校验可能导致:

 page size 过大导致内存溢出

 恶意 order by 导致数据库慢查询 

 任意重定向 

 sql 注入

 反序列化注入 

 正则输入源串拒绝服务 redos 

==说明:java 代码用正则来验证客户端的输入,有些正则写法验证普通用户输入没有问题, 但是如果攻击人员使用的是特殊构造的字符串来验证,有可能导致死循环的结果。

【02 强制】在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防重放限制, 如数量限制、疲劳度控制、验证码校验,避免被滥刷、资损。 说明:如注册时发送验证码到手机,如果没有限制次数和频率,那么可以利用此功能骚扰到其 它用户,并造成短信平台资源浪费。

【03 推荐】发贴、评论、发送即时消息等用户生成内容的场景必须实现防刷、文本内容违禁词过 滤等风控策略。

4.14)【mysql数据库】


【01 强制】主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。 说明:pk_ 即 primary key;uk_ 即 unique key;idx_ 即 index 的简称。

【02 强制】小数类型为 decimal,禁止使用 float 和 double。

==说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不 正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储。

【03 强制】varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长 度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索 引效率。

【04 推荐】单表行数超过 500 万行或者单表容量超过 2gb,才推荐进行分库分表。 说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。

【05 强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。

== 说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明 显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据 墨菲定律,必 然有脏数据产生。

【06 强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度即可。 说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*)的区分度 来确定。

【07 推荐】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合 索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。 正例:where a=? and b=? order by c; 索引:a_b_c 反例:索引中有范围查找,那么索引有序性无法利用,如:where a>10 order by b; 索引 a_b 无法排序。

【08 推荐】利用延迟关联或者子查询优化超多分页场景。

==说明:mysql 并不是跳过 offset 行,而是取 offset+n 行,然后返回放弃前 offset 行,返回 n 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过 特定阈值的页数进行 sql 改写。

== 正例:先快速定位需要获取的 id 段,然后再关联: select a.* from 表 1 a, (select id from 表 1 where 条件 limit 100000,20 ) b where =

【09 推荐】建组合索引的时候,区分度最高的在最左边。

==正例:如果 where a=? and b=? ,a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即 可。

== 说明:存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。如:where a>? and b=? 那么即使 a 的区分度更高,也必须把 b 放在索引的最前列。

【10 推荐】防止因字段类型不同造成的隐式转换,导致索引失效。

【11 参考】创建索引时避免有如下极端误解: 1)宁滥勿缺。认为一个查询就需要建一个索引。 2)宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增速度。 3)抵制惟一索引。认为业务的惟一性一律需要在应用层通过“先查后插”方式解决

【12 强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 sql92 定义的 标准统计行数的语法,跟数据库无关,跟 null 和非 null 无关。 说明:count(*)会统计值为 null 的行,而 count(列名)不会统计此列为 null 值的行。

【13 强制】count(distinct col) 计算该列除 null 之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为 null,那么即使另一列有不同的值,也返回为 0。

【14 强制】使用 isnull()来判断是否为 null 值。 

==说明:null 与任何值的直接比较都为 null。 1) null<>null 的返回结果是 null,而不是 false。 2) null=null 的返回结果是 null,而不是 true。 3) null<>1 的返回结果是 null,而不是 true。

【15 参考】truncate table 比 delete 速度快,且使用的系统和事务日志资源少,但 truncate 无事务且不触发 trigger,有可能造成事故,故不建议在开发代码中使用此语句。 说明:truncate table 在功能上与不带 where 子句的 delete 语句相同。

 

4.15)【orm映射】


【01 推荐】不要写一个大而全的数据更新接口。传入为 pojo 类,不管是不是自己的目标更新字 段,都进行 update table setc1=value1,c2=value2,c3=value3; 这是不对的。执行 sql 时,不要更新无改动的字段,一是易出错;二是效率低;三是增加 binlog 存储。

【02 参考】中的 comparevalue 是与属性值对比的常量,一般是数字,表示相等时带 上此条件;表示不为空且不为 null 时执行;表示不为 null 值时 执行。 

三、番外--git的使用

    【01 常见git命令】    


#【001】

统一概念:工作区:改动(增删文件和内容)

暂存区:输入命令:git add 改动的文件名,此次改动就放到了 ‘暂存区’

本地仓库(简称:本地):输入命令:git commit 此次修改的描述,此次改动就放到了 ’本地仓库’,每个 commit,我叫它为一个 ‘版本’。

远程仓库(简称:远程):输入命令:git push 远程仓库,此次改动就放到了 ‘远程仓库’(github 等)

commit-id:输出命令:git log,最上面那行 commit xxxxxx,后面的字符串就是 commit-id

#【002】

#编辑修改等

git show # 显示某次提交的内容 git show $id

git checkout <file-name> #放弃工作区的修改 ,类似于 svn revert

git revert <commit-id> #以新增一个 commit 的方式还原某一个 commit 的修改

#比较diff

git diff <branch1>..<branch2> # 在两个分支之间比较

git diff --staged # 比较暂存区和版本库差异

git diff --cached # 比较暂存区和版本库差异

git whatchanged --since='2 weeks ago' #查看两个星期内的改动

git diff --word-diff #详细展示一行中的修改

#查看提交记录

git log -p -2 # 查看最近两次详细修改内容的diff

git blame <file-name> #查看某段代码是谁写的, blame 的意思为‘责怪’,你懂的。

git reflog #显示本地更新过 head 的 git 命令记录 ,类似 shell的 history

git log --all --grep='<given-text>' #在 commit log 中查找相关内容

#git 本地分支管理

git branch -r # 查看远程分支

git branch <new_branch> # 创建新的分支

git co <branch> # 切换到某个分支

git co $id # 把某次历史提交记录checkout出来,但无分支信息,切换到其他分支会自动删除

git branch -d <branch> # 删除某个分支

git branch -vv 展示本地分支关联远程仓库的情况

git merge <branch> # 将branch分支合并到当前分支

#git暂存管理

git stash # 暂存

git stash list # 列所有stash

git stash apply # 恢复暂存的内容

git stash drop # 删除暂存区

#git远程分支管理

git pull --no-ff # 抓取远程仓库所有分支更新并合并到本地,不要快进合并

git push # push所有分支-- 要慎用,还是要push具体的分支好一点 https://www.cnblogs.com/djiankuo/p/6492533.html

git push -u origin develop # 首次将本地develop分支提交到远程develop分支,并且track

git push origin master # 将本地主分支推到远程主分支

git push origin dev_20190513_registrationpath #我们的java项目 数据统计的git push命令

#git远程仓库管理

git remote -v # 查看远程服务器地址和仓库名称

git remote show origin # 查看远程服务器仓库状态

【02 】本地仓库“三棵树”    


本地仓库由 git 维护的三棵“树”组成。

1)【图01】本地仓库git 三棵树

2019.05.26  周日--《阿里巴巴 Java 开发手册》精华摘要
本地仓库git 三棵树

2)【图02】git本地三棵树的相互转化命令:

 

2019.05.26  周日--《阿里巴巴 Java 开发手册》精华摘要
git本地三棵树的相互转化命令

3)三棵树的更详细的命令示意图

2019.05.26  周日--《阿里巴巴 Java 开发手册》精华摘要
三棵树的更详细的命令示意图

 

git commit的时候,只是提交的 缓存区内的内容(如果你git add过,否则也等同你本地工作区内容的提交)

== git add可以实现我之前在 云主机上保存临时文件的tmpdjp的操作

==git diff 对比的是工作区和 缓存区的区别

==git diff --cached 对比是 缓冲区和本地的 head版本库的对比

另外需要指出来的是 git stash 不在上面的“三颗树”里,git stash 是暂存区,区别于 缓存区“stage” 

git stash的用法见 

四、写在最后

    简单的摘录,见仁见智,希望喜欢java开发的同学能从中收益。

    欢迎关注我的微信公众号哈 “ 程序员的文娱情怀” http://t.cn/rotyztu