为了学习git,我首先会登录到google查询git的官网地址,是http://git.or.cz/。毕竟git官方网站是最权威的学习git、下载git和更新git的地方嘛,其中的Documentation链接是用于用户入门和进阶的地方。最先映入眼帘的是这样一句话:git – the stupid content tracker。呵呵 你可能会认为怎么可以把stupid用在git上呢?其实,stupid在这里应该解释为“傻瓜式的”,而并非是你想象的那个意思^_^。对的,git就是一个傻瓜式的内容跟踪器。其次,你会看到官网对于“学习路线的推介”:新手请浏览gittutorial(7),然后是Everyday Git(包括了常用命令),接着是”man git-commandname”,cvs用户需要看gitcvs-migration(7),需要更全面的了解git请看 Git User’s Manual。如果你希望用“男人”来获取帮助,那么基本格式是这样:man git-commandname比如man git-log就是获取git日志方面的信息;man git-commit就是获取“提交项目”方面的信息。如果你连log或者commit都不知道,那也没关系,先man git看看都有哪些命令就可以了。那么细说git:
1.什么是git?
git官网上的原文解释是:Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. Git iseasy to learn and has atiny footprint with lightning fast performance. It outclasses SCM tools like Subversion, CVS, Perforce, and ClearCase with features likecheap local branching, convenientstaging areas, andmultiple workflows. (想了解更多我们可以查看http://git-scm.com/documentation)
Git在Wikipedia上的定义:它是一个免费的、分布式的版本控制工具,或是一个强调了速度快的源代码管理工具。Git最初被Linus Torvalds开发出来用于管理Linux内核的开发。每一个Git的工作目录都是一个完全独立的代码库,并拥有完整的历史记录和版本追踪能力,不依赖于网络和中心服器。
Git的出现减轻了许多开发者和开源项目对于管理分支代码的压力,由于对分支的良好控制,更鼓励开发者对自己感兴趣的项目做出贡献。其实许多开源项目包括Linux kernel, Samba, X.org Server, Ruby on Rails,都已经过渡到使用Git作为自己的版本控制工具。对于我们这些喜欢写代码的开发者嘛,有两点最大的好处,我们可以在任何地点(在上班的地铁上)提交自己的代码和查看代码版本;我们可以开许许多多个分支来实践我们的想法,而合并这些分支的开销几乎可以忽略不计。
2.安装git on windows?
在windows上安装git是非常容易的。msysGit 项目是易于安装过程的其中之一。简单的从Github 网页上下载并且运行它:http://msysgit.github.com/。
安装完成后,我们会发现有一个命令行的版本(它包含一个在之后方便使用的SSH client )和一个标准的GUI。
Note on Windows usage: you should use Git with the provided msysGit shell (Unix style), it allows to use the complex lines of command given in this book. If you need, for some reason, to use the native Windows shell / command line console, you have to use double quotes instead of simple quotes (for parameters with spaces in them) and you must quote the parameters ending with the circumflex accent (^) if they are last on the line, as it is a continuation symbol in Windows.
在Windows上的使用应注意:应使用与提供了 msysGit shell(Unix风格)的Git,在给出的这本书它允许使用复杂的命令行。如果出于某种原因需要使用本机Windows shell 或者命令行控制台,必须使用双引号,而不是简单的引用(与空间参数),如果他们最后在一行的最后,你必须引用以弯曲的口音(^)结束的参数,这是由于它是一个延续在Windows象征。
3.安装完成后的第一次操作
打开git bash/git shell后
1.设置SSH建立计算机与Github的链接
- 运行命令 cd ~/.ssh 检查自己的电脑上是否存在sshkeys,如果显示No such file or directory 则需要去创建一个新的ssh keys,
- 运行命令:$ ssh-keygen -t rsa -C "your_email@youremail.com"点击回车来创建新的ssh keys 输入你的passphrase(密码),并重新输入确认,这样一个新的keys就创建完成了,上面代码显示,密匙位置放在了C:/Users/用户名/.ssh/文件夹中。(.ssh文件夹可能是隐藏的,需要查看隐藏文件)
- 将你新生成的ssh keys 添加到github中。在 GitHub 网站点击“Account Settings” > 点击 “SSH Public Keys”> 点击 “Add another public key”,在本机找到你创建的密匙文件id_rsa.pub,使用记事本打开,复制里面所有的内容,粘贴到网站key的文本框中,点击Add Key 保存将.ssh文件打开,复制内容到空白处。
2. 打开注册的github网页
然后创建自己的仓库,必须保证这个仓库与本地提交的仓库名一样,此时我创建的是Testjava仓库。
3.配置用户信息
回到git bash,把自己介绍给git,即就是要设置本地git的用户名和邮箱,下面命令将修改/home/[username]/.gitconfig文件,也就是说下面的配置只对每一个ssh的用户 可见, 所以每个人都需要做。以下两条命令配置好好后提交代码的log里面会显示提交者的信息 :
git config –global user.name “Your Name”
git config –global user.email “you@example.com”
任何人在使用git之前,都要提交简单的个人信息,以便git区分不同的提交者身份。
4. 如何导入一个新的git项目
我们可以将我们编写的项目(假设有TestDiv.java和TestMod.java两个个文件),而且这个项目的全部代码和资源都放在Testjava目录 下,此处Testjava文件可以用命令创建在自己想放的仓库位置(mkdir Testjava),现在我将用下面的步骤来导入这个项目:
- 验证一下ssh.因为下图是设置好之后重新打开的git bash。所以可以验证一下ssh, 用命令ssh -T git@github.com,提示输入之前自己设置的passphrase(密码),完成回车告知我们此用户成功被认证,但是github不能提供shell访问。
- 想在e盘创建Testjava文件,其中加入了含有TestDiv.java和TestMod.java两个文件的文件夹shujutest.操作一下命令来完成导入:
$cd e: //切换到e盘目录下
$mkdir Testjava //创建仓库名为Testjava,与github上的仓库名一致
$cd Testjava //进入到仓库下
$git init // 用于初始化当前所在目录的这个项目(Testjava),shell返回的提示表明已经建立了一个.git隐藏目录来保存这个项目目前的进展信息。
$touch READNE //添加一个README 文件,用以记录我们对于代码的注释和使用方法,由我们自己在本地完成的项目文档。
$git add README
$git add shujutest
$git commit -m "first commit"
$git remote add Test1 git@github.com:Horizonyi/Testjava.git
$git push -u origin master
注意:一般默认的是 $git remote add Orig git@github.com:Horizonyi/Testjava.git,这里默认的远程仓库是origin,但是由于自己多次添加设置了远程仓库,提示错误:remote origin alreay exits,造成无法push到远程仓库,所以采取办法发是:先将origin pull 到本地仓库(git pull -u origin master),然后再一次push(git push -u origin master).
可以用命令来查看我们的远程仓库: git remote -v.
删除远程仓库:git
4.常用命令的解释:
想要新增一个文件文件时,必须老实的git add:
git add: 要求git给我目前的这个项目制作一个快照snapshot(快照只是登记留名,快照不等于记录在案管快照叫做索引index)。快照一般会暂时存储在一个临时 存储区域中。
当开始一个新的项目时:
git init :用于初始化当前所在目录的这个项目(Testjava),shell返回的提示表明已经建立了一个.git隐藏目录来保存这个项目目前的进展信息
git commit:用于将快照里登记的内容永久写入git仓库中,也就是开发者已经想好了要提交自己的开发成果了。“”里面的内容可以自己来写作为提交的备注
git remote add [仓库名][url] :添加远程仓库
git push [仓库名]-u master:
git pull :完成了两个动作,首先从远端分支获取diff信息,第二个动作就是将改变合并到本地分支中.pull命令的意思是从远端git仓库中取出(git-fetch)修改的代码,然后合并(git-merge)到我(rocrocket)的项目中去。读者要记住一个小技巧,那就是“git pull .”命令,它和git merge的功能是一样的,以后完全可以用
git pull .来代替git merge哦!请注意,git-pull命令有可能会因为/home/bob的目录权限问题而被拒绝,解决方法是chmod o+rx/home/bob。
想检查到目前为止对源码都做了哪些修改(相对于本次工作刚开始之时):
git diff :查看文件改动前后发生了哪些变化,只在git add之前使用有效。如果已经add了,那么此命令输出为空。
git status :在git commit之前有效,表示都有哪些文件发生了改动。
git log:查看自项目开启到现在的所有开发日志
git log -p:会输出非常详细的日志内容,包括了每次都做了哪些源码的修改
开启一个试验分支(experimental),如果分支开发成功则合并到主分支(master),否则放弃该试验分支。
git branch experimental :创建一个试验分支,名称叫experimental
git branch :显示当前都有哪些分支,其中标注*为当前所在分支
git checkout experimental :转移到experimental分支(省略数小时在此分支上的开发过程)…
如果分支开发成功:
git commit -a :在experimental分支改进完代码之后用commit在此分支中进行提交.
git checkout master :转移回master分支
git merge experimental:经证实分支开发成功,将exerimental分支合并到主分支
git commit -a :彻底完成此次分支合并,即提交master分支
git branch -d experimental :因为experimental分支已提交,所以可安全删除此分支
如果分支开发失败:
git checkout master
git branch -D experimental :由于分支被证明失败,因此使用-D来放弃并删除该分支
随时查看图形化分支信息。
gitk
当bob希望改进你的(rocrocket)的工作成果,则:
cd /home/rocrocket/project
git clone /home/rocrocket/project myrepo :此命令用于克隆我的工作到bob的myrepo目录下。请注意,此命令有可能会因为/home/rocrocket的目录权限问题而被 拒绝,解决方法是chmod o+rx /home/rocrocket。(省略bob数小时的开发过程)$git commit -a //bob提交自己的改进成果到自己的git仓库中,并口头告知我(rocrocket)他已经完成了工作。
或者
cd /home/rocrocket/project:回到仓库工程下
git fetch /home/bob/myrepo master:bobworks :此命令意思是提取出bob修改的代码内容,然后放到我(rocrocket)工作
目录下的bobworks分支中。之所以要放到分支中,而不是master中,就是要我先仔仔细细看看bob的开发成果,如果我觉得满意,我再merge到master中,如果不满意,我完全可以直接git branch -D掉。
git whatchanged -p master..bobworks :用来查看bob都做了什么
git checkout master :切换到master分区
git pull . bobworks :如果我检查了bob的工作后很满意,就可以用pull来将bobworks分支合并到我的项目中了
git branch -D bobworks :如果我检查了bob的工作后很不满意,就可以用-D来放弃这个分支就可以了
注意:获得帮助可以使用类似man git-****的命令格式:
想获得关于commit命令的帮助,则man git-commit
想获得关于pull命令的帮助,则man git-pull
想获得关于merge命令的帮助,则man git-merge
5.了解git是怎样工作的?
1.直接记录快照,而非差异比较
Git 和其他版本控制系统的主要差别在于,Git 只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异。这类系统(CVS,Subversion,Perforce,Bazaar 等等)每次记录有哪些文件作了更新,以及都更新了哪些行的什么内容:
![](http://www.nowamagic.net/librarys/images/201401/2014_01_06_01.png)
Git 并不保存这些前后变化的差异数据。实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一链接。Git 的工作方式就如下图所示。
![](http://www.nowamagic.net/librarys/images/201401/2014_01_06_02.png)
这是 Git 同其他系统的重要区别。它完全颠覆了传统版本控制的套路,并对各个环节的实现方式作了新的设计。Git 更像是个小型的文件系统,但它同时还提供了许多以此为基础的超强工具,而不只是一个简单的 VCS。稍后会讨论 Git 分支管理的时候,我们会再看看这样的设计究竟会带来哪些好处。
2.近乎所有操作都是本地执行
在 Git 中的绝大多数操作都只需要访问本地文件和资源,不用连网。但如果用 CVCS 的话,差不多所有操作都需要连接网络。因为 Git 在本地磁盘上就保存着所有当前项目的历史更新,所以处理起来速度飞快。
举个例子,如果要浏览项目的历史更新摘要,Git 不用跑到外面的服务器上去取数据回来,而直接从本地数据库读取后展示给你看。所以任何时候你都可以马上翻阅,无需等待。如果想要看当前版本的文件和一个月前的版本之间有何差异,Git 会取出一个月前的快照和当前文件作一次差异运算,而不用请求远程服务器来做这件事,或是把老版本的文件拉到本地来作比较。
用 CVCS 的话,没有网络或者断开 VPN 你就无法做任何事情。但用 Git 的话,就算你在飞机或者火车上,都可以非常愉快地频繁提交更新,等到了有网络的时候再上传到远程仓库。同样,在回家的路上,不用连接 VPN 你也可以继续工作。换作其他版本控制系统,这么做几乎不可能,抑或非常麻烦。比如 Perforce,如果不连到服务器,几乎什么都做不了(默认无法发出命令 p4 edit file 开始编辑文件,因为 Perforce 需要联网通知系统声明该文件正在被谁修订。但实际上手工修改文件权限可以绕过这个限制,只是完成后还是无法提交更新。);如果是 Subversion 或 CVS,虽然可以编辑文件,但无法提交更新,因为数据库在网络上。看上去好像这些都不是什么大问题,但实际体验过之后,你就会惊喜地发现,这其实是会带来很大不同的。
3.时刻保持数据完整性
在保存到 Git 之前,所有数据都要进行内容的校验和(checksum)计算,并将此结果作为数据的唯一标识和索引。换句话说,不可能在你修改了文件或目录之后,Git 一无所知。这项特性作为 Git 的设计哲学,建在整体架构的最底层。所以如果文件在传输时变得不完整,或者磁盘损坏导致文件数据缺失,Git 都能立即察觉。
Git 使用 SHA-1 算法计算数据的校验和,通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值,作为指纹字符串。该字串由 40 个十六进制字符(0-9 及 a-f)组成,看起来就像是:
1 | 24b9da6552252987aa493b52f8696cd6d3b00373 |
Git 的工作完全依赖于这类指纹字串,所以你会经常看到这样的哈希值。实际上,所有保存在 Git 数据库中的东西都是用此哈希值来作索引的,而不是靠文件名。
4.多数操作仅添加数据
常用的 Git 操作大多仅仅是把数据添加到数据库。因为任何一种不可逆的操作,比如删除数据,都会使回退或重现历史版本变得困难重重。在别的 VCS 中,若还未提交更新,就有可能丢失或者混淆一些修改的内容,但在 Git 里,一旦提交快照之后就完全不用担心丢失数据,特别是养成定期推送到其他仓库的习惯的话。
这种高可靠性令我们的开发工作安心不少,尽管去做各种试验性的尝试好了,再怎样也不会弄丢数据。至于 Git 内部究竟是如何保存和恢复数据的,我们会在后面讨论 Git 内部原理时再作详述。
5.文件的三种状态
好,现在请注意,接下来要讲的概念非常重要。对于任何一个文件,在 Git 内都只有三种状态:已提交(committed),已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本地数据库中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存的清单中。
由此我们看到 Git 管理项目时,文件流转的三个工作区域:Git 的工作目录,暂存区域,以及本地仓库。
![](http://www.nowamagic.net/librarys/images/201401/2014_01_06_03.png)
每个项目都有一个 Git 目录(如果 git clone 出来的话,就是其中 .git 的目录;如果 git clone --bare 的话,新建的目录本身就是 Git 目录。),它是 Git 用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。
从项目中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录。这些文件实际上都是从 Git 目录中的压缩对象数据库中提取出来的,接下来就可以在工作目录中对这些文件进行编辑。
所谓的暂存区域只不过是个简单的文件,一般都放在 Git 目录中。有时候人们会把这个文件叫做索引文件,不过标准说法还是叫暂存区域。
基本的 Git 工作流程如下:
- 在工作目录中修改某些文件。
- 对修改后的文件进行快照,然后保存到暂存区域。
- 提交更新,将保存在暂存区域的文件快照永久转储到 Git 目录中。
所以,我们可以从文件所处的位置来判断状态:如果是 Git 目录中保存着的特定版本文件,就属于已提交状态;如果作了修改并已放入暂存区域,就属于已暂存状态;如果自上次取出后,作了修改但还没有放到暂存区域,就是已修改状态。