昨天在github上疯狂找vim的配置文件,当然少不了需要用到git,正好也就把它系统的学习一下吧,之前也了解过一些,但其实不是很理解。这次觉得相对还是很透彻了。用到了一些进阶功能。
首先,事实上可能很多人还是把git当做svn之类的工具来用的,说的low一点相当于网盘,把你写好的代码放在服务器上做一个备份。但是,必须明白的是Linus大神写这个神奇的东西可不仅仅是为了这个,它的设计理念当然和svn不一样。svn我也不熟,就不瞎说的,只提一点,svn是集中式管理,就是所有人都要把代码都提交到中心服务器上才可以,而git是“分布式版本控制系统”,实际上是不需要中心服务器的,在本地就完全可以很好的工作,但由于github的出现,使得我们觉得git好像必须要有服务器一样。
闲言少叙,进入正题。(本文的操作基于Linux)
基本操作
-
git config --global user.name "lovelock" git config --global user.email "example@gmail.com"
上面这两条命令会在你的用户根目录也就是
$HOME
下建立一个.gitconfig文件,大致形式如下:[user] name = lovelock email = example@gmail.com
当然这其实也是github的要求,其他的代码托管我没有用过,但料想用户名和邮箱应该都是需要的。
-
git clone git@github.com:lovelock/linuxdots.git
这条命令是把我在github分享的一个linux配置文件克隆到本地。然后就可以进去进行各种修改,自己拿来用或者通过
pull request
提交到原始分支。 -
下面说一下创建新
repo
的方法。这个方法其实github的help页面已经说的很详细了,但我觉得很是不少人会遇到问题,看看stackoverflow上关于这些东西的问答就知道了。- 在github上创建一个
repo
,这里没有什么说的。 - 建立一个本地目录,如
mkdir linuxdots
,这个目录的名字没有必要和服务器端的相同。但通常会取一个容易区分的名字对吧。 cd linuxdots
进入linuxdots
目录git init
会在当前目录下创建一个.git
目录,这个用来存放git处理我们的代码的方法和差异文件等等。- 这时可以在这个目录下创建几个文件,比如
README.md
,你可能会不知道(我最开始知道git的时候可是真不知道)这个.md
的文件是什么,它叫markdown
,是一种用比HTML
的标记要更少更简单的标记来实现格式化文本的方法,现在我就在一个很舒服的markdown parser
马克飞象中编辑这篇文章。 git add .
这是通常的做法,意思是把当前目录下的所有文件变成staged for commit
状态,但当你的代码复杂后,难免出现回删除文件或文件夹的情况,这时单纯用这个命令就不行了,因为它的完整用法其实是
也就是说它的作用是把还没有在stage上文件加进来,而没有把已经在stage上然后被删除的文件变成gti add <file>...
unstaged
状态的功能。需要git add --all
来完成这件事。这时你当前目录的所有文件都已经“蓄势待发”了,下一步就是commit
了。git commit -m 'some message'
git强制需要在commit
时写一条信息,记录这次commit
做了什么。git remote add origin git@github.com:lovelock/linuxdots.git
,创建一个名为origin
的远程repo
,而因为指定了刚刚创建的repo
,这个origin
就像指针一样指向了指定的repo
。git push origin master
是把本地的master
分支上传到github上。至此相当于完成了创建一个“软件仓储的过程。
- 在github上创建一个
- 这里提一下上面几个步骤中会遇到的错误。
- 如果你按照上面提到的github的官方帮助文档中的说法(用
https
协议)你可能会遇到每一次提交都让你输入用户名和密码的问题,虽然这样看起来事很安全,但很烦不是吗?即使设置了密码失效时间,但还是需要经常输入啊。所以更干净利落的做法是用ssh
协议。 - 你可能听别人或者我说用
ssh
协议比较方便,然后发现各种fatal error
,说你没有权限什么的。理解这个问题又牵涉到ssh
的密钥的知识。这里简单提一点,你需要做的就是ssh-keygen
,想简单就一路回车,在你的根目录下生成一个.ssh
隐藏文件夹,这里面会有两个文件,id_rsa id_rsa.pub
,你这时需要做的是把id_rsa.pub
的内容复制到你的github.com
账户里受信任的key
列表里。这样你的本地机器和远程服务器就建立了信任关系,不需要每次都输入用户名和密码了,但要注意每次你克隆或其他操作时,相应的要用形如git clone git@github.com:lovelock/linuxdots.git
这样的命令,而不是git clone https://github.com/lovelock/linuxdots.git
。 - 还有一点需要提,git从2.0改变了
git push
操作的默认行为。1.x版本的默认操作是matching
,也就是如果执行git push
而没有指定分支,它将push所有本地的分支到远程仓储中对应匹配的分支。而新的行为是simple
,这样它只有当前分支会被push到你使用git pull
获取的代码。如果你在用1.x版本的git,也很简单,用git config --global push.default simple
即可。这句又会在$HOME/.gitconfig
中添加一行。
- 如果你按照上面提到的github的官方帮助文档中的说法(用
进阶操作
分支操作
为了加深我自己的理解,我在本地新建了一个仓储用来测试。举个例子,你的master
分支下已经有了一些文件,这时你想加入一个新的功能,但怕这个新功能的引入会对master
分支产生不好的影响,有了git
你需要做的就是git checkout -b aNewBranchName
,这相当于两步操作git branch aNewBranchName
和 git checkout aNewBranchName
,也就是新建一个分支,然后进入这个分支。如果你的shell支持的话,这时shell会有变化的提示。然后你可以在这里进行修改了。这里的操作不会影响master
分支。然后你做了足够的测试之后,认为可以合并到主分支了,那么首先切换到master
分支,然后git merge aNewBranchName
,就把后者合并到了主分支中。注意,如果你在原来文件的同一行进行了修改,那么合并时就会出错,因为git不知道你想用哪个覆盖哪个,这时就需要你手动去改了,这一点做得很好,它不替你做决定,就像一直提醒我们不要用rm -rf
这个命令一样。详细用法见Git分支-分支的新建与合并。
子模块
经常会看到某些项目中引用别人的项目,那个项目的名称会是灰色的,并且后面带一个@,这就是最简单的子模块(submodule)了。你clone这个项目时它不会把相应的文件都下载下来,而是只有子模块之外的东西,需要进入项目主目录,然后执行`git submodule init && git submodule update`把那些灰色的文件全部下载下来。还有一个问题,是如果你自己也想用别人的项目作为子模块,应该怎么办呢?我开始以为根本不用设置,因为每个项目中都有.git目录,难道不会自动识别?真不会。只能在项目主目录下新建一个.gitmodules文件,在里面用和.gitconfig一样的格式记录下。如下
[linuxdots] path = .vim/linuxdots url = https://github.com/lovelock/linuxdots.git
需要强调的是,这个项目下载完成之后的名字是由你决定的而不是由项目的原作者,说这话是因为有path这个选项,比如,需要用到oh-my-zsh,那么我把path指定成.zsh,因为我在.zshrc中把$ZSH设置为.zsh,这样下载完成之后它就自动重命名了。
更深入的我自己目前还用不到,看了也是忘记,用到再记下来吧。