版本控制-GIT

Table of Contents

仓库概念

纯仓库和工作仓库

一个Git代码仓库(repository)可以是一个纯仓库(Bare repository)或者是一个开发者仓库(Development repository,  nonbare)。
开发者仓库可以用于普通的日常开发,反之,一个纯仓库没有工作目录并且不能用于日常开发。一个纯仓库没有核实(checked-out)分支(branch)的概念,或者说,你不能直接对一个纯仓库进行提交。

一个纯仓库看起来功能很少,但是它极好的为合作开发者充当为可信的基础。其他的开发者从纯仓库clone、etch并且向它push更新。

如果你执行git clone带了–bare参数,Git则创建一个纯仓库,否则,则建立一个开发者仓库。

仓库克隆

git clone命令可以基于你指定的源仓库建立一个新的Git仓库。Git不会复制所有有关源仓库的所有信息。

在通常使用git clone后,源仓库存于refs/heads/的开发者的分支,被clone到refs/remotes/下成为远程跟踪分支。源仓库在refs/remotes/下的远程跟踪分支不会被clone。

来自于源仓库的标签(Tags)也会被拷贝。然而仓库特殊的信息,比如钩子(hook)、配置文件、参考日志和源仓库隐藏的不会被复制。

这里,git@compile.3322.org:testing.git被认为是源仓库、远程仓库(remote repository),新的,clone结果是testing.git。
默认每个clone的仓库通过一个叫做origin的远程分支维护到它的父仓库的链接。名字”origin”不是在任何情况下必须的。如果你不像使用它,在做clone操作的时候加一个–origin name的选项即可。

Git同时对默认的origin远程仓库配置了默认的fetch refspec:

建立这个refspec预测你会想通过从源仓库获得修改来更新你的本地仓库。

远程仓库(Remotes)

你当前工作的仓库被称为本地(local)或当前(current)仓库,同时,你想要交互文件的仓库被称为远程仓库。但是后面的术语有点使用不当,因为仓库可能不在物理上的远程或者另外一台机器,它可以是一个本地文件系统上的其他的一个仓库。

Git同时使用远程仓库和跟踪(tracking)分支作为方便连接其他仓库的参考引用。remote为仓库提供了一个友好的名字并用来代替实际的仓库URL。一个远程仓库对于本地仓库组成了跟踪分支的一部分。

使用git remote命令可以创建、启动、操做和查看一个远程仓库。所有引入的远程仓库都被记录在.git/config文件并可以使用git config操作。

除了git clone,其他和远程仓库常用的Git命令是:

跟踪分支

一旦clone一个仓库,即使你产生本地提交(commit)或者创建本地分支,你也可以跟上(keep up with)源仓库的修正。实际上,你可以建立一个名为testd的本地分支而不需要确认有开发者在上工作,或者源仓库也可以创建一个test分支。通过跟踪分支,Git允许在2个test分支跟踪发展。

在一个clone操作后,Git对源仓库的每个当前分支在本地仓库建立远程跟踪分支。本地仓库使用它的跟踪分支追随发生在源仓库的变化。

参考其他仓库

为了使你的仓库和其他仓库同步工作,你需要定义一个remote。一个remote是存在仓库配置文件中的一个命名节点。它包含2部分。第一部分以URL的方式确定了另一个仓库的名字。第二部分,称为refspec,定义了一个ref(通常是一个分支)如何从一个仓库的命名空间映射到另一个仓库的命名空间。

参考到远程仓库

Git支持多种形式的URL方式命名远程仓库。这些形式指明了访问协议和数据的地址。

最简单的Git URL形式指向一个本地文件系统中的仓库。有2种方式:

如果你需要通过网络从一个真实的远程仓库获得数据,最有效的方法被称为Git本地协议(Git native protocol),例如

git-daemon通过这种方式发布仓库提供匿名读取。你可以使用这种URL方式clone或者fetch。

使用这种方式的客户端是无认证的,不需要密码。而且,~user格式被指向到用户主目录。一个单独的~没有任何意义。此外,~user方式只在服务器端使用–user-path参数使能访问。

为了安全,经过认证连接,Git本地协议可以被转成一个使用以下形式的SSH连接:

Git也提供了类似scp语法的URL格式。它和SSH格式一样,但是不能指定端口参数:

HTTP和HTTPS URL变体也完全支持,尽管任何一个都没有Git本地协议有效率。

最后,rsync协议同样支持:

参考说明(refspec)

通常一个ref是一个分支的名字。一个refspec将远程仓库的分支映射到你的本地仓库的分支。

在一个refspec,你通常看到开发者分支的名字有refs/heads/前缀并且被跟踪的分支名字有refs/remotes/前缀。

refspec的语法是:

它主要由一个源ref,一个冒号和一个目的ref组成。完整格式可以有一个可选的加号。加号指在传输中普通的fast-forward安全检查不会被执行。此外,一个星号是匹配所有分支名字的通配符。

有时,源ref是可选的,冒号和目的ref也是可选的。

使用refspec的技巧是理解它所指定的数据流向。refspec通常为source:destination。但是源和目的的角色取决于执行的Git操作。关系如下:

一个典型的git fetch命令使用如下的refspec:

这个refspec解释如下:

所有来自远程仓库的在refs/heads/命名空间的原分支映射到你的本地仓库。远程名字放入refs/remotes/remote命名空间。

因为有星号,这个refspec应用在远程的refs/heads/*找到的所有分支。

refspec可以被git fetchgit push使用。因为git pull的第一步是fetch,fetch refspec等同与git pull

通过git push操作,你想提供和发布在你的本地仓库上作出的修改。为了在你上传之后允许其他人找到你的修改,你的修改必须作为主分支出现在仓库。因此,通过git push操作,来自你的仓库的源分支通过使用如下refspec送到远程仓库:

这个refspec解释如下:

从本地仓库,找到原命名空间refs/heads/下找到的所有分支,放入到远程仓库的目的命名空间refs/heads/下的有相同名字的匹配的分支。

第一个refs/heads/指的是你的本地仓库(因为你在做push操作),第二个指的是远程仓库。星号保证所有的分支被复制。

使用远程仓库例子

参考资料

  • Reilly.Version.Control.with.Git.2009.pdf

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.