Git之坑

最近在使用Git进行多人协作时遇到了一些坑,在些处记录一下。

在使用git的过程中,最频繁使用的应该就是git pull了。在git pull命令时,一般会遇到下面几种情况。

如果是本地完全没有修改,则可以顺利进行git pull,如果有本地提交会与git pull下来的commit进行自动merge(当然自动merge也有可能失败,手动解决一下冲突即可)。

如果本地的修改与被git pull下来的commit中修改有相同的文件,这时git会报错提示,这时只让你先把本地修改commit或stash一下,也不会有太大问题。

最坑的就是是本地有修改,并且与git pull下来的commit并没有修改相同的文件。但是本地的commit(即没有push到远程仓库的提交)与git pull下来的commit自动合并时冲突了,这里git会提醒你要使用git commit -a来提交,但是根据git commit -a的语义,其实他不仅仅是把冲突内容全部合并,还会把本地的其他没有完成的修改一并提交上去。

一般来说,本地的修改大都是不完整的修改,这里如果提交上去,很容易造成其他问题。因此为了保险起见,如果本地有修改一定要先使用git stash将本地修改暂存之后,再执行git pull命令去拉取代码。

上面的坑,最多只会造成不完整的修改被提交,很容易及时发现。

但是另外一个关于submodule的坑,在超过一个人协作的情况下如果不注意是必然会发生的事。

假设有A和B两个人进行协作修改工程P。在P中引用了submodule S。

最初P-A(A的本地仓库)与P-B(B的本地仓库)中对submodule S的引用都是commit 1(SHA-1:xxxxxxxxxxx)。

这里S仓库有一个bug被修复了,P-A将自己的本地仓库中S的引用更新至commit 2(SHA-1:xxxxxxxxxxxxx)。然后提交并push到远程仓库。

这之后,B对P-B仓库成功执行了git pull命令。理论上P-B的仓库此时对S仓库的引用已经变更为commit 2了。但是由于S在P-B目录中的最新commit依然为commit 1。

在这之后,其实P-B中的S仓库并没有任何变动,依然为commit1,并且除了使用git status可以主动查看外,git 在合并之后并没有任何主动提交。这时P-B在完成某项修改之后,直接使用git commit -a就会重新将对S仓库的引用变更为commit 1。并且git 不会有任何提示。

如果要解决这个问题,必须要每次git pull之后,立即执行git submodule update –init来将仓库中的S目录更新到当前最新引用值。

回首2016

16年初我又辞职了,即使在满足我的薪资要求的情况下。主要原因就在于,我的技术路线图受阻。

原本按我的打算,在有了少许高并发和socket经验之后,我需要进一下积累数据库使用实战经验。

然而在上家公司中,数据库部分操作是单独剥离出来,由java实现的。
而我所维护的C++部分仅仅处理高并发和正常的战斗逻辑并不涉及任何数据库部分。

因此,为了顺利继续我的技术路线图,我违反了自己的约定。

如果要找一个词来概括我2016年的大部分内容,那就是lua。

是的,正是由于这门语言,让我接触到了不一样的世界,函数式编程、面向原型编程,动态语言,虚拟机,协程,垃圾回收等各种以前闻所未闻的概念。

对于垃圾回收,我以前是有鄙视心理的,因为我曾一直有一个错觉,当你把这个对象置为nil,则此对象即会被释放,因此垃圾收集仅仅是屏蔽了malloc/free而已(就像是C++用引用来代替指针一样),在经过一段时间实践之后,才发现之前的短视。 并由此开始研究垃圾回收算法,如三色标记清除、引用计数,指针探测等各种不同的垃圾回收算法。

在luaVM源码中对于弱类型的实现,可以说是以C语言的方式来对ADT做出了完美诠释。其实说穿了,本质上抽象都是一样的,在C++的世界里我们还可以用OO的方式来实现, 这也再次说明其实大部分OO上的编程技巧并不是OO语言所专有的,重要的是在这背后的思想。

对于C++的特性,我一般是尽可能的少用C++提供的复杂的特性,对于模板我也是仅仅在极其必要是才会使用。因此模板我其实并不是非常熟。换言之,并不能写出很精秒的模板代码。但是新公司中将板模用于自动序列化的做法确实让我惊艳到了

在接触到数据库使用之后,由于我们使用的是内存数据库,我曾一度限入内存数据库和进程内cache之间取舍的纠结之中,最后终于幡然醒悟(当然也可能是误入歧途 :D)。

在不断重构silly的过程中,除了对lua及luaVM的了解不断加深,对于TCP/IP在linux实现的实现方式也有了更深入的了解。


不过遗憾的是,2015年我制定的目标,并没有完成。

一方面是因为时间没有想象中的那么充足。
另一方面则是因为初次接受这么多新奇的概念,在1年之内我很难做到完全消化。

因此,到目前为止, 我也仅仅做到对luaVM的源码有些熟悉而已,只阅读过部分luaVM中的源码(gc部分)。更谈不上脚本语言的设计和虚拟机的实现。

那么2017年,我的目标将是2016年的延续:
1. 阅读完luaVM的每一行源码
2. 设计一个虚拟机(如果有可能实现一个栈式虚拟机和一个寄存器虚拟机)
3. 阅读《计算机程序设计艺术》
4. 实现一个完整的blog系统(基于silly)
5. 研究一下主流的分布式系统源码如spark,zookeeper等

btw, 这一年的lua使用下来,我发现了一个事实。

动态语言并不简单,由于缺少类型系统等一些除错手段,因此编写动态语言代码往往需要更深厚的编码经验和准则。

当然这也是正常的,毕竟做任何事都是要付出代价的,动态语言简洁的代价便是,你需要有更清晰的头脑。

如果你不以为然,请试着用lua写一个1W行代码的的逻辑一试便知 🙂