学习一下git(四)



之前有关git的学习都是基于本地,除了版本的管理和控制外,和别人的协作一般还是需要远程服务器。你可以自己架设服务器,也可以用git托管服务,比如github,其他的可以参见git官方wiki上的托管服务列表

可以从git clone 开始,

$ git clone https://github.com/xbin999/gittest.git
</pre> git clone除了建立自己的本地分支master和远程分支origin/master外,并且会将他们都指向orgin上的master分支,这自动就是一个跟踪分支(从远程分支checkout出来)。 <pre>
$ git remote -v
origin https://github.com/xbin999/gittest.git (fetch)
origin https://github.com/xbin999/gittest.git (push)

git remote add 可以添加远程仓库地址,指定别名。 git remote show 显示远程仓库信息。
git fetch 从远程仓库抓取信息。注意fetch出来只是更新remote索引。要在本地编辑需要merge到本地分支中或者checkout出一个新的分支。 git push 推送数据到远程仓库。

而和远程服务器最简单的协作方式之一:先在自己的特性分支中工作一段时间,完成后合并到自己的 master 分支;然后下载合并 origin/master 上的更新(如果有的话),再推回远程服务器。一般的协作流程如图所示:



对于自己拥有的项目,可以用git push推送。但如果要给公开项目作贡献,往往你并没有直接更新主仓库分支的权限,需要把工作成果交给项目维护人。

一种方式使用 git 托管服务商提供的仓库复制功能,一般称作 fork,比如GitHub 都支持这样的操作,而且许多项目管理员都希望大家使用这样的方式。 另一种方式是通过电子邮件寄送文件补丁。

学习一下git(三)



任何的版本管理控制系统都会有分支的管理,不过git的分支管理要简单地多,确实比较牛。这源于前面所说的设计,版本间的差异保存的不是文件差异或者变化量,而是一系列文件的快照。

看一个例子,git仓库中三个文件,git add加入暂存区域后,会把当前版本的文件快照保存到git仓库中,并将校验和(也就是SHA-1哈希串)加入暂存区域;git commit提交时,会计算每个目录的校验和,作为树(tree)对象保存,结果如图(这几个图真是太棒了,想不夸都不行):



每一次修改后,再提交,就有不同的commit对象指向不同的快照。



而对于git的分支,本质就是个指向commit对象的指针,默认是master分支,每次提交后移动master即可。



使用git branch testing创建一个新的分支testing,这时新分支也是一个指针,指向同一快照。至于你工作在哪个分支,则有HEAD的特别指针来标识。



可以使用git checkout testing来切换到新建分支。



有了分支后,你可以在不同的分支上分别进行版本的演进。而gi很t有意思的是可以很在同一个目录中,不同分支间进行随意地切换,切换到新的分支后,目录中的文件就都会自动更新到新版本,不象其他版本工具,你可能需要多个目录分别保存不同的版本。git的版本切换开销非常之低,可以几毫秒完成分支的创建和切换。所以Git鼓励开发者频繁使用分支。

在分支的使用中,除了branch,checkout创建和切换分支外,另外需要的就是分支代码的合并。

合并分支有两种方法:

一是采用merge,如果遇到冲突,需要手工修改冲突的文件,再运行git add把它标记为已解决状态。

二是采用rebase,参见示例,rebase是把分支experiment的C3版本在master分支上C4版本上重新打一遍,rebase比merge看起来主干线会更清晰,本质是把合并的工作责任交给主干线的提交了。



需要遵守一条准则:“一旦分支中的提交对象发布到公共仓库,就不要对该分支进行rebase操作。”

看来rebase还是少用为妙。以上的分支操作并不设计远程,下次整理一下有关远程仓库的操作和分支的管理。

学习一下git(二)



两种途径开始git,一是init初始化新仓库,再添加文件;二是从现有仓库clone。

git init git clone> 为什么是clone,而不是checkout,就是因为git和其他VCS不同的是git收取项目历史所有的数据,而不仅仅是某一个版本。

在有了git仓库后,常用的操作就是add, commit, log, status, diff, rm, mv,而这些操作还是需要理解三个区域,以及在区域间文件的状态变化周期。

文件的状态变化周期

git diff 比较工作目录中当前文件和暂存区域快照之间的差异。 git diff –cached 比较暂存区域和上次提交的快照之间的差异。
git diff –staged 同上。git diff采用合并格式diff的变体,带上下文,有关diff的格式详细参考阮一峰的读懂diff。> diff –git a/yun.txt b/yun.txt
>
> index de629e5..67ca091 100755
>
> — a/yun.txt
>
> +++ b/yun.txt
>
> @@ -13,3 +13,4 @@ pc-jfjwapp11 10.70.217.70
>
> pc-jfjwapp12 10.70.217.71
>
> $ test
>
> second line
>
> +add 8-21
>
> 1. 第一行,a版本是变动前的,b版本是变动后的。
> 2. 第二行,de629e5是a版本的哈希值,67ca091是b版本的哈希值,755表示文件权限。
> 3. 第三、四行表示比较的两个文件,—是a版本,+++是b版本。
> 4. 第五行@@和@@之间是两个文件的变化,-13,3 是a版本的第13行开始,一共3行,+13,4是表示b版本的第13行开始,一共4行。
> 5. 之后是变化的文件内容,带有+号的是表示b版本内容,带有-号的是表示a版本的内容。
git commit git commit -a 跳过使用暂存区域,也就是不要git add了。 git rm 移除文件
git rm –cached 从暂存区域移除,当前工作目录保留,比如编译中间文件。 git log -p -2 其中-p选项展开显示每次提交的内容差异,-2则仅显示最近的两次更新。
* gitk 是随git一同发布,基于Tcl/Tk的,git log的图形化工具。

如果和常规的版本控制管理系统相比较,多人协同开发,还是需要一个代码托管的地方。github 就提供了免费软件项目git仓库托管服务,国内也有gitcafe。所以完整的git使用还涉及和托管服务之间的交互,和远程仓库的协作下次继续。

学习一下git(一)



看ruby和写代码的时候,很难离得开git )和github,所以让自己也系统地看一下。

git )是一个分布式的版本控制和源代码管理系统,最开始是由Linus Torvalds为linux内核开发而设计实现的。

传统的版本控制管理,象CVS,SVN一般都会有一个中心服务器,本地check out代码,然后修改,提交合并代码,但这样的问题是依赖于中心服务器。而对于分布式版本控制系统则在本地都有完整的代码仓库,任何一台服务器发生故障,都可以使用镜像的本地仓库恢复。

git很大的一个特点是对于文件保存完整的数据,而非文件的增量差异,在不同版本时对于没有变化的文件不再保存,而仅做一个链接。

Git保存更新时的文件快照

由于其分布式的特点,每台机器上都是一个仓库,所以基本上操作都在本地,包括往库里提交修改、版本差异比较、查看更新日志等等。

对于git来说,任何一个文件流转过程中都存在三种状态:

已提交(committed),表明文件已经提交到本地仓库中。 已修改(modified),表明文件已经修改,但未提交。
已暂存(staged),表明已修改的文件放在下次提交时要保存的清单中。

所以对于本地工作时,git有三个工作区域:git的工作目录,git本地仓库和暂存区域,一般在工作目录中会有一个.git目录,其中就保存了元数据和对象数据库,而暂存区域文件(index索引文件)也放在.git目录中。对于理解暂存区的作用,worldhello上有一篇很好的文章和一个图,引用一下:
git work area

如果我修改一个文件,增加一行”in stage”,然后使用git add 保存到暂存区,之后再增加一行”in work directory”,git status查看状态:

➜ /Users/yangbin/tmp/gittest git:(master) >git status -s
➜ /Users/yangbin/tmp/gittest git:(master) >git add yun.txt
➜ /Users/yangbin/tmp/gittest git:(master) ✗ >echo “in stage” >> yun.txt
➜ /Users/yangbin/tmp/gittest git:(master) ✗ >git status -s
M yun.txt
➜ /Users/yangbin/tmp/gittest git:(master) ✗ >echo “in work directory” >> yun.txt
➜ /Users/yangbin/tmp/gittest git:(master) ✗ >git status -s
MM yun.txt

此时工作区、暂存区和本地仓库yun.txt文件的内容各不相同,可以使用:
git commit yun.txt 提交暂存区的内容到本地仓库,也就是增加“in stage”;
git rm – cached yun.txt 直接从暂存区删除内容,工作区不变; git checkout . yun.txt 使用暂存区文件更新工作区文件;
* git chekcout HEAD yun.txt 使用本地仓库文件更新工作区和暂存区文件。

当然我们要使用git一般都是从git init 和git clone开始的,这个下次再说。