UnixAgain

热爱Unix及相关的一切

博客园 首页 联系 订阅 管理


昨天在github上疯狂找vim的配置文件,当然少不了需要用到git,正好也就把它系统的学习一下吧,之前也了解过一些,但其实不是很理解。这次觉得相对还是很透彻了。用到了一些进阶功能。

首先,事实上可能很多人还是把git当做svn之类的工具来用的,说的low一点相当于网盘,把你写好的代码放在服务器上做一个备份。但是,必须明白的是Linus大神写这个神奇的东西可不仅仅是为了这个,它的设计理念当然和svn不一样。svn我也不熟,就不瞎说的,只提一点,svn是集中式管理,就是所有人都要把代码都提交到中心服务器上才可以,而git是“分布式版本控制系统”,实际上是不需要中心服务器的,在本地就完全可以很好的工作,但由于github的出现,使得我们觉得git好像必须要有服务器一样。

闲言少叙,进入正题。(本文的操作基于Linux)

基本操作

  1. git config --global user.name "lovelock"
    git config --global user.email "example@gmail.com"
    

    上面这两条命令会在你的用户根目录也就是$HOME下建立一个.gitconfig文件,大致形式如下:

     [user]
         name = lovelock
         email = example@gmail.com
    

    当然这其实也是github的要求,其他的代码托管我没有用过,但料想用户名和邮箱应该都是需要的。

  2. git clone git@github.com:lovelock/linuxdots.git
    

    这条命令是把我在github分享的一个linux配置文件克隆到本地。然后就可以进去进行各种修改,自己拿来用或者通过pull request提交到原始分支。

  3. 下面说一下创建新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状态,但当你的代码复杂后,难免出现回删除文件或文件夹的情况,这时单纯用这个命令就不行了,因为它的完整用法其实是
            gti add <file>...
      
      也就是说它的作用是把还没有在stage上文件加进来,而没有把已经在stage上然后被删除的文件变成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上。至此相当于完成了创建一个“软件仓储的过程。
  4. 这里提一下上面几个步骤中会遇到的错误。
    • 如果你按照上面提到的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中添加一行。

进阶操作

分支操作

为了加深我自己的理解,我在本地新建了一个仓储用来测试。举个例子,你的master分支下已经有了一些文件,这时你想加入一个新的功能,但怕这个新功能的引入会对master分支产生不好的影响,有了git你需要做的就是git checkout -b aNewBranchName,这相当于两步操作git branch aNewBranchNamegit 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,这样下载完成之后它就自动重命名了。

 

更深入的我自己目前还用不到,看了也是忘记,用到再记下来吧。

posted on 2014-04-19 15:54  UnixAgain  阅读(255)  评论(0编辑  收藏  举报