纪念一个真正改变世界的人

十月 22nd, 2011

虽然Dennis M. Ritchie去世的消息我一周前就已经知道了,但是一直未能写一些文字聊以纪念我这位尊敬的导师,而且我也相信他几乎是所有程序员的导师,因为真的需要好好地静下心,虔诚的纪念一下这位计算机界最伟大的科学家。

Dennis Ritchie black

Dennis M. Ritchie的一生最伟大的两个成就是设计了C语言和UNIX操作系统(和另一位同样伟大的Ken Thompson一起),而正是这两样东西几乎奠定了整个计算机程序设计的基础。计算机中几乎所有的软件都和这两样东西有着或远或近的血缘关系,之前,人们都说Steve jobs是改变世界的人,然而,他赖以成功的mac os x系统的内核其实就是UNIX,iphone和ipad上所用的ios系统的设计语言objective-c只是c语言几十种变种中的一个。如果说Steve jobs是亚历山大、凯撒,那么Dennis M. Ritchie则是柏拉图、苏格拉底、亚里士多德一样的存在。前者建立了时代,而后者缔造了文明。谁真正改变了世界,不言而喻。

对我说自己而言,Dennis M. Ritchie是灯塔一样的存在,当时光大约九年前,那时候,我是一名浙江大学计算机系的大二的学生,拿着一本谭浩强的教程很郁闷地学着编程,除了考试还是考试,我慢慢意识到高中的学习方法,也许能很顺利通过考试,但显然不能满足我对大学的理想,凭借着在中学时代自学basic语言和dos系统经验,我知道编程不应该是这个样子的,一定是哪里出了问题,但始终不得其门而入,当时甚至不理解指针指向的地址到底是内存中的地址还是硬盘中的地址,更谈不上做点自己想做的事情,直到某一天,在图书馆随手拿起了一本《计算机应用文摘》,看到了一篇很奇妙的文章,具体的内容我已经忘记了,大意是批评了谭浩强那种教育方式,然后推荐了C语言设计者的巨作《the c programming language》,文字极具自信和感染力,当即决定找这本书来看看,为了寻找这本书的原版,联系了这篇文字的作者,gaobo,电话里留下了QQ,之后经常向他请教c语言的学习方法,那时候,gaobo也只是上海交通大学计算机系大三的一个学生,从今天的眼光来看,他那时候已经具备了教授《程序员入门培训》这样的课程(当然,如果有这门课的话。)的能力。当时,和所有的初学者一样,我总是有很多今天看起来很毛躁的问题,比如如何学好指针,为什么这样编译不通过,什么编译器好之类的,然而gaobo是一个不是那么具有耐心的人,几次不耐烦的教育下来,他给了我一个BBS讨论区,说可以在这里问你想问的问题,即是饮水思源的C板,于是,从此我有了在水源的第一个id:lingjiexyz。

在今天看来,无论是gaobo还是饮水思源的C板,还是手里这本已经被我翻得破旧不堪的《the c programming language》 ,都成为了我走上这条道路的关键,这位尊敬的导师给我带了良师益友,带来了自信,工作和荣耀。Dennis M. Ritchie至少改变了我的人生,让我用感激的目光,目送这个伟大而低调的灵魂.

Stay hungry, stay foolish

十月 9th, 2011

 

从2011年10月6日,醒来打开手机看微博的那一刻,我就知道自己必须写点什么,因为这对我这样的人,无论如何,这是一个非常特殊的消息,而对于我所处的这个行业,这也是一个时代宣告结束,在我 看来,这是一个属于计算机界的”希腊-罗马”时代,一个计算机界的”中国先秦时代”,随着时间延伸。人类将会越来越将这个时代神圣化。

毫无疑问。Steve jobs是伟大的,他创立的Apple公司让图形界面,鼠标,以至于多点触摸这些真正推动计算机时代的标志性技术真正的进入了实用的领域,没有他。也许windows系统只是DOS系统的一个模块,没有他,也许IBM不会考虑PC领域,而Bill Gates的”每个人的桌面上都有一台PC”的梦想要遥远许多,是的,也许没有他,我们最终也会拥有这些技术,是的,也许是时代把他放在了那个位置,但是,又如何?至少这是他,不是你,也不是我,这就够了,这就足以证明他是计算机界最伟大的CEO,凯撒一样的传奇。

毫无疑问,Steve jobs是一个有个性的,如果不是他对于技术艺术家般的追求,今天的微软也许只有office,如果不是他对于创新有一种宗教式偏激,也许不会有mac os x,ios这样的能被称为艺术的软件、不会有macbook,iphone、ipad这样的让人不可思议的时尚设备,而正是这些启蒙了windows,android,启蒙了IBM的PC,HTC的手机 。或者也许以后三星的平板,这是真正的自由,因为眼里不只有钱(也不视金钱如粪土),这是真正的伟大 ,因为这不止成就了Apple,这成就了一个时代。

Steve jobs说过”如果你每天对着镜子说,今天你将死去,你会做很多必须做的事情 ,而总有一天,你会发现你是对的。”(大意如此),这也算我的人生态度,因为了解死亡,才会热爱时间,因为有所准备,随时接受死亡,而且,jobs是佛教徒,对于佛教徒来说,死亡是一个机会,让你永远跳出轮回,我虽不信佛,但我希望他跳出这个轮回,这个世界,他已经玩够了,应该不需要留恋,我因此祝贺他。

Thank you said Stay hungry, stay foolish.

Goodbye steve jobs.

秋日闻香见桂花

九月 29th, 2011

香溢书斋如琼浆,

恍惚入肠已半醉,

抬眼朦胧望远窗,

月宫桂花上门来。

Git简易教程

九月 28th, 2011

概述

在说明什么是git之前,我们需要对版本控制(Version Control)做一个基本的概述,一般情况下,我们的源代码都是在时间和空间两个维度上进行管理并维护的,代码本身以及组织代码的项目文件(如makefile或者vs的项目文件)都是以文件和目录的形式存储在磁盘空间上的,这种文件管理的形式已经被大家所熟悉了,然而,我们在不同时间段里做出的各种修改怎么管理呢?版本控制系统 (Version Control System,以下简称VCS)就是一种记录代码修改演化的系统,他的功能就是方便你今后找回某个特定时期(或版本)的文件、查看版本之间发生了哪些变化、对变化进行比较或者是修正致命错误。

版本控制系统主要经历了本地版本控制,集中式版本控制到分布式版本控制的发展:

  • 本地版本控制(Local Version Control System)顾名思义就是本地化的版本控制系统,没有网络协作等较为先进的版本控制的概念。
  • 集中式版本控制(Centralized Version Control System)为有一台版本控制服务器运行在那边存放并提供一个项目中所有版本文件的服务,在很长一段时间内占据主流,其中CVS与SVN为其代表。
  • 分布式版本控制(Distributed Version Control System)克服了集中式版本控制可能因为单点失败造成的巨大损失的缺点,让每一台客户端在每一次checkout操作后都完全镜像整个版本控制中的项目。在分布式版本控制系统中,任何一台机器都可以视为版本控制服务器。即使有一台服务器失去服务能力,其它机器与系统可以继续协作维持版本控制系统的正常运转。git就是分布式版本控制系统。

git与其它主流的VCS最大的区别就是,在项目版本更新的过程中,git记录的并非是基于初始文件的变化数据,而是通过一系列快照(Snapshot,就像是个小型的文件系统)来保存记录每个文件。如果有些文件在版本更新后没有发生任何变化,那么在新的版本中它会是一个指向最近一次更新的文件版本的链接。 此外,几乎所有git的操作都是在本地进行的,所以,没有了”延迟”,几乎所有的操作都是瞬间完成的。例如,当你想要查看项目历史时,不需要特地去服务器上抓取历史记录,直接在本地浏览即可。这意味着,你可以在本地对比两个不同版本的文件的差别,可以在本地查看过去有哪些人对指定文件作出了修改与更新,可以……几乎完全本地化的操作也让这样一种场景成为了可能: 当有人由于没有网络连接条件但是又必须抓紧时间对自己的项目进行修改与开发,同时又需要有版本管理系统来记录每次他commit的历史,这时,git提供了他所有需要的便利。

git使用SHA-1 Hash算法加密生成的40位字符串(而不是文件名)来记录代表git中的每样东西。格式就像这样:

??6bafcdc09f3d6d416f6572f82082987a486d3098

git中的文件主要会处于三种状态,它们分别是:

  • Committed: 文件或数据已经安全的存放在了git本地数据库中
  • Modified: 文件或数据已经修改但是尚未commit到数据库
  • Staged:文件或数据已被标记要放入到下一次commit中

这样的机制致使git的镜像会由三个部分组成(假设有一个git目录叫git-repo):

  • Git directory: 存放项目中所有元数据以及对象的地方(git-repo/.git/)
  • Working directory: 在这里是从git项目数据库中checkout出的一个单独的(默认情况下是最新的)项目版本,用于对指定项目版本中的文件进行修改和编辑(git-repo/)
  • Staging area: 一般是存放在Git directory中的一个简单的文件,里面存放着下一次需要commit的文件的信息(在git-repo/.git/中)

安装与配置

Git可以安装在各种操作系统下,下面以windows为例,linux系统和mac os系统的用户可以查找github.com上的help内容。

在windows下安装git非常简单,只要依次完成下面操作即可:

第一步:下载 msysgit(http://code.google.com/p/msysgit/), 安装时一般只需要保留默认选项, 只是要注意,不要使用putty作为客户端,GitHub只支持openssh. 安装完成后需要生成SSH Key。

第二步:配置ssh的key,在用户目录下(windows下通常是C:\Documents and Settings\<your_username>,其他系统通常都是/home/<your_username>)如果已经存在ssh的配置会存有一个.ssh目录(是隐藏目录),目录下会存有两个文件(id_rsa, id_rsa.pub),将其备份一下,然后生成新的,这里cygwin的命令序列如下

$ ssh-keygen -t rsa -C “your_mail_addr@yourmail.com”
Enter file in which to save the key (/c/Users/<your_username>/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):<此处需要你为其设定一个密码>
Enter same passphrase again:<重复一遍密码>
Your identification has been saved in /c/Users/<your_username>/.ssh/id_rsa.
Your public key has been saved in /c/Users/<your_username>/.ssh/id_rsa.pub.
The key fingerprint is:
e8:ae:60:8f:38:c2:98:1d:6d:84:60:8c:9e:dd:47:81 your_mail_addr@yourmail.com

第三步:将Public Key 添加到你所需要提交的服务器上(这里以GitHub为例,其他服务器的方式联系相关的管理员),打开你的GitHub->SSH Public Key->点击”Add another public key”,  将你的public key(id_rsa.pub)的内容拷贝到GitHub中。

第四步:测试配置是否成功,同样的,在cygwin里如此输入:

$ ssh git@github.com
ERROR: Hi <your_username> You’ve successfully authenticated, but GitHub does not provide
shell access
Connection to github.com closed.

看到以上信息表示操作成功,接下来,我们可以学习一些基本使用。

本地基本操作

首先我们要初始化一个Repository,如果完全是新建一个项目,我们可以:

mkdir test
cd test
git init

这个时候,test目录下就会多出一个叫做.git的目录,该目录下会有个config文件,他的内容如下:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true

我们需要加入自己的用户信息(注意,该信息必须与你配置ssh的时候的信息保持一致):

[user]
        name = your_username
        email = your_mail_addr@yourmail.com

当然,用户信息我们完全可以用命令行来配置,在git init命令之前输入如下命令:

  git config –global user.name “your_username”
  git config –global user.email “your_mail_addr@yourmail.com

如果项目目录已经存在,我们可以直接:

cd existing_git_repo
git init

接下来就是一些基本的操作了……

首先要用的是:git status,该命令用于查看目前git镜像的状态,在使用git的过程中,我们将会反复的使用到这个工具:

$ git status
# On branch master
#
# Initial commit
#
nothing to commit (create/copy files and use “git add” to track)

可以看出,git status给出了相当详细的信息,第一行中首先给出的是git的分支(branch)状态信息,接着,git会告诉你现在还没有东西提交到镜像中,建议先使用命令git add来对文件进行追踪。所以,接下来我们介绍git add命令, 假设在的工作目录中使用python语言写一个helloworld的小程序,将代码保存完成后,我们得到一个hello.py文件,然后,我们希望将这个文件被git镜像追踪(track)到,那么只需要:

$ git add hello.py

这样,我们就将hello.py加入到了git镜像中去进行版本控制,再次使用git status来查看目前的镜像状态:

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use “git rm –cached …” to unstage)
#
# new file: hello.py
#

注意这里它提到了changes to be committed,意思是该文件已经处于staged状态,接下去你可以根据自己的需要将其提交(commit),或者如果你觉得这是一个误操作,该文件不应当被提交,你可以通过git rm –cached命令来取消它的staged状态(你会发现status信息中给出了精确的提示)。

现在,我们通过命令git commit将hello.py提交:

$ git commit

这时,会出现一个带有status信息的文本给你编辑(使用什么编辑器取决于你对git的配置),在以”#”开头的注释行下输入一些文本,用于注释此次提交,方便于其他代码协作者的维护与理解!

你也可以通过命令参数-m来直接输入注释内容,加快提交速度:

$ git commit -m “comment here”

至此,你的文件hello.py已经处于tracked状态!。

现在,我们有一个hello.py在镜像中了,接下来,假设发现了一个小错误,额,比如一个循环的条件写错了,于是我们需要针对文件完成修改,之后,当我们再次git status的时候:

# On branch master
# Changed but not updated:
# (use “git add …” to update what will be committed)# (use “git checkout — …” to discard changes in working directory)
#
# modified: hello.py
#
no changes added to commit (use “git add” and/or “git commit -a”)

git status显示,hello.py被修改过了,如果你想要提交,需要再次git add该文件,或者,可以直接使用git commit -a跳过add的步骤,直接提交(尚未track的文件必须先git add才能进行提交)。

在提示中,还有提到说,如果你想撤销对hello.py的修改,就可以使用git checkout命令来实现,这里的情况会是:

$ git checkout – hello.py

如果你这么做了,你就会发现,你的hello.py又回到了之前没有被修改过的时候的状态。

在Unix/Unix-like系统中,几乎都会有一个小巧的对比文件不同的工具叫做diff,在git中也有这么一个工具,来详细比较你修改后准备提交的文件与修改前的状态的不同之处,恩,也许你猜到了,这个命令就是git diff

现在我们尝试着再次修改一下hello.py,然后运行git diff:

$ git diff
diff –git a/ hello.py b/ hello.py
index befc634..a86316b 100644
— a/hello.py
+++ b/hello.py
@@ -1,3 +1,4 @@
+/* new comment line */
if __name__ == “__main__”:
print “hello, world!”

通过git的diff工具,很容易了解到我们更改了哪些地方。这个时候,如果我们想撤销之前的更改,可以使用git reset命令:

$ git reset HEAD hello.py
$ git status
# On branch master
# Untracked files:
# (use “git add …” to include in what will be committed)
#
# hello.py
nothing added to commit but untracked files present (use “git add” to track)

再次git status,hello.py又回到了untracked状态!

接下来,如果需要修改README.txt(通常是项目的自述文件)的文件名(千万要记得我们的文件在git的镜像中进行版本控制管理,不要鲁莽的直接使用unix命令mv或者rm来对git镜像中的文件进行普通的文件操作),我们该使用git mv命令:

$ git mv README.txt tutorial.txt
$ git status
# On branch master
# Changes to be committed:
# (use “git reset HEAD …” to unstage)
#
# renamed: README.txt -> tutorial.txt
#
$ git commit -a -m “renamed a file”
[master 55ce30d] renamed a file
1 files changed, 0 insertions(+), 0 deletions(-)
rename README.txt => tutorial.txt (100%)

可以看到,在提交变更后,README.txt在文件系统以及git镜像中都被成功地重命名为了tutorial.txt。同样的,你可以unstage来撤销对该文件的重命名,the choice is yours!

如果我们不再需要tutorial.txt这个文件,我们可以将其从git镜像中删除,git中删除文件的命令是git rm:

$ git rm tutorial.txt
rm ‘tutorial.txt’
$ git status
# On branch master
# Changes to be committed:
# (use “git reset HEAD …” to unstage)
#
# deleted: tutorial.txt
#
$ git commit -a -m ” deleted a file”
[master 7d81981] deleted a file
1 files changed, 0 insertions(+), 1 deletions(-)
delete mode 100644 tutorial.txt

正如之前所提到的,这些操作都是可以恢复的,因为git是版本控制系统,所以自然而然的就会有一套版本历史管理机制。

我们可以用工具git log提供了查看git镜像的commit历史:

$ git log
commit 7d819818530ce89322019ba5000723c973eb0420
Author: ghosTM55
Date: Sun Mar 14 15:26:22 2010 +0800


deleted a file


commit 55ce30d88fb5c81d20bdf86e2034053613fed632
Author: ghosTM55
Date: Sun Mar 14 15:11:39 2010 +0800

renamed a file

commit 2ed9f1f9bd1a7561cd7e57dcdbd7f2cda54668fb
Author: ghosTM55
Date: Sun Mar 14 14:58:11 2010 +0800

a little change

基本上可以清楚地看到,git详细记录了每次commit的信息(checksum值、提交者信息、提交时间)。

下面简单的说一下分支管理的操作,git的分支管理是异常的简单和方便,可以用git branch命令进行非常直观的操作:

首先可以在工作目录下查看当前的项目存在多少分支:

$ git branch
* master
test

可以清楚地看到,目前该项目存在两个分支master和test,带*的是当前分支(我们可以用命令git checkout test切换到test反之)。接下来我们为项目添加一个分支:

$ git branch new
$ git branch
* master
new
test

我们看到新分支new已经添加进git的镜像里了,如果要删除该分支,我们可以如此:

$ git branch -d new
Deleted branch new (was 63c0da1).
$ git branch
* master
test

这时候我们就看到new已不在镜像中,当我们需要将指定分支中的代码合并到默认分支的时候,可以使用命令:

远程基本操作

(这部分引用一个网络blog:http://archive.cnblogs.com/a/2050324/)

要参与任何一个 Git 项目的协作,必须要了解该如何管理远程仓库。远程仓库是指托管在网络上的项目仓库,可能会有好多个,其中有些你只能读,另外有些可以写。同他人协作开发某 个项目时,需要管理这些远程仓库,以便推送或拉取数据,分享各自的工作进展。管理远程仓库的工作,包括添加远程库,移除废弃的远程库,管理各式远程库分 支,定义是否跟踪这些分支,等等。本节我们将详细讨论远程库的管理和使用。

查看当前的远程库

要查看当前配置有哪些远程仓库,可以用 git remote 命令,它会列出每个远程库的简短名字。在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个名字来标识你所克隆的原始仓库:

$ git clone git://github.com/schacon/ticgit.git
Initialized empty Git repository in /private/tmp/ticgit/.git/
remote: Counting objects: 595, done.
remote: Compressing objects: 100% (269/269), done.
remote: Total 595 (delta 255), reused 589 (delta 253)
Receiving objects: 100% (595/595), 73.31 KiB | 1 KiB/s, done.
Resolving deltas: 100% (255/255), done.
$ cd ticgit
$ git remote
origin

也可以加上 -v 选项(译注:此为 –verbose 的简写,取首字母),显示对应的克隆地址:

$ git remote -v
origin    git://github.com/schacon/ticgit.git

如果有多个远程仓库,此命令将全部列出。比如在我的 Grit 项目中,可以看到:

$ cd grit
$ git remote -v
bakkdoor git://github.com/bakkdoor/grit.git
cho45 git://github.com/cho45/grit.git
defunkt git://github.com/defunkt/grit.git
koke git://github.com/koke/grit.git
origin git@github.com:mojombo/grit.git

这样一来,我就可以非常轻松地从这些用户的仓库中,拉取他们的提交到本地。请注意,上面列出的地址只有 origin 用的是 SSH URL 链接,所以也只有这个仓库我能推送数据上去(我们会在第四章解释原因)。

添加远程仓库

要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,运行 git remote add [shortname] [url]

$ git remote
origin
$ git remote add pb git://github.com/paulboone/ticgit.git
$ git remote -v
origin    git://github.com/schacon/ticgit.git
pb    git://github.com/paulboone/ticgit.git

现在可以用字串 pb 指代对应的仓库地址了。比如说,要抓取所有 Paul 有的,但本地仓库没有的信息,可以运行 git fetch pb

$ git fetch pb
remote: Counting objects: 58, done.
remote: Compressing objects: 100% (41/41), done.
remote: Total 44 (delta 24), reused 1 (delta 0)
Unpacking objects: 100% (44/44), done.
From git://github.com/paulboone/ticgit
* [new branch] master -> pb/master
* [new branch] ticgit -> pb/ticgit

现在,Paul 的主干分支(master)已经完全可以在本地访问了,对应的名字是 pb/master,你可以将它合并到自己的某个分支,或者切换到这个分支,看看有些什么有趣的更新。

从远程仓库抓取数据

正如之前所看到的,可以用下面的命令从远程仓库抓取数据到本地:

$ git fetch [remote-name]

此命令会到远程仓库中拉取所有你本地仓库中还没有的数据。运行完成后,你就可以在本地访问该远程仓库中的所有分支,将其中某个分支合并到本地,或者只是取出某个分支,一探究竟。(我们会在第三章详细讨论关于分支的概念和操作。)

如果是克隆了一个仓库,此命令会自动将远程仓库归于 origin 名下。所以,git fetch origin 会抓取从你上次克隆以来别人上传到此远程仓库中的所有更新(或是上次 fetch 以来别人提交的更新)。有一点很重要,需要记住,fetch 命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。(说 明:事先需要创建好远程的仓库,然后执行:git remote add [仓库名] [仓库url],git fetch [远程仓库名],即可抓取到远程仓库数据到本地,再用git merge remotes/[仓库名]/master就可以将远程仓库merge到本地当前branch。这种分支方式比较适合独立-整合开发,即各自开发测试好后 再整合在一起。比如,Android的Framework和AP开发。

可以使用–bare 选项运行git init 来设定一个空仓库,这会初始化一个不包含工作目录的仓库。

$ cd /opt/git
$ mkdir project.git
$ cd project.git
$ git –bare init

这时,Join,Josie 或者Jessica 就可以把它加为远程仓库,推送一个分支,从而把第一个版本的工程上传到仓库里了。)

如果设置了某个分支用于跟踪某个远端仓库的分支(参见下节及第三章的内容),可以使用 git pull 命令自动抓取数据下来,然后将远端分支自动合并到本地仓库中当前分支。在日常工作中我们经常这么用,既快且好。实际上,默认情况下 git clone 命令本质上就是自动创建了本地的 master 分支用于跟踪远程仓库中的 master 分支(假设远程仓库确实有 master 分支)。所以一般我们运行 git pull,目的都是要从原始克隆的远端仓库中抓取数据后,合并到工作目录中当前分支。

推送数据到远程仓库

项目进行到一个阶段,要同别人分享目前的成果,可以将本地仓库中的数据推送到远程仓库。实现这个任务的命令很简单: git push [remote-name] [branch-name]。如果要把本地的 master 分支推送到 origin 服务器上(再次说明下,克隆操作会自动使用默认的 master 和 origin 名字),可以运行下面的命令:

$ git push origin master

只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那 你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,并到自己的项目中,然后才可以再次推送。有关推送数据到远程仓库的详细内容见第三章。

查看远程仓库信息

我们可以通过命令 git remote show [remote-name] 查看某个远程仓库的详细信息,比如要看所克隆的origin 仓库,可以运行:

$ git remote show origin
* remote origin
URL: git://github.com/schacon/ticgit.git
Remote branch merged with ‘git pull’ while on branch master
master
Tracked remote branches
master
ticgit

除了对应的克隆地址外,它还给出了许多额外的信息。它友善地告诉你如果是在 master 分支,就可以用git pull 命令抓取数据合并到本地。另外还列出了所有处于跟踪状态中的远端分支。

实际使用过程中,git remote show 给出的信息可能会像这样:

$ git remote show origin
* remote origin
URL: git@github.com:defunkt/github.git
Remote branch merged with ‘git pull’ while on branch issues
issues
Remote branch merged with ‘git pull’ while on branch master
master
New remote branches (next fetch will store in remotes/origin)
caching
Stale tracking branches (use ‘git remote prune’)
libwalker
walker2
Tracked remote branches
acl
apiv2
dashboard2
issues
master
postgres
Local branch pushed with ‘git push’
master:master

它告诉我们,运行 git push 时缺省推送的分支是什么(译注:最后两行)。它还显示了有哪些远端分支还没有同步 到本地(译注:第六行的 caching 分支),哪些已同步到本地的远端分支在远端服务器上已被删除(译注:Stale tracking branches 下面的两个分支),以及运行 git pull 时将自动合并哪些分支(译注:前四行中列出的 issues 和 master 分支)。(此命令也可以查看到本地分支和远程仓库分支的对应关系。)

远程仓库的删除和重命名

在新版 Git 中可以用 git remote rename 命令修改某个远程仓库的简短名称,比如想把 pb 改成 paul,可以这么运行:

$ git remote rename pb paul
$ git remote
origin
paul

注意,对远程仓库的重命名,也会使对应的分支名称发生变化,原来的 pb/master 分支现在成了paul/master

碰到远端仓库服务器迁移,或者原来的克隆镜像不再使用,又或者某个参与者不再贡献代码,那么需要移除对应的远端仓库,可以运行 git remote rm 命令:

$ git remote rm paul
$ git remote
origin

推荐书籍

版本控制之道——使用Git

副标题: —使用Git
作者: Travis Swicegood
译者: 董越 / 付昭伟 / 等译
出版社: 电子工业出版社
出版年: 2010年5月
页数: 204
定价: 39.80元

Git权威指南

作者: 蒋鑫
出版社: 机械工业出版社华章公司
出版年: 2011-6
页数: 593
定价: 89.00元
装帧: 平装
ISBN: 9787111349679

避谈人生

九月 6th, 2011

常有人对我说,你久居家中,不知世间残酷,如此这般,我终笑而不语,珠不知残酷已在此人嘴中,既我久居家中,便可如此自居过来人,奈我无言以辨,此一也;虽知此人幼稚,然奈其好意不可驳其薄面,有言难明,此其二也;既不可驳面,亦被当作默认,自然各种教训纷沓自来,恶性循环,无穷尽矣,其三也。社会残酷有无外 仗势欺人,有言难诉,忍气吞声三者乎?

社会残酷,自古有之,非久居家中而能不知,况如今网络社会之复杂甚于现实多矣,然,世之残酷人皆对之,无碍,其无情耳,无情则可图利,有能者居之耳,尚可。亲朋好友之残酷,有情,进不可薄情,退不可自薄,迷茫岂不更胜于前者乎?

世故者当避谈人生,何也?言之必错而害人耳,望人慎之。

译书感悟

八月 26th, 2011

最近参与了《测试驱动的javascript开发》译书工作,到今天《译者序》的最终定稿,意识到这项工作终于告一段落了,对我来说,这真是一段奇妙的经历,值得为之留下一些心得体会。
起初,我绝没有想到这本书会让我投注那么多的精力,对我来说只不过又是一次帮帮朋友审稿的小事罢了,这位朋友也出版了几本技术译作了,我完全信任他对这项工作的责任心,但是我一直都希望技术出版能有越来越好的质量,于是自持懂一点javascript,不停地给出一些几乎是鸡蛋里挑骨头的批评。所幸的是朋友并没有对我的指手画脚有任何的怨念,而我也认为这是我对技术的信仰,真心地希望在我的“鞭策”之下,能有一本更有质量的译作出版,为中国开发者们提供一些帮助。
直到有一天,这位朋友跟我说。书还有两章,我来不及了,不如你来吧,两个月内完成。我顿时觉得有点蒙,之前完全没有译书的经验,而且时间那么紧张,我完全不知道自己有任何的把握做这件事,但我最终还是决定接受这个“重托” ,因为这对我来说也是一种责任,既然已经做了那么多了,就让这本书修成正果吧。而且对我自己未尝不是一种历练 。
接下这任务的时候,我最担心的是能不能按时完成任务,同时保证我所追求的质量,这方面我没有任何的参考系,于是做了很多预防性的措施,我让我的另一个好友朱磊跟我同步进行翻译,只不过我从前一章开始,他从后一章开始,然后聚合起来,选择一个最令人满意的结果,也许我这样做是太谨慎了,但是作为第一次完成这样的工作,我认为还是必要的,宁可让人觉得我字面上的工作不多,也要保证书本身的质量,并按时完成任务。
当然,由于中英文在技术表达上的巨大差异,要找到一种既有很好的阅读性,又能表达精确的行文风格是一个超乎想像的工作,我和朋友们都为此尽了最大的努力,但是仍然不能说这个结果没有遗憾。有时候,“严于律己”实在是有些虚伪了,但无论如何,我觉得,这是一个尽了我最大努力的工作了。

读“当年明月”书后感

八月 20th, 2011

“当年明月”之明史。低于正史,高于演义,且有作者自身见解,于当今浮躁世界,不可多得,可得庙堂之雅,亦可感市井之娱。读史本也该如此,读之甚悦。其中自太祖创业,屠官,成祖靖难,明四大奇案、直至东林阉党之争,煤山自缢。将明二百余年之事洋洋洒洒几十万字娓娓道来,其实,在余之见,虽都表了”人性”二字,然角度不可不谓新颖,较于过往通篇仁义忠孝之伪君子之言好上千百倍,使人尚有所获。虽皮毛亦可知足矣。

余常与友人叹,二十四史之中,尤明史最难,兴于攘外,亡于党争,终复被异族取而代之。此一惑也;文明昌盛,民富于江南,国强于内阁,火枪火炮之军败于金戈铁马之流,此二惑也;有明一代,内阁与皇权可制衡于天下矣,当是时,手工业亦已崛起于民间,何故不得变革之路,此三惑也。

有人常说,史者,王侯将相之家事耳,惑之何谓?余笑对曰,人者,循规蹈矩之类也,虽有史四五千年,真创新者甚少,故若有人知前事一万,而后事尚一事不解,如此书呆之流,诚属不易也,读史,非为故事之真假,而为知人耳,若知人,则可明今日之事。焉能无谓?

在C++中使用sqlite的示例

八月 5th, 2011

最近因为工作原因,终于使我有机会腾出时间来接触了一下SQLite数据库,结果是该数据库在一系列高级Framework的实用性和用户体验让我感到兴奋,于是我打算在主要的工作环境中—C++—试试看这个工具,也许以后可以作为常用的工具。一些实验下来,感觉不错,下面将简单的介绍一下静态链接(即连接.ib文件)的方式:

准备工作:

使用环境:环境: VS2008

在SQLite的官方网站下载Windows平台下的3.7.4版本的SQLite, 下载地址:
http://www.sqlite.org/sqlite-dll-win32-x86-3070400.zip    
压缩文件中包含了sqlite3.dll和sqlite3.def文件,接着打开V2008自带的命令行工具, 用LIB命令生成用于连接(LINK)使用的lib文件:
LIB /DEF:sqlite3.def /machine:IX86
这样就生成了:sqlite3.lib 和 sqlite3.exp 两个文件,sqlite3.lib文件是我们连接程序所使用的。

在SQLite官方网站下载SQLite3的源程序, 下载地址:
http://www.sqlite.org/sqlite-amalgamation-3070400.zip
解压出sqlite3.h文件

打开VS2008,新建项目→Visual C++→win32控制台应用程序→(项目名字自己取),然后在项目向导里勾选”空项目”,如下图所示:

将(1)和(2)中得到的文件放在项目源文件所在的目录中, 此时该目录下应该包含:
sqlite3.h
sqlite3.dll
sqlite3.lib
sqlite3.def
这四个文件.

开始编写程序

先配置一下项目,选择菜单: “项目” → “(项目名称) 属性…”, 在弹出的对话框中选择”配置属性” →”链接器” →”输入”, 在”附加依赖项”中输入”sqlite3.lib”,并在”模块定义文件”中输入”sqlite3.def”,如果需要的话,还可以在”延迟加载的dll”里输入”sqlite3.dll”,整体如下图所示:

然后继续在对话框中选择”配置属性”→”C/C++”→”预编译头”, 在”创建/使用预编译头”中确认一下状态是”不使用预编译头”,以便项目不会引入一些windows环境相关的预处理选项。然后”确定”。

接下来,将sqlite3.h引入项目,然后新建源文件db.cpp和main.cpp,在db.cpp里输入代码:

#include <cstdio>

#include <cstdlib>

#include “sqlite3.h”

 

int testdb(void)

{

    sqlite3 *db=NULL;

    char *zErrMsg = 0;

    int rc;

 

    //打开指定的数据库文件,如果不存在将创建一个同名的数据库文件

    rc = sqlite3_open(“zsl.db”, &db);

    if( rc )

    {

        fprintf(stderr, “Can’t open database: %s\n”, sqlite3_errmsg(db));

        sqlite3_close(db);

        return (1);

    }

    else

        printf(“You have opened a sqlite3 database named zsl.db successfully!\n”);

 

    //创建一个表,如果该表存在,则不创建,

    //并给出提示信息,存储在zErrMsg

    char *sql = ” CREATE TABLE test(ID INTEGER PRIMARY KEY,AGE INTEGER,LEVEL INTEGER,NAME VARCHAR(12),SALARY REAL);” ;

    sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );

 

    //插入数据

    sql = “INSERT INTO \”test\” VALUES(NULL , 1 , 1 , ’200605011206′, 18.9 );” ;

    sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );

    int nrow = 0, ncolumn = 0; //查询结果集的行数、列数

    char **azResult; //二维数组存放结果

 

    //查询数据

    sql = “SELECT * FROM test “;

    sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );

    int i = 0 ;

    printf( “row:%d column=%d \n” , nrow , ncolumn );

    printf( “\nThe result of querying is : \n” );

    for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )

        printf( “azResult[%d] = %s\n”, i , azResult[i] );

 

    //删除数据

    sql = “DELETE FROM test WHERE AGE = 1 ;” ;

    sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );

    //释放掉azResult 的内存空间

    sqlite3_free_table( azResult );

    sqlite3_close(db); //关闭数据库

    int c=getchar();

 

    return 0;

}

在main.cpp里输入代码:

#include “sqlite3.h”

 

int testdb(void);

int main( void )

{

    testdb();

}

然后编译,如果没什么问题的话,终端会输出如下结果:

而在源文件所在目录会多出一个数据库文件:zsl.db。

至此大功告成。

安装sqlite心得

八月 5th, 2011

最近的一项测试引发了一次连锁反应的技术学习,因为测试需要去学了点Google App Engine,因为GAE又需要学点django,结果引起了对django的兴趣,又因此去学了点sqlite,下面把sqlite安装部署过程做一个总结,以备自己和别人日后参考。

首先,对sqlite做一个简单的介绍,SQLite 是一个嵌入式的关系数据库系统,使用十分广泛,它不像常见的客户端/服务器结构范例(简称C/S),SQLite引擎不是个让程序与之通信的独立进程,而是连接到程序中成为程序的一个主要部分。所以主要的通信协议是在编程语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库(定义、表、索引和数据本身)都在宿主主机上存储在一个单一的文件中。它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的,这会给开发工作(特别是非企业级的应用)带来不必要的资源成本(内存和硬盘容量)和部署成本(部署数据库服务器很多地方需要单独购买服务),而且他又比access这样的数据库更为安全,并且全面支持SQL92的标准,对于小型的桌面开发和web服务开发来说,这是个非常不错的选择。

接下来,言归正传,介绍一下sqlite的安装过程,这是相当简单的:

sqlite最新版本可以从这里下载。

http://www.sqlite.org/download.html

我们这里将以Windows下的sqlite3.7.4为例介绍其安装方法(各自可以选择下载安装适合自己的版本),建议下载shell和dll两个包方便日后的开发,下载后,将这两个包解压缩至C:\sqlite目录(也可以选择你喜欢的任何目录)即完成安装。

C:\sqlite目录构造为:

C:\sqlite

|

+–sqlite3.exe

+–sqlite3.dll

+–sqlite3.def

把该目录加进系统的环境变量,然后打开一个shell窗口(我这里使用MYSY,也可以使用windows自带的cmd),输入命令sqlite3,出现如下信息,说明安装成功。

如果你不喜欢命令行终端操作,可以下载图形界面的管理shell,因为这个项目是开源的,所以有很多优秀的管理shel可以使用,我这里使用的是sqliteadmin程序,界面如下图所示:

大家可以到此处下载:http://sqliteadmin.orbmu2k.de/

另外比较知名的图形管理shell有:(资料来自http://zh.wikipedia.org/wiki/SQLite

  • Navicat導航貓 for SQLite 是一套專為 SQLite 設計的強大資料庫管理及開發工具。它可以用於任何版本 2 或 3 的 SQLite 資料庫,並支援大部份 SQLite的功能,包括觸發器、索引、檢視等。。
  • SQLiteMan,使用QT开发的一个SQLite客户端,支持多语言、跨平台。SQLiteMan
  • SQLite Manager,以Firefox浏览器的扩展形式提供的SQLite客户端。
  • SQLite Database Browser,一款连接SQLite数据库的图形客户端。
  • SqlPro SQL Client,又一款能工作在SQLite数据库上的图形客户端。
  • SQLiteSpy,是一个快速和紧凑的GUI SQLite数据库管理器。它读取sqlite3的文件和执行对他们的SQL。它的图形用户界面使得它很容易探索,分析和处理sqlite3的数据库。SQLiteSpy

另外,补充一点,sqlite扩展是蛮多的,支持很多Framework,比如.net Frameworks,可以到这个项目主页去下载相应的runtime:

http://sqlite.phxsoftware.com/

下载安装完成之后(只是个setup.exe,和一般的程序安装无异),可以在Visual Studio 2008里创建连接,选择数据联系方式是SQLite Database File (.NET Framework Data Provider for SQLite),如下图:

如此就可以在VS2008里面如常使用数据库了,正如下图展示的那样:

念奴娇 疯子梦话

八月 5th, 2011

都赞古国,有文明,封禁人言有遗风。
需看圣贤平天下,不想有士帝王师。
人言可畏,洪水滚滚,虚心见心虚。
何苦来也?要信我为奇迹。

惊闻狗儿俱来,不禁顿悟,此间犬做儒。
终见孔孟传人,签了几家合同。
有了乌纱,还有五毛,日子真和谐。
只需放屁,且看世间奈何?