2019.05.26 周日--《阿里巴巴 Java 开发手册》精华摘要
一、写在开头
java作为一个编程界最流行的语言之一,有着很强的生命力。代码的编写规范也是不容忽视的,今天,我就把自己阅读的国内的互联网巨头阿里巴巴的《阿里巴巴 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 值,能够表示额外的信息,如:远程调用失败,异常退出。
【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 三棵树
2)【图02】git本地三棵树的相互转化命令:
3)三棵树的更详细的命令示意图
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