Git使用基础篇
?
? ? ? ? ? Git是一个分布式的版本控制工具,本篇文章从介绍Git开始,重点在于介绍Git的基本命令和使用技巧,让你尝试使用Git的同时,体验到原来一个版 本控制工具可以对开发产生如此之多的影响,文章分为两部分,第一部分介绍Git的一些常用命令,其中穿插介绍Git的基本概念和原理,第二篇重点介绍 Git的使用技巧,最后会在Git Hub上创建一个开源项目开启你的Git实战之旅
1、Git是什么????????Git在Wikipedia上的定义:它是一个免费的、分布式的版本控制工具,或是一个强调了速度快的源代码管理工具。Git最初被Linus Torvalds开发出来用于管理Linux内核的开发。每一个Git的工作目录都是一个完全独立的代码库,并拥有完整的历史记录和版本追踪能力,不依赖 于网络和中心服务器。
????????Git的出现减轻了许多开发者和开源项目对于管理分支代码的压力,由于对分支的良好控制,更鼓励开发者对自己感兴趣的项目做出贡献。其实许多开源项目 包括Linux kernel, Samba, X.org Server, Ruby on Rails,都已经过渡到使用Git作为自己的版本控制工具。对于我们这些喜欢写代码的开发者嘛,有两点最大的好处,我们可以在任何地点(在上班的地铁 上)提交自己的代码和查看代码版本;我们可以开许许多多个分支来实践我们的想法,而合并这些分支的开销几乎可以忽略不计。
????????现在进入本篇文章真正的主题,介绍一下Git的基本命令和操作,会从Git的版本库的初始化,基本操作和独有的常用命令三部分着手,让大家能够开始使用Git。
????????Git通常有两种方式来进行初始化:
????????git clone: 这是较为简单的一种初始化方式,当你已经有一个远程的Git版本库,只需要在本地克隆一份,例如'git clone git://github.com/someone/some_project.git some_project'命令就是将'git://github.com/someone/some_project.git'这个URL地址的远程版 本库完全克隆到本地some_project目录下面
????????git init和git remote:这种方式稍微复杂一些,当你本地创建了一个工作目录,你可以进入这个目录,使用'git init'命令进行初始化,Git以后就会对该目录下的文件进行版本控制,这时候如果你需要将它放到远程服务器上,可以在远程服务器上创建一个目录,并把 可访问的URL记录下来,此时你就可以利用'git remote add'命令来增加一个远程服务器端,例如'git remote add origin git://github.com/someone/another_project.git'这条命令就会增加URL地址为'git: //github.com/someone/another_project.git',名称为origin的远程服务器,以后提交代码的时候只需要使用 origin别名即可
? ? ?现在我们有了本地和远程的版本库,让我们来试着用用Git的基本命令吧:
????????git pull:从其他的版本库(既可以是远程的也可以是本地的)将代码更新到本地,例如:'git pull origin master'就是将origin这个版本库的代码更新到本地的master主枝,该功能类似于SVN的update
????????git add:是将当前更改或者新增的文件加入到Git的索引中,加入到Git的索引中就表示记入了版本历史中,这也是提交之前所需要执行的一步,例如'git add app/model/user.rb'就会增加app/model/user.rb文件到Git的索引中
????????git rm:从当前的工作空间中和索引中删除文件,例如'git rm app/model/user.rb'
????????git commit:提交当前工作空间的修改内容,类似于SVN的commit命令,例如'git commit -m "story #3, add user model"',提交的时候必须用-m来输入一条提交信息
????????git push:将本地commit的代码更新到远程版本库中,例如'git push origin'就会将本地的代码更新到名为orgin的远程版本库中
????????git log:查看历史日志
????????git revert:还原一个版本的修改,必须提供一个具体的Git版本号,例如'git revert bbaf6fb5060b4875b18ff9ff637ce118256d6f20',Git的版本号都是生成的一个哈希值、
????????上面的命令几乎都是每个版本控制工具所公有的,下面就开始尝试一下Git独有的一些命令:
4、Git独有的一些命令? ? ? ?git branch:对分支的增、删、查等操作,例如'git branch new_branch'会从当前的工作版本创建一个叫做new_branch的新分支,'git branch -D new_branch'就会强制删除叫做new_branch的分支,'git branch'就会列出本地所有的分支
????????git checkout:Git的checkout有两个作用,其一是在不同的branch之间进行切换,例如 'git checkout new_branch'就会切换到new_branch的分支上去;另一个功能是还原代码的作用,例如'git checkout app/model/user.rb'就会将user.rb文件从上一个已提交的版本中更新回来,未提交的内容全部会回滚
????????git rebase:用下面两幅图解释会比较清楚一些,rebase命令执行后,实际上是将分支点从C移到了G,这样分支也就具有了从C到G的功能?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
????????git reset:将当前的工作目录完全回滚到指定的版本号,假设如下图,我们有A-G五次提交的版本,其中C 的版本号是 bbaf6fb5060b4875b18ff9ff637ce118256d6f20,我们执行了'git reset bbaf6fb5060b4875b18ff9ff637ce118256d6f20'那么结果就只剩下了A-C三个提交的版本
???????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
????????git stash:将当前未提交的工作存入Git工作栈中,时机成熟的时候再应用回来,这里暂时提一下这个命令的用法,后面在技巧篇会重点讲解
????????git config:利用这个命令可以新增、更改Git的各种设置,例如'git config branch.master.remote origin'就将master的远程版本库设置为别名叫做origin版本库,后面在技巧篇会利用这个命令个性化设置你的Git,为你打造独一无二的 Git
????????git tag:可以将某个具体的版本打上一个标签,这样你就不需要记忆复杂的版本号哈希值了,例如你可以使用 'git tag revert_version bbaf6fb5060b4875b18ff9ff637ce118256d6f20'来标记这个被你还原的版本,那么以后你想查看该版本时,就可以使用 revert_version标签名,而不是哈希值了
????????Git之所以能够提供方便的本地分支等特性,是与它的文件存储机制有关的。Git存储版本控制信息时使用它自己定义的一套文件系统存储机制,在代码根目录下有一个.git文件夹,会有如下这样的目录结构:
?
?
????????有几个比较重要的文件和目录需要解释一下:HEAD文件存放根节点的信息,其实目录结构就表示一个树型结构,Git采用这种树形结构来存储版本信息, 那么HEAD就表示根;refs目录存储了你在当前版本控制目录下的各种不同引用(引用指的是你本地和远程所用到的各个树分支的信息),它有heads、 remotes、stash、tags四个子目录,分别存储对不同的根、远程版本库、Git栈和标签的四种引用,你可以通过命令'git show-ref'更清晰地查看引用信息;logs目录根据不同的引用存储了日志信息。因此,Git只需要代码根目录下的这一个.git目录就可以记录完 整的版本控制信息,而不是像SVN那样根目录和子目录下都有.svn目录。那么下面就来看一下Git与SVN的区别吧
5、Git与SVN的不同????????SVN(Subversion)是当前使用最多的版本控制工具。与它相比较,Git最大的优势在于两点:易于本地增加分支和分布式的特性。
????????下面两幅图可以形象的展示Git与SVN的不同之处
???? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????
?
???????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
????????对于易于本地增加分支,图中Git本地和服务器端结构都很灵活,所有版本都存储在一个目录中,你只需要进行分支的切换即可达到在某个分支工作的效果。 而SVN则完全不同,如果你需要在本地试验一些自己的代码,只能本地维护多个不同的拷贝,每个拷贝对应一个SVN服务器地址。举一个实际的例子,以前我所 在的小组使用SVN作为版本控制工具,当我正在试图增强一个模块,工作做到一半,由于会改变原模块的行为导致代码服务器上许多测试的失败,所以并没有提交 代码。这时候上级对我说,现在有一个很紧急的Bug需要处理, 必须在两个小时内完成。我只好将本地的所有修改diff,并输出成为一个patch文件,然后回滚有关当前任务的所有代码,再开始修改Bug的任务,等到 修改好后,在将patch应用回来。前前后后要完成多个繁琐的步骤,这还不计中间代码发生冲突所要进行的工作量。可是如果使用Git, 我们只需要开一个分支或者转回到主分支上,就可以随时开始Bug修改的任务,完成之后,只要切换到原来的分支就可以优雅的继续以前的任务。只要你愿意,每 一个新的任务都可以开一个分支,完成后,再将它合并到主分支上,轻松而优雅。
????????分布式对于Git而言,你可以本地提交代码,所以在上面的图中,Git有利于将一个大任务分解,进行本地的多次提交,而SVN只能在本地进行大量的一 次性更改,导致将来合并到主干上造成巨大的风险。Git的代码日志是在本地的,可以随时查看。SVN的日志在服务器上的,每次查看日志需要先从服务器上下 载下来。我工作的小组,代码服务器在美国,每次查看小组几年前所做的工作时,日志下载就需要十分钟,这不能不说是一个痛苦。后来我们迁移到Git上,利用 Git日志在本地的特性,我用Ruby编写了一个Rake脚本,可以查看某个具体任务的所有代码历史,每次只需要几秒钟,大大方便我的工作。当然分布式并 不是说用了Git就不需要一个代码中心服务器,如果你工作在一个团队里,还是需要一个服务器来保存所有的代码的。
????????总结
????????本篇介绍了Git的基本概念、一些常用命令和原理,大家可以尝试动手体会一下,下一篇会重点介绍Git命令的使用技巧,Git附带的工具,最后会在Git Hub上创建一个开源项目。
上一篇介绍了Git的基本概念和一些基本命令,本篇的重点在如下三个部分:个性化定制你的Git,更酷更巧妙的使用Git,以及如何在Git Hub上开启你自己的开源项目。在所有技巧中,最重要的技巧是学会查看Git的帮助,因为Git是一个相对复杂的版本控制工具,如果你熟悉它的命令,那么给你带来的价值是不言而喻的,所以要学会掌握那根金手指─查看Git的帮助,在任何Git命令后加上'--help'就会显示该命令的帮助文档,例如 'git log --help'你就可以看到命令'git log'的所有使用方法。接下来,从打扮Git开始吧。
Git梳妆
我们可以利用Git的config命令或者直接编辑~/.gitconfig文件(如果没有的话创建它)来为自己打造独一无二的Git。我建议直接编辑用户目录下得.gitconfig文件,拿我本地的文件为例,一一为大家解说,完整的文件内容如下:
[user]
name = Phoenix
email = phoenixtoday@gmail.com
[alias]
co = checkout
ci = commit -a
st = status
br = branch
oneline = log --pretty=oneline --since='2 days ago'
onelog = log -p -1
[color]
status = auto
branch = auto
ui = auto
该文件主要包含三个部分的内容:
用户基本信息:可以设置你的名字和email,这样在你提交代码的时候就会显示出你的名字
命令别名:这是.gitconfig文件中,我最喜欢的部分,它可以大大减少你敲击键盘的次数(俗话说优秀的程序员都很懒么)。在该文件中,我将co设置为checkout的别名,那么下次我只要用'git co new_branch'就可以切换到new_branch分支下了,简洁而优雅;将ci设置为commit -a的别名,-a选项表示我不需要将修改和删除的文件通过'git add'命令来加入索引,这样设置在使用'git ci -m"message"'这样的命令时,相当于连续执行了'git add 被修改和删除的文件'和'git commit -m"message"'两条命令,再一次节省了我们宝贵的时间;最酷的是最后两行,后面的章节会一一介绍。Git提供许多优雅、人性化的选项,我们如果再结合别名的设置,可以发挥你最大的想象力,真的让你自己的Git活起来
颜色:每次看diff时是不是挺痛苦的?那么为什么不给我们的Git加上颜色呢?只需要加上那三行,就可以让红色和绿色的提示出现在你的控制台中
Git灵动
现在来讲讲'git log','git stash','git formate-patch'三个命令的用法和技巧:
git log:不同于SVN,Git将代码的历史记录全部在本地克隆了一份,所以这就使得'git log'这样的命令使用起来非常的迅速,也是我最常使用的Git命令之一。在使用'git log'的时候,你可以加入很多的后缀。'-p'表示查看修改的具体内容,例如'git log -p'它不但会打印出提交的时间、版本号、人员等,还会将具体的代码修改部分打印出来;'-n'其中n表示一个数字,这表示打印出具体的几个日志,例如 'git -p -1'正如我的Git配置文件中设置的onelog别名的内容一样,就表示打印出当前最新的一次日志记录及具体修改内容;'--since="时间/日期"','--until="时间/日期"'表示你希望查找某个日期段的日志记录,例如'git log --since="2 days ago" --until="1 hour ago"'就表示你希望查找两天前到一小时前的日志记录,Git是足够聪明的,它可以将类似于'2 days ago'和'1 hour ago'这种表示时间的英语转化为具体的时间数字;有的时候,你不希望翻很多页才可以看到所有的日志,你只希望看到简短的说明,那么Git为你提供打印格式的定制'git --pretty=格式种类',其中格式种类有full、short、oneline等,例如'git log pretty=oneline'就会将每条代码历史记录放在一行里,看起来简单明了
git stash:在第一篇中,我举了一个使用branch解决紧急任务切换的问题,其实stash命令也可以很好的解决这样的问题。当你不想提交当前完成了一半的代码,但是却不得不修改一个紧急Bug,那么使用'git stash'就可以将你当前未提交到本地(和服务器)的代码推入到Git的栈中,这时候你的工作区间和上一次提交的内容是完全一样的,所以你可以放心的修 Bug,等到修完Bug,提交到服务器上后,再使用'git stash apply'将以前一半的工作应用回来。也许有的人会说,那我可不可以多次将未提交的代码压入到栈中?答案是可以的。当你多次使用'git stash'命令后,你的栈里将充满了未提交的代码,这时候你会对将哪个版本应用回来有些困惑,'git stash list'命令可以将当前的Git栈信息打印出来,你只需要将找到对应的版本号,例如使用'git stash apply stash@{1}'就可以将你指定版本号为stash@{1}的工作取出来,当你将所有的栈都应用回来的时候,可以使用'git stash clear'来将栈清空
git format-patch:当你想给一个开源项目(例如Rails)提交一段代码的时候,或者你想给小组成员展示一段你并不想提交的代码,那么你还是需要 patch的,Git的'format-patch'命令良好的支持了这个功能。我来基本描述一下使用这个命令的步骤和方法:第一,利用branch命令创建一个分支;第二,修改你的代码;第三,在该分支上提交你的修改;第四,使用'git format-patch'命令来生成一个patch文件,例如:'git format-patch master --stdout > ~/Desktop/tmp.patch'就是将工作分支与master主干的不同,存放在'~/Desktop'文件夹下,生成一个叫做 tmp.patch的文件(另一种简单的版本是利用diff命令,例如'git diff ..master > ~/Desktop/tmp.patch'),这样就生成了patch文件。那么别人就可以使用'git apply'命令来应用patch,例如'git apply ~/Desktop/tmp.patch'就是将patch打在当前的工作分支上
Git亲友团
Git的使用技巧还包括利用Git包含的和附加的一些强大工具,这些工具主要包括git svn、git citool、gitk和Git的自动提示脚本:
git svn:Git和SVN可以很方便的集成在一起,这就大大减少了从SVN向Git迁移的学习成本,这也是我特别建议大家首次接触Git的使用方式。git svn是一个Git内置的工具,你安装了Git也就安装了它,譬如说你们团队有一个SVN服务器,但是你想利用Git本地的一些强大特性,那么你依然可以安装Git,使用Git的branch功能,只不过再更新代码和提交代码的时候,使用git svn命令即可。在这里我简单的讲讲最常使用和需要注意的两个命令,其余的命令读者可以通过'git svn --help'来查看:'git svn rebase'命令取代了'svn update'用于将服务器代码更新到本地;'git svn dcommit'取代了'svn ci',需要注意的是,本地必须用Git提交了代码之后,再使用'git svn dcommit'。只需要这样,你就可以轻松地从SVN转向Git了。
git citool:这是我个人使用率最频繁的一个工具,上一篇文章也提到了,Git可以本地提交代码,那么你自然可以本地修改你的提交了,这个工具就是可视化界面,用于修改你本地的提交。只要在你的工作区间输入'git citool',就会出现如下的界面
?
?
你可以用它来提交代码,可以用它来将你本地的修改追加在上一次提交的代码中,你还可以用它来修改你上次提交的信息等等。这个工具可以大大帮助你完成以前SVN不可能完成的任务
gitk:是一个查看主干/分支情况的工具,它主要用于观察整个项目的分支状况,使用'gitk'命令就会出现一个图形化界面供你查看,本篇就简单的说一下,大家回去试试就知道了
Git 的自动提示脚本:它是Shawn O. Pearce为了让Git使用起来更方便而写得Shell脚本,你可以在http://gitweb.hawaga.org.uk/ 找到一个叫做gitcompletion的脚本,下载下来,并按照该脚本中指导的方式进行配置,你就具有了Git自动提示(敲入部分Git命令,再按 Tab键)的功能,而且有了这个脚本,你也可以看到你当前工作在哪个branch下。惟一的不足是,它只支持Linux、Unix、Mac操作系统(推荐大家都用Mac进行开发)
Git实战─Git Hub
经过这么长时间理论知识的熏陶,想必大家早已跃跃欲试了,那么我们在Git Hub上建立一个开源项目作为实战演习吧。Git Hub是全球最大的Git服务器供应商,每个帐号有100M的免费使用空间,网址是:https://github.com/
首先我们在Git Hub上创建一个帐号,按照上面指导的方法设置好你的认证信息(每次提交代码都会需要这个认证信息)
然后,如下图新建一个项目(选择Create a New Repository),名叫git usage
?
?
在服务器端,你可以看到这个项目的信息,包括项目源代码的URL,如下图
?
?
在本地使用如下的命令,就可以完成你的第一次提交了:
mkdir git-usage(创建项目目录) cd git-usage(进入项目目录) git init(Git初始化) touch README(创建一个README文件) git add README(增加该文件到索引) git commit -m 'first commit'(本地提交) git remote add origin git@github.com:phoenixtoday/git-usage.git(增加远程服务器代码库地址) git push origin master(将本地代码提交到远程服务器上)
总结
我所在的项目小组自从使用Git后,发现Git提供的种种特性大大提高了我们的开发效率,在认识Git前我们无法想象一个版本控制工具可以让开发任务切换变得如此自然流畅。所以我强烈推荐大家使用Git,你付出的学习绝对物有所值