一、squash
squash准确来说并不是一个命令,而是rebase命令的一个功能。squash的作用很简单——合并多个commit。
来看用法:
git rebase -i HEAD~5
-i的意思是使用“交互式”的修改方法。加了这个参数之后,Git会把所有commit列出来,让你进行一些修改,修改完成之后会根据你的修改来rebase。HEAD-5的意思是只修改最近的5个commit。
运行完这条命令之后,会进入一个编辑界面,大概是这样的:
pick awe Add sth pick add Have a rest pick xxc Wow pick cxz Yeah pick dsa Finish it
可以看到一共有5行,这就是最近的5个commit以及它们的信息。
假设我们现在想把它们合并成一个commit,要怎么做呢?直接看例子:
pick awe Add sth squash add Have a rest squash xxc Wow squash cxz Yeah squash dsa Finish it
我们把后4个commit的pick都改成了squash,修改完成之后保存退出,Git就会继续执行rebase命令了。执行完可以看一下结果,最后的4条commit都消失了,它们都被合并到了倒数第5条中。
现在大家应该理解了,squash的作用就是把当前commit向前合并,一直合并到pick为止。
rebase完成之后大家可以看一下最后一个commit的信息,里面会包含rebase之前最后5条的所有commit信息,也就是诸如“Add sth Have a rest Wow Yeah Finish it”这些东西。
二、fixup
fixup和squash非常类似,把pick修改成fixup,同样会向前合并到pick,唯一的区别就是,fixup会忽略当前commit的信息,只会应用修改。
怎么理解呢?还用上面的例子说,假设我们使用fixup代替squash:
pick awe Add sth fixup add Have a rest fixup xxc Wow fixup cxz Yeah fixup dsa Finish it
保存退出之后,等Git执行完rebase我们查看一下最后一条commit的信息,会发现里面只有“Add sth”,另外四条commit的信息比如“Have a rest”都没有了。
三、stash
stash是一条Git命令,作用非常简单——保存当前状态。
假设我们现在正在进行工作,修改了一些文件,添加了一些文件。这时我们突然想切换到另一个分支工作,但是又不想commit当前的修改(可能因为它们还不能运行),那该怎么办呢?答案就是stash。
来看命令——git stash
执行完命令之后,Git会把当前的状态保存,同时清理当前目录。我们可以运行一下 git status,会发现当前目录没有任何修改。这时我们就可以放心地切换分支工作了。
等其他工作结束,想继续之前的工作时,可以运行 git stash apply,Git会把保存的状态复原。
stash可以运行多次,会保存多个状态,可以运行 git stash list 来查看所有状态。运行 git stash apply 会默认复原到最近一次保存的状态,如果想指定复原状态可以使用 git stash apply stash@{2} ,这条命令会复原到 stash@{0} 状态。
运行 apply 之后,被复原的状态并不会自动删除,仍然在 stash list 当中。可以运行 git stash drop stash@{0} 来删除 stash@{0} 状态,或者使用 git stash pop 命令来代替 git stash apply 命令,这样复原之后会自动删除被复原状态。
如果 apply 的时候出现冲突(因为你 stash 之后对文件进行了修改),那么需要手动解决冲突。
最后需要注意一点:stash 复原的时候默认不复原 staged 文件,也就是说如果你运行过 add 命令,使用 git status 查看的话文件应当处于 staged 状态,但是如果你 stash 并复原再看,那个文件的状态又变回 unstaged 了。解决办法就是运行 git stash apply 命令时加上 –index 参数:git stash apply –index,这样就可以完全恢复到 stash 之前的状态。