Git -- 重写提交历史
本文将通过介绍通过rebase和filter-branch重写提交历史,但两者都会新建提交对象,谨慎使用,尤其是提交历史已共享的情况下 交互式rebasegit rebase -i,基于某个提交对象开始,通过交互的方式,依次进行rebaseRebase的内容请参照「Git++ - 分支」 12345678910111213141516171819202122232425262728$ git log --oneline --decorate --graph --all* 3b1df9b (HEAD -> master) C4* bed6252 C3* 2b17907 C2* 4c02e18 C1* b71fde1 C0$ git rebase -i HEAD~3 # rebase onto (4c02e18 C1)reword 2b17907 C2 # editedreword bed6252 C3 # editedpick 3b1df9b C4# Rebase 4c02e18..3b1df9b onto 4c02e18 (3 command(s))## Commands:# p, pic...
Git -- Stash
本文主要介绍stash操作,常用于储藏未完成的工作,以免将脏状态保存为一个提交 git stashgit stash:储藏working directory和index的当前状态(不包括untracked文件)git stash apply:仅应用working directory的修改,不应用index的修改git stash list:stash列表git stash drop:删除stash 1234567891011121314151617181920212223242526272829303132$ gst -sb## masterM a.txt M b.txt$ git stash list # Stdout print nothing$ git stash # save working directory and index stateSaved working directory and index state WIP on master: 2e5960b add a.txt b.txtHEAD is now at 2e5960b add a.txt b.txt$ gstOn ...
Git -- 引用和提交区间
本文主要介绍常见的引用(commit对象及其祖先的的引用,branch引用,HEAD引用等)和提交区间commit对象,tag对象的内容请参照「Git++ - 对象」 引用commit对象引用git show:显示Git对象信息 1234567891011$ git log --oneline --decorate --graph --all* 4f6c14f (HEAD -> master) add README.md$ git show --oneline -s 4f6c14f4f6c14f add README.md$ git show --oneline -s HEAD4f6c14f add README.md$ git show --oneline -s master4f6c14f add README.md commit对象祖先的引用 在Fast Forward Merge中,只有一个父提交对象,第一父提交对象在Recursive Merge中,合并操作发生时的当前分支所指向的提交对象是第一父提交对象,被合并的分支所指向的提交对象是第二父提交对象 HEAD^:HEAD的第一...
Git -- 分支
本文主要介绍一些我在日常开发中与Git分支相关的一些操作,通过实例阐述一些基本分支概念 分支的本质Git分支的本质仅仅只是指向Commit对象的可变指针 master分支并非一个特殊分支 MergeFast-Forward Merge当前分支(HEAD)指向的Commit对象是待被合并分支所指向Commit对象的**上游**,只需要简单地向前移动HEAD指针 12345678910111213141516171819202122$ git log --oneline --decorate --graph --all* c4292f7 (hotfix) C4| * bebf901 (dev) C3|/* b17415c (HEAD -> master) C2* 425fa18 C1* 1f62295 C0$ git merge hotfixUpdating b17415c..c4292f7Fast-forward C4 | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 C4$ git log --o...
Git -- 有趣的命令
本文主要介绍一些我在日常开发中觉得比较有趣的Git基础命令 差异对比日常开发中,差异对比是执行比较频繁的命令HEAD一般指向当前分支的最后一次Commit,下面三种是我最常用的差异对比 git diff尚未暂存的Working Tree与HEAD的差异 git diff –cachedIndex与HEAD的差异注 : 别名git diff --staged git diff HEAD尚未暂存的Working Tree + Index与HEAD的差异 操作实例12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455$ gst -sb## master$ lsREADME.md$ echo 'Hello' >> README.md$ gst -sb## master M README.md$ git diffdiff --git a/README.md b/README.mdindex e69de29..e965047 10...
JVM基础 -- 类初始化
本文主要关注类加载过程中的类初始化阶段,介绍clinit方法、主动引用和被动引用 clinit类(接口)初始化阶段是执行**clinit**方法的过程 接口 clinit 接口的clinit方法主要用于在接口初始化时,**初始化接口的域**(默认是public static final) 编译后,接口中的域,有些会在Class文件常量池中,有些在clinit方法中进行初始化 代码1234567public interface InterfaceClinit { class InnerClass { } InnerClass INNER_CLASS = new InnerClass(); String NAME = "zhongmingmao";} 字节码1234567891011121314151617181920public static final me.zhongmingmao.class_initialization.InterfaceClinit$InnerClass INNER_CLASS; ...
JVM基础 -- 晋升规则
本文将通过最基本的垃圾收集器(Serial + Serial Old),简单地讲述JVM内存分配和回收过程中的3个基本的晋升规则:大对象直接晋升、对象年龄晋升、动态晋升代码托管在:https://github.com/zhongmingmao/jvm_demo -XX:+UseSerialGC 新生代采用Serial垃圾收集器(Copying算法,单线程,Stop The World) 老年代采用Serial Old垃圾收集器(Mark-Compact算法,单线程,Stop The World) Minor GC / Major GC / Full GC常规理解 Eden空间不够 ➔ Minor GC ➔ 回收Young Generation Old Generation空间不够 ➔ Major GC ➔ 回收Old Generation Method Area(Java 8开始由MetaSpace实现,之前由Permanent Generation实现)空间不够 ➔ Full GC ➔ 回收Young Generation+Old Generation+Method Ar...
JVM基础 -- 伪泛型
本文将从JVM字节码的角度解释一下Java为什么是伪泛型 伪泛型 Java是伪泛型的,泛型在Java中只是语法糖,是通过类型擦除和强制转换来实现的 在运行期,ArrayList<Integer>与ArrayList<String>就是同一个类,在Java中并不存在类似与ArrayList<Integer>这种泛型类型 代码1234567891011121314151617181920public class FakeGeneric { static class Father { } static class Son extends Father { } private static void checkFather(Father father) { } public static void main(String[] args) { Map<Father, Father> map = new HashMap<...
JVM基础 -- 方法重载 + 方法重写
本文将从JVM字节码的角度解释方法重载与方法重写 方法重载代码12345678910111213141516171819202122232425262728293031323334package me.zhongmingmao.test;public class StaticDispatch { interface Human { } static class Man implements Human { } static class Woman implements Human { } public static void sayHello(Human human) { System.out.println("Hello , I'm a human"); } public static void sayHello(Man man) { System.out.println("...
JVM基础 -- JVM字节码执行过程
本文将通过是实例简单介绍JVM字节码基于栈的执行过程 Stack Frame 一个方法从调用到执行完成,对应着一个栈帧(Stack Frame)在虚拟机栈(VM Stack)里面从入栈到出栈的过程 在编译成字节码期间,栈帧需要多大的局部变量表(Local Variable Table),多深的操作数栈(Operand Stack)都已经完全确定,并且写入到方法表的Code属性中 在活动线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧,与这个栈帧关联的方法称为当前方法 局部变量表 用于存放方法参数和方法内部定义的局部变量 方法表中的locals属性记录了局部变量表的最大容量 局部变量表的存储单元为32-bit的slot,boolean、byte、char、short、int、float等会占用一个slot,long和double会占用两个slot 如果执行的是实例方法,那么第0个slot默认存储this 为了节省栈帧空间,slot是可重用的 操作数栈 方法表中的stack属性记录了操作数栈的最大深度 操作数栈可以容纳任意的Java数据类型,32-bit数据类型所占用的栈容量为1,64-bi...













