== 克隆周边 ==

在较老一代的版本控制系统里，checkout是获取文件的标准操作。你将获得一组特定保
存状态的文件。

在Git和其他分布式版本控制系统里，克隆是标准的操作。通过创建整个仓库的克隆来
获得文件。或者说，你实际上把整个中心服务器做了个镜像。凡是主仓库上能做的事，
你都能做。

=== 计算机间同步 ===

我可以忍受制作tar包或利用rsync来作备份和基本同步。但我有时在我笔记本上编辑，
其他时间在台式机上，而且这俩之间也许并不交互。

在一个机器上初始化一个Git仓库并提交你的文件。然后转到另一台机器上：

 $ git clone other.computer:/path/to/files

以创建这些文件和Git仓库的第二个拷贝。从现在开始，

 $ git commit -a
 $ git pull other.computer:/path/to/files HEAD

将把另一台机器上特定状态的文件“拉”到你正工作的机器上。如果你最近对同一个文
件做了有冲突的修改，Git将通知你，而你也应该在解决冲突之后再次提交。

=== 典型源码控制 ===

为你的文件初始化Git仓库：

 $ git init
 $ git add .
 $ git commit -m "Initial commit"

在中心服务器，在某个目录初始化一个“裸仓库”：

 $ mkdir proj.git
 $ cd proj.git
 $ git init --bare
 $ touch proj.git/git-daemon-export-ok

如需要的话，启动Git守护进程：

 $ git daemon --detach  # 它也许已经在运行了

对一些Git伺服服务，按照其指导来初始化空Git仓库。一般是在网页上填一个表单。

把你的项目“推”到中心服务器：
 $ git push central.server/path/to/proj.git HEAD

捡出源码，可以键入：

 $ git clone central.server/path/to/proj.git

做了改动之后，开发保存变更到本地：

 $ git commit -a

更新到最近版本：

 $ git pull

所有冲突应被处理，然后提交：

 $ git commit -a

把本地改动捡入到中心仓库：

 $ git push

如果主服务器由于其他开发的活动，有了新的变更，这个捡入会失败，该开发应该把最
新版本拿下来，解决合并冲突，然后重试。

为使用上面pull和push命令，开发必须有SSH访问权限。不过，通过键入以下命令，任何
人都可以看到源码：

 $ git clone git://central.server/path/to/proj.git

本地git协议和HTTP类似：并无安全验证，因此任何人都能拿到项目。因此，默认情况
git协议禁止推操作。

=== 封闭源码 ===

闭源项目不要执行touch命令，并确保你从未创建`git-daemon-export-ok`文件。资源库
不再可以通过git协议获取；只有那些有SSH访问权限的人才能看到。如果你所有的资源
库都是封闭的，那也没必要运行运行git守护了，因为所有沟通都走SSH。

=== 裸仓库 ===

之所以叫裸仓库是因为其没有工作目录；它只包含正常情况下隐藏在`.git`子目录下
的文件。换句话说，它维护项目历史，而且从不保存任何给定版本的快照。

裸仓库扮演的角色和中心版本控制系统中中心服务器的角色类似：你项目的中心。开
发从其中克隆项目，捡入新近改动。典型地裸仓库存在一个服务器上，该服务器除了
分散数据外并不做啥。开发活动发生在克隆上，因此中心仓库没有工作目录也行。


很多Git命令在裸仓库上失败，除非指定仓库路径到环境变量`GIT_DIR`，或者指定
`--bare`选项。

=== 推还是拽 ===

为什么我们介绍了push命令，而不是依赖熟悉的pull命令？首先，在裸仓库上pull会
失败：除非你必须“fetch”，一个之后我们要讨论的命令。但即使我们在中心服务器上
保持一个正常的仓库，拽些东西进去仍然很繁琐。我们不得不登陆服务器先，给pull
命令我们要拽自机器的网络地址。防火墙会阻碍，并且首先如果我们没有到服务器的
shell访问怎么办呢？

然而，除了这个案例，我们反对推进仓库，因为当目标有工作目录时，困惑随之而来。

简短截说，学习Git的时候，只在目标是裸仓库的时候push，否则用pull的方式。

=== 项目分叉 ===

项目走歪了吗？或者认为你可以做得更好？那么在服务器上：

 $ git clone git://main.server/path/to/files

之后告诉每个相关的人你服务器上项目的分支。

在之后的时间，你可以合并来自原先项目的改变，使用命令：

 $ git pull

=== 终极备份 ===

会有很多散布在各处，禁止篡改的冗余存档吗? 如果你的项目有很多开发，那干脆啥也
别做了。你的每份代码克隆是一个有效备份。不仅当前状态，还包括你项目整个历史。
感谢哈希加密算法，如果任何人的克隆被损坏，只要他们与其他的交互，这个克隆就会
被修好。

如果你的项目并不是那么流行，那就找尽可能多的伺服来放克隆吧。

真正的偏执狂应该总是把HEAD最近20字节的SHA1哈希值写到安全的地方。应该保证安全，
而不是把它藏起来。比如，把它发布到报纸上就不错，因为对攻击者而言，更改每份报
纸是很难的。

=== 轻快多任务 ===

比如你想并行开发多个功能。那么提交你的项目并运行：

 $ git clone . /some/new/directory

Git使用硬链接和文件共享来尽可能安全地创建克隆，因此它一眨眼就完成了，因此你现
在可以并行操作两个没有相互依赖的功能。例如，你可以编辑一个克隆，同时编译另一
个。感谢 http://en.wikipedia.org/wiki/Hard_link[hardlinking], 本地克隆比简单
备份省时省地。

现在你可以同时工作在两个彼此独立的特性上。比如，你可以在编译一个克隆的时候编
辑另一个克隆。任何时候，你都可以从其它克隆提交并拖拽变更。

 $ git pull /the/other/clone HEAD

=== 游击版本控制 ===

你正做一个使用其他版本控制系统的项目， 而你非常思念Git？ 那么在你的工作目录初
始化一个Git仓库：

 $ git init
 $ git add .
 $ git commit -m "Initial commit"

然后克隆它：

 $ git clone . /some/new/directory

并在这个目录工作，按你所想在使用Git。过一会，一旦你想和其他每个人同步，在这种
情况下，转到原来的目录，用其他的版本控制工具同步，并键入：

 $ git add .
 $ git commit -m "Sync with everyone else"

现在转到新目录运行：

 $ git commit -a -m "Description of my changes"
 $ git pull

把你的变更提交给他人的过程依赖于其他版本控制系统。这个新目录包含你的改动的文
件。需要运行其他版本控制系统的命令来上载这些变更到中心仓库。

Subversion, 或许是最好的中心式版本控制系统，为无数项目所用。 *git svn* 命令为
Subversion仓库自动化了上面的操作，并且也可以用作
http://google-opensource.blogspot.com/2008/05/export-git-project-to-google-code.html[
导出Git项目到Subversion仓库] 的替代。

=== Mercurial ===

Mercurial是一个类似的的版本控制系统，几乎可以和Git一起无缝工作。使用
`hg-git`插件，一个Mercurial用户可以无损地往Git仓库推送，从Git仓库拖拽。

使用Git获得`hg-git`插件：

 $ git clone git://github.com/schacon/hg-git.git

或使用Mercurial:

 $ hg clone http://bitbucket.org/durin42/hg-git/

不好意思，我没注意Git有类似的插件。因此, 我主张使用Git而不是Mercurial作为主资
源库，即使你偏爱Mercurial。使用Mercurial项目，通常一个自愿者维护一个平行的
Git项目以适应Git用户，然而感谢`hg-git`插件，一个Git项目自动地适应Mercurial用
户。

尽管该插件可以把一个Mercurial仓库转成一个Git仓库，通过推到一个空的仓库，
这个差事交给`hg-fast-export.sh`脚本还是更容易些。来自：

 $ git clone git://repo.or.cz/fast-export.git

要转化，只需在一个空目录运行：

 $ git init
 $ hg-fast-export.sh -r /hg/repo

注意该脚本应加入你的`$PATH`。

=== Bazaar ===

我们简略提一下Bazaar，它毕竟是紧跟Git和Mercurial之后最流行的自由分布式版本控
制系统。

Bazaar有后来者的优势，它相对年轻些；它的设计者可以从前人的错误中学习，并且躲
过去翻历史上犯过的错误。另外，它的开发人员对可移植性以及和与其它版本控制系统
的互操作性也考虑周全。

一个`bzr-git`插件让Bazaar用户在一定程度下可以工作在Git仓库。`tailor`程序转
换Bazaar仓库到Git仓库，并且可以递增的方式做，要知道`bzr-fast-export`只是
在一次性转换性情况下工作良好。

=== 我偏爱Git的原因 ===

我起先选择Git是因为我听说它能管理不可想象地不可管理的Linux内核源码。我从来没
觉得有离开的必要。Git已经服侍的很好了，并且我也没有被其瑕疵所困扰。因为我主要
使用Linux，其他平台上的问题与我无关。

还有，我偏爱C程序和bash脚本，以及诸如Python的可执行可脚本：较少依赖，并且我也
沉迷于快速的执行时间。

我考虑过Git才能如何提高，甚至自己写类似的工具，但只作为研究练练手。即使完成这
个项目，我也无论如何会继续使用Git，因为使用一个古里古怪的系统所获甚微。

自然地，你的需求和期望可能不同，并且你可能使用另一个系统会好些。尽管如此，使
用Git你都错不太远。
