1
0
Fork 0

zh version

This commit is contained in:
Scott Chacon 2011-04-07 16:46:35 -04:00
parent 4d9f6ed2cf
commit 4e6a83d28d
11 changed files with 2218 additions and 0 deletions

106
_layouts/zh_reference.html Executable file
View File

@ -0,0 +1,106 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Git 参考手册</title>
<link rel="stylesheet" type="text/css" href="/zh//css/reset.css" media="screen" />
<link rel="stylesheet" type="text/css" href="/zh//css/text.css" media="screen" />
<link rel="stylesheet" type="text/css" href="/zh//css/grid.css" media="screen" />
<link rel="stylesheet" type="text/css" href="/zh//css/layout.css" media="screen" />
<link rel="stylesheet" type="text/css" href="/zh//css/nav.css" media="screen" />
<!--[if IE 6]><link rel="stylesheet" type="text/css" href="/zh//css/ie6.css" media="screen" /><![endif]-->
<!--[if IE 7]><link rel="stylesheet" type="text/css" href="/zh//css/ie.css" media="screen" /><![endif]-->
<script type="text/javascript" src="/js/jquery-1.4.1.min.js"></script>
<script type="text/javascript" src="/js/jquery-ui.min.js"></script>
<script type="text/javascript" src="/js/action.js"></script>
</head>
<body>
<div class="container_12">
<div class="grid_12">
<span id="branding">Git 参考手册</span>
</div>
<div class="grid_12">
<ul id="menu">
<li><a id="menu_home" href="/zh/index.html">参考手册</a></li>
<!-- <li><a id="menu_cookbook" href="/zh//cookbook.html">Cookbook</a></li> -->
<li><a id="menu_about" href="/zh/about.html">关于</a></li>
<li>&#167;</li>
<li><a href="/zh/http://github.com/dotnil/git-reference">网站源码</a></li>
</ul>
<br/>
&nbsp;
</div>
<div class="grid_2" id="reflist">
<div class="block">
<h3><a href="/zh/creating">获取与创建项目</a></h3>
<ul>
<li><a href="/zh/creating/#init">init</a></li>
<li><a href="/zh/creating/#clone">clone</a></li>
</ul>
</div>
<div class="block">
<h3><a href="/zh/basic">基本的快照</a></h3>
<ul>
<li><a href="/zh/basic/#add">add</a></li>
<li><a href="/zh/basic/#status">status</a></li>
<li><a href="/zh/basic/#diff">diff</a></li>
<li><a href="/zh/basic/#commit">commit</a></li>
<li><a href="/zh/basic/#reset">reset</a></li>
<li><a href="/zh/basic/#rm-mv">rm, mv</a></li>
</ul>
</div>
<div class="block">
<h3><a href="/zh/branching">分支与合并</a></h3>
<ul>
<li><a href="/zh/branching/#branch">branch</a></li>
<li><a href="/zh/branching/#branch">checkout</a></li>
<li><a href="/zh/branching/#merge">merge</a></li>
<li><a href="/zh/branching/#log">log</a></li>
<li><a href="/zh/branching/#tag">tag</a></li>
</ul>
</div>
<div class="block">
<h3><a href="/zh/remotes">分享与更新项目</a></h3>
<ul>
<li><a href="/zh/remotes/#fetch">fetch, pull</a></li>
<li><a href="/zh/remotes/#push">push</a></li>
<li><a href="/zh/remotes/#remote">remote</a></li>
</ul>
</div>
<div class="block">
<h3><a href="/zh/inspect">检查与比较</a></h3>
<ul>
<li><a href="/zh/inspect/#log">log</a></li>
<li><a href="/zh/inspect/#diff">diff</a></li>
</ul>
</div>
<!--
<div class="block">
<h3><a href="/zh//fixing">Fixing and Changing History</a></h3>
<ul>
<li><a href="/zh//fixing/rebase.html">rebase</a></li>
<li><a href="/zh//fixing/revert.html">revert</a></li>
<li><a href="/zh//fixing/checkout.html">checkout</a></li>
<li><a href="/zh//fixing/reset.html">reset</a></li>
<li><a href="/zh//fixing/cherry-pick.html">cherry-pick</a></li>
</ul>
</div>
-->
</div>
<div class="grid_10 home_box" id="content_box">
{{ content }}
</div>
<div class="clear"></div>
</div>
</body>
</html>

2
zh/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
_site
*~

8
zh/about.html Normal file
View File

@ -0,0 +1,8 @@
---
layout: zh_reference
---
<div class="box">
<h2>谁的作品?</h2>
<br/>
<p>Git 参考手册是 Github 项目组的成果。<a href="http://cyj.me">逸才</a><a href="http://gitref.org">Git Reference</a> 的基础上做了中文翻译。</p>
</div>

586
zh/basic/index.html Normal file
View File

@ -0,0 +1,586 @@
---
layout: zh_reference
---
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://progit.org/book/ch2-2.html"></a>
</span>
基本的快照
</h2>
<div class="block">
<p>
Git 的所有工作就是创建与保存您的项目的快照以及之后的快照对比等工作。本章将对有关创建与提交您的项目的快照的命令作介绍。
</p>
<p>
这里有个重要的概念Git 有一个叫做“索引”的东东,有点像是您的快照的缓存区。这就使您能够从更改的文件中创建出一系列组织良好的快照,而不是一次提交所有的更改。
</p>
<p class="nutshell">
<strong>一言以蔽之</strong>,使用 <code>git add</code> 添加需要追踪的新文件和待提交的更改,然后使用 <code>git status</code><code>git diff</code> 查看有何改动,最后用 <code>git commit</code> 将您的快照记录。这就是您要用的基本流程,绝大部分时候都是这样的。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-add.html">文档</a> &nbsp;
<a target="new" href="http://progit.org/book/ch2-2.html#tracking_new_files"></a>
</span>
<a name="add">git add</a>
<span class="desc">添加文件到缓存</span>
</h2>
<div class="block">
<p>
在 Git 中,在提交您修改的文件之前,您需要把它们添加到缓存。如果该文件是新的,您可以执行 <code>git add</code> 将该文件添加到缓存,但是,即使该文件已经被追踪了 —— 也就是说,曾经提交过了 —— 你仍然需要执行 <cpde>git add</code> 将新更改的文件添加到缓存去。让我们看几个例子:
</p>
<p>回到我们的 Hello World 示例,初始化该项目之后,我们就要用 <code>git add</code> 将我们的文件添加进去了。我们可以用 <code>git status</code> 看看我们的项目的当前状态。
</p>
<pre>
<b>$ git status -s</b>
<span class="red">??</span> README
<span class="red">??</span> hello.rb
</pre>
我们有俩尚未被追踪的文件,得添加一下。
<pre>
<b>$ git add README hello.rb</b>
</pre>
现在我们再执行 <code>git status</code>,就可以看到这俩文件已经加上去了。
<pre>
<b>$ git status -s</b>
<span class="green">A</span> README
<span class="green">A</span> hello.rb
</pre>
<p class="aside">
新项目中,添加所有文件很普遍,可以在当前工作目录执行命令:<code>git add .</code>。因为 Git 会递归地将您执行命令时所在的目录中的所有文件添加上去,所以如果你将当前的工作目录作为参数,它就会追踪那儿的所有文件了。如此,<code>git add .</code> 就和 <code>git add README hello.rb</code> 有一样的效果。此外,效果一致的还有 <code>git add *</code>,不过那只是因为我们这还木有子目录,不需要递归地添加新文件。
</p>
<p>好了,现在我们改个文件,再跑一下 <code>git status</code>,有点古怪。</p>
<pre>
<b>$ vim README</b>
<b>$ git status -s</b>
<span class="green">A</span><span class="red">M</span> README
<span class="green">A</span> hello.rb
</pre>
<p>
“AM” 状态的意思是,这个文件在我们将它添加到缓存之后又有改动。这意味着如果我们现在提交快照,我们记录的将是上次跑 <code>git add</code> 的时候的文件版本而不是现在在磁盘中的这个。Git 并不认为磁盘中的文件与您想快照的文件必须是一致的 —— (如果您需要它们一致,)得用 <code>git add</code> 命令告诉它。
</p>
<p class="nutshell">
<strong>一言以蔽之</strong>
当您要将您的修改包含在即将提交的快照里的时候,执行 <code>git add</code>。任何您没有添加的改动都不会被包含在内 —— 这意味着您可以比绝大多数其他源代码版本控制系统更精确地归置您的快照。
</p>
<p>请查看《Pro Git》中 <code>git add</code> 的 “-p” 参数,以了解更多关于提交文件的灵活性的例子。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-status.html">文档</a> &nbsp;
<a target="new" href="http://progit.org/book/ch2-2.html#checking_the_status_of_your_files"></a>
</span>
<a name="status">git status</a>
<span class="desc">查看您的文件在工作目录与缓存的状态</span>
</h2>
<div class="block">
<p>正如您在 <code>git add</code> 小节中所看到的,您可以执行 <code>git status</code> 命令查看您的代码在缓存与当前工作目录的状态。我演示该命令的时候加了 <code>-s</code> 参数,以获得简短的结果输出。若没有这个标记,命令 <code>git status</code> 将告诉您更多的提示与上下文欣喜。以下便是同样状态下,有跟没有 <code>-s</code> 参数的输出对比。简短的输出如下:
</p>
<pre>
<b>$ git status -s</b>
<span class="green">A</span><span class="red">M</span> README
<span class="green">A</span> hello.rb
</pre>
而同样的状态,详细的输出看起来是这样的:
<pre>
<b>$ git status</b>
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# <span class="green">new file: README</span>
# <span class="green">new file: hello.rb</span>
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# <span class="red">modified: README</span>
#
</pre>
<p>您很容易发现简短的输出看起来很紧凑。而详细输出则很有帮助,提示您可以用何种命令完成您接下来可能要做的事情。
</p>
<p>Git 还会告诉您在您上次提交之后,有哪些文件被删除、修改或者存入缓存了。</p>
<pre>
<b>$ git status -s</b>
<span class="green">M</span> README
<span class="red">D</span> hello.rb
</pre>
您可以看到,在简短输出中,有两栏。第一栏是缓存的,第二栏则是工作目录的。所以假设您临时提交了 README 文件,然后又改了些,并且没有执行 <code>git add</code>,您会看到这个:
<pre>
<b>$ git status -s</b>
<span class="green">M</span><span class="red">M</span> README
<span class="red">D</span> hello.rb
</pre>
<p class="nutshell">
<strong>一言以蔽之</strong>,执行 <code>git status</code> 以查看在您上次提交之后有啥被修改或者临时提交了,从而决定自己是否需要提交一次快照,同时也能知道有什么改变被记录进去了。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html">文档</a> &nbsp;
<a target="new" href="http://progit.org/book/ch2-2.html#viewing_your_staged_and_unstaged_changes"></a>
</span>
<a name="diff">git diff</a>
<span class="desc">显示已写入缓存与已修改但尚未写入缓存的改动的区别</span>
</h2>
<div class="block">
<p><code>git diff</code> 有两个主要的应用场景。我们将在此介绍其一,在 <a href="/inspect">检阅与对照</a> 一章中,我们将介绍其二。我们这里介绍的方式是用此命令描述已临时提交的或者已修改但尚未提交的改动。
</p>
<h4>
git diff
<small>#尚未缓存的改动</small>
</h4>
<p>如果没有其他参数,<code>git diff</code> 会以规范化的 diff 格式(一个补丁)显示自从您上次提交快照之后尚未缓存的所有更改。
</p>
<pre>
<b>$ vim hello.rb</b>
<b>$ git status -s</b>
<span class="red">M</span> hello.rb
<b>$ git diff</b>
<span class="umber">diff --git a/hello.rb b/hello.rb
index d62ac43..8d15d50 100644
--- a/hello.rb
+++ b/hello.rb</span>
<span class="lblue">@@ -1,7 +1,7 @@</span>
class HelloWorld
def self.hello
<span class="red">- puts "hello world"</span>
<span class="green">+ puts "hola mundo"</span>
end
end
</pre>
<p>所以,<code>git status</code>显示您上次提交更新至后所更改或者写入缓存的改动,而 <code>git diff</code> 一行一行地显示这些改动具体是啥。通常执行完 <code>git status</code> 之后接着跑一下 <code>git diff</code> 是个好习惯。
</p>
<h4>
git diff --cached
<small>#查看已缓存的改动</small>
</h4>
<p><code>git diff --cached</code> 命令会告诉您有哪些内容已经写入缓存了。也就是说,此命令显示的是接下来要写入快照的内容。所以,如果您将上述示例中的 <code>hello.rb</code> 写入缓存,因为 <code>git diff</code> 显示的是尚未缓存的改动,所以在此执行它不会显示任何信息。
</p>
<pre>
<b>$ git status -s</b>
<span class="red">M</span> hello.rb
<b>$ git add hello.rb </b>
<b>$ git status -s</b>
<span class="green">M</span> hello.rb
<b>$ git diff</b>
<b>$ </b>
</pre>
<p>如果您想看看已缓存的改动,您需要执行的是
<code>git diff --cached</code></p>
<pre>
<b>$ git status -s</b>
<span class="green">M</span> hello.rb
<b>$ git diff</b>
<b>$ </b>
<b>$ git diff --cached</b>
<span class="umber">diff --git a/hello.rb b/hello.rb
index d62ac43..8d15d50 100644
--- a/hello.rb
+++ b/hello.rb</span>
<span class="lblue">@@ -1,7 +1,7 @@</span>
class HelloWorld
def self.hello
<span class="red">- puts "hello world"</span>
<span class="green">+ puts "hola mundo"</span>
end
end
</pre>
<h4>
git diff HEAD
<small>查看已缓存的与未缓存的所有改动</small>
</h4>
<p>如果您想一并查看已缓存的与未缓存的改动,可以执行 <code>git diff HEAD</code> ——也就是说您要看到的是工作目录与上一次提交的更新的区别,无视缓存。假设我们又改了些 <code>ruby.rb</code> 的内容,那缓存的与未缓存的改动我们就都有了。以上三个 <code>diff</code> 命令的结果如下:
</p>
<pre>
<b>$ vim hello.rb </b>
<b>$ git diff</b>
<span class="umber">diff --git a/hello.rb b/hello.rb
index 4f40006..2ae9ba4 100644
--- a/hello.rb
+++ b/hello.rb</span>
<span class="lblue">@@ -1,7 +1,7 @@</span>
class HelloWorld
<span class="green">+ # says hello</span>
def self.hello
puts "hola mundo"
end
end
<b>$ git diff --cached</b>
<span class="umber">diff --git a/hello.rb b/hello.rb
index 2aabb6e..4f40006 100644
--- a/hello.rb
+++ b/hello.rb</span>
<span class="lblue">@@ -1,7 +1,7 @@</span>
class HelloWorld
def self.hello
<span class="red">- puts "hello world"</span>
<span class="green">+ puts "hola mundo"</span>
end
end
<b>$ git diff HEAD</b>
<span class="umber">diff --git a/hello.rb b/hello.rb
index 2aabb6e..2ae9ba4 100644
--- a/hello.rb
+++ b/hello.rb</span>
<span class="lblue">@@ -1,7 +1,8 @@</span>
class HelloWorld
<span class="green">+ # says hello</span>
def self.hello
<span class="red">- puts "hello world"</span>
<span class="green">+ puts "hola mundo"</span>
end
end
</pre>
<h4>
git diff --stat
<small>显示摘要而非整个 diff</small>
</h4>
<p>如果我们不想要看整个 diff 输出,但是又想比 <code>git status</code> 详细点,就可以用 <code>--stat</code> 选项。该选项使它显示摘要而非全文。上文示例在使用 <code>--stat</code> 选项时,输出如下:
</p>
<pre>
<b>$ git status -s</b>
<span class="green">M</span><span class="red">M</span> hello.rb
<b>$ git diff --stat</b>
hello.rb | 1 <span class="green">+</span>
1 files changed, 1 insertions(+), 0 deletions(-)
<b>$ git diff --cached --stat</b>
hello.rb | 2 <span class="green">+</span><span class="red">-</span>
1 files changed, 1 insertions(+), 1 deletions(-)
<b>$ git diff HEAD --stat</b>
hello.rb | 3 <span class="green">++</span><span class="red">-</span>
1 files changed, 2 insertions(+), 1 deletions(-)
</pre>
<p>您还可以在上述命令后面制定一个目录,从而只查看特定文件或子目录的 <code>diff</code> 输出。
</p>
<p class="nutshell">
<strong>一言以蔽之</strong>
执行 <code>git diff</code> 来查看执行 <code>git status</code> 的结果的详细信息 —— 一行一行地显示这些文件是如何被修改或写入缓存的。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-commit.html">文档</a> &nbsp;
<a target="new" href="http://progit.org/book/ch2-2.html#committing_your_changes"></a>
</span>
<a name="commit">git commit</a>
<span class="desc">记录缓存内容的快照</span>
</h2>
<div class="block">
<p>现在您使用 <code>git add</code> 命令将想要快照的内容写入了缓存,执行 <code> git commit</code> 就将它实际存储快照了。Git 为您的每一个提交都记录您的名字与电子邮箱地址,所以第一步是告诉 Git 这些都是啥。
</p>
<pre>
<b>$ git config --global user.name 'Your Name'</b>
<b>$ git config --global user.email you@somedomain.com</b>
</pre>
<p>让我们写入缓存,并提交对 <code>hello.rb</code> 的所有改动。在首个例子中,我们使用 <code>-m</code> 选项以在命令行中提供提交注释。
</p>
<pre>
<b>$ git add hello.rb </b>
<b>$ git status -s</b>
<span class="green">M</span> hello.rb
<b>$ git commit -m 'my hola mundo changes'</b>
[master 68aa034] my hola mundo changes
1 files changed, 2 insertions(+), 1 deletions(-)
</pre>
<p>现在我们已经记录了快照。如果我们再执行 <code>git status</code>,会看到我们有一个“干净的工作目录”。这意味着我们在最近一次提交之后,没有做任何改动 —— 在我们的项目中没有未快照的工作。
</p>
<pre>
<b>$ git status</b>
# On branch master
nothing to commit (working directory clean)
</pre>
<p>如果您漏掉了 <code>-m</code> 选项Git 会尝试为您打开一个编辑器以填写提交信息。如果 Git 在您对它的配置中找不到相关信息,默认会打开 <code>vim</code>。屏幕会像这样:
</p>
<pre>
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: hello.rb
#
~
~
".git/COMMIT_EDITMSG" 9L, 257C
</pre>
<p>在此,您在文件头部添加实际的提交信息。以“#”开头的行都会被无视 ——Git 将 <code> git status</code> 的输出结果放在那儿以提示您都改了、缓存了啥。
</p>
<p>通常,撰写良好的提交信息是很重要的。以开放源代码项目为例,多多少少以以下格式写您的提示消息是个不成文的规定:
</p>
<pre>
简短的关于改动的总结25个字或者更少
如果有必要,更详细的解释文字。约 36 字时换行。在某些情况下,
第一行会被作为电子邮件的开头,而剩余的则会作为邮件内容。
将小结从内容隔开的空行是至关重要的(除非你没有内容);
如果这两个待在一起,有些 git 工具会犯迷糊。
空行之后是更多的段落。
- 列表也可以
- 通常使用连字符(-)或者星号(*)来标记列表,前面有个空格,
在列表项之间有空行,不过这些约定也会有些变化。
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: hello.rb
#
~
~
~
".git/COMMIT_EDITMSG" 25L, 884C written
</pre>
<p class="aside">
提交注解是很重要的。因为 Git 很大一部分能耐就是它在组织本地提交和与他人分享的弹性,它很给力地能够让您为逻辑独立的改变写三到四条提交注解,以便您的工作被同仁审阅。因为提交与推送改动是有区别的,请务必花时间将各个逻辑独立的改动放到另外一个提交,并附上一份良好的提交注解,以使与您合作的人能够方便地了解您所做的,以及您为何要这么做。
</p>
<h4>
git commit -a
<small>自动将在提交前将已记录、修改的文件放入缓存区</small>
</h4>
<p>如果您觉得 <code>git add</code> 提交缓存的流程太过繁琐Git 也允许您用 <code>-a</code> 选项跳过这一步。基本上这句话的意思就是,为任何已有记录的文件执行 <code>git add</code> —— 也就是说,任何在您最近的提交中已经存在,并且之后被修改的文件。这让您能够用更 Subversion 方式的流程,修改些文件,然后想要快照所有所做的改动的时候执行 <code>git commit -a</code>。不过您仍然需要执行 <code>git add</code> 来添加新文件,就像 Subversion 一样。
</p>
<pre>
<b>$ vim hello.rb</b>
<b>$ git status -s</b>
<span class="red">M</span> hello.rb
<b>$ git commit -m 'changes to hello file'</b>
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: hello.rb
#
<span class="hl">no changes added to commit (use "git add" and/or "git commit -a")</span>
<b>$ git commit -am 'changes to hello file'</b>
[master 78b2670] changes to hello file
1 files changed, 2 insertions(+), 1 deletions(-)
</pre>
<p>注意,如果您如果您不缓存改动,直接执行 <code>git commit</code>Git 会直接给出 <code>git status</code> 命令的输出,提醒您啥也没缓存。我已将该消息中的重要部分高亮,它说没有添加需要提交的缓存。如果您使用 <code>-a</code>,它会缓存并提交每个改动(不含新文件)。
</p>
<p>
现在您就完成了整个快照的流程 ——改些文件,然后用 <code>git add</code> 将要提交的改动提交到缓存,用 <code>git status</code><code>git diff</code> 看看您都改了啥,最后 <code>git commit</code> 永久地保存快照。
</p>
<p class="nutshell">
<strong>一言以蔽之</strong>,执行 <code>git commit</code> 记录缓存区的快照。这个快照就可以用来做比较、分享以及,如果需要,恢复。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-reset.html">文档</a> &nbsp;
<a target="new" href="http://progit.org/book/ch2-4.html#unstaging_a_staged_file"></a>
</span>
<a name="reset">git reset HEAD</a>
<span class="desc">取消缓存已缓存的内容</span>
</h2>
<div class="block">
<p><code>git reset</code> 可能是人类写的最费解的命令了。我用 Git 有些年头了,甚至还写了本书,但有的时候还是会搞不清它会做什么。所以,我只说三个明确的,通常有用的调用。请您跟我一样尽管用它 —— 因为它可以很有用。
</p>
<p>在此例中,我们可以用它来将不小心缓存的东东取消缓存。假设您修改了两个文件,想要将它们记录到两个不同的提交中去。您应该缓存并提交一个,再缓存并提交另外一个。如果您不小心两个都缓存了,那要如何才能<i>取消</i>缓存呢?您可以用 <code>git reset HEAD -- file</code>。技术上说,在这里您不需要使用 <code>--</code> —— 它用来告诉 Git 这时您已经不再列选项,剩下的是文件路径了。不过养成使用它分隔选项与路径的习惯很重要,即使在您可能并不需要的时候。
</p>
<p>好,让我们看看取消缓存是什么样子的。这里我们有两个最近提交之后又有所改动的文件。我们将两个都缓存,并取消缓存其中一个。
</p>
<pre>
<b>$ git status -s</b>
<span class="red">M</span> README
<span class="red">M</span> hello.rb
<b>$ git add .</b>
<b>$ git status -s</b>
<span class="green">M</span> README
<span class="green">M</span> hello.rb
<b>$ git reset HEAD -- hello.rb </b>
Unstaged changes after reset:
M hello.rb
<b>$ git status -s</b>
<span class="green">M</span> README
<span class="red">M</span> hello.rb
</pre>
<p>
现在您执行 <code>git commit</code> 将只记录 <code>README</code> 文件的改动,并不含现在并不在缓存中的 <code>hello.rb</code>
</p>
<p class="aside">
如果您好奇,它实际的操作是将该文件在“索引”中的校验和重置为最近一次提交中的值。<code>git add</code> 会计算一个文件的校验和,将它添加到“索引”中,而 <code>git reset HEAD</code> 将它改写回原先的,从而取消缓存。
</p>
<p class="tip">
如果您想直接执行 <code>git unstage</code>,您可以在 Git 中配置个别名。执行 <code>git config --global alias.unstage "reset HEAD"</code> 即可。一旦执行完它,您就可以直接用 <code>git unstage [file]</code> 作为代替了。
</p>
<p>如果您忘了取消缓存的命令Git 的常规 <code>git status</code> 输出的提示会很有帮助。例如,在您有已缓存的文件时,如果您不带 <code>-s</code> 执行 <code>git status</code>,它将告诉您怎样取消缓存:
</p>
<pre>
<b>$ git status</b>
# On branch master
# Changes to be committed:
# <span class="hl">(use "git reset HEAD <file>..." to unstage)</span>
#
# <span class="green">modified: README</span>
# <span class="green">modified: hello.rb</span>
#
</pre>
<p class="nutshell">
<strong>一言以蔽之</strong>,执行 <code>git reset HEAD</code> 以取消之前 <code>git add</code> 添加,但不希望包含在下一提交快照中的缓存。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a href="http://www.kernel.org/pub/software/scm/git/docs/git-rm.html">文档</a> &nbsp;
<a href="http://progit.org/book/ch2-2.html#removing_files"></a>
</span>
<a name="rm-mv">git rm</a>
<span class="desc">将文件从缓存区移除</span>
</h2>
<div class="block">
<p>
<code>git rm</code> 会将条目从缓存区中移除。这与 <code>git reset HEAD</code> 将条目取消缓存是有区别的。“取消缓存”的意思就是将缓存区恢复为我们做出修改之前的样子。在另一方面,<code>git rm</code> 则将该文件彻底从缓存区踢出,因此它不再下一个提交快照之内,进而有效地删除它。
</p>
<p>
默认情况下,<code>git rm file</code> 会将文件从缓存区和您的硬盘中(工作目录)删除。如果要在工作目录中留着该文件,可以使用 <code>git rm --cached</code>
</p>
<h4>
git mv
<small>git rm --cached orig; mv orig new; git add new</small>
</h4>
<p>
不像绝大多数其他版本控制系统Git 并不记录记录文件重命名。它反而只记录快照并对比快照以找到有啥文件可能被重命名了。如果一个文件从更新中删除了而在下次快照中新添加的另一个文件的内容与它很相似Git 就知道这极有可能是个重命名。因此,虽然有 <code>git mv</code> 命令,但它有点多余 —— 它做得所有事情就是 <code>git rm --cached</code>,重命名磁盘上的文件,然后再执行 <code>git add</code> 把新文件添加到缓存区。您并不需要用它,不过如果觉得这样容易些,尽管用吧。
</p>
<p class="aside">
我自己不会用此命令的普通形式 —— 删除文件。通常直接从硬盘删除文件,然后执行 <code>git commit -a</code> 会简单些。它会自动将删除的文件从索引中移除。
</p>
<p class="nutshell">
<strong>一言以蔽之</strong>
执行 <code>git rm</code> 来删除 Git 追踪的文件。它还会删除您的工作目录中的相应文件。
</p>
</div>
</div>
<p><a href="/zh/branching">到 分支与合并 &#187;</a></p>

630
zh/branching/index.html Normal file
View File

@ -0,0 +1,630 @@
---
layout: zh_reference
---
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://progit.org/book/ch3-0.html"></a>
</span>
分支与合并
</h2>
<div class="block">
<p>分支是我最喜欢的 Git 特性之一。如果您用过其他版本控制系统,把您所知的分支给忘记,倒可能更有帮助些 —— 事实上,以我们使用分支的方式,把 Git 的分支看作 <i>上下文</i> 反而更合适。当您检出分支时,您可以在两三个不同的分支之间来回切换。
</p>
<p class="nutshell">
<b>一言以蔽之</b>,您可以执行 <code>git branch (branchname)</code> 来创建分支,使用 <code>git checkout (branchname)</code> 命令切换到该分支在该分支的上下文环境中提交快照等之后可以很容易地来回切换。当您切换分支的时候Git 会用该分支的最后提交的快照替换您的工作目录的内容,所以多个分支不需要多个目录。使用 <code>git merge</code> 来合并分支。您可以多次合并到统一分支,也可以选择在合并之后直接删除被并入的分支。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-branch.html">文档</a> &nbsp;
<a target="new" href="http://progit.org/book/ch3-2.html"></a>
</span>
<a name="branch">git branch</a>
<span class="desc">列出、创建与管理工作上下文</span>
</h2>
<br/>
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html">文档</a> &nbsp;
<a target="new" href="http://progit.org/book/ch3-2.html"></a>
</span>
<a name="checkout">git checkout</a>
<span class="desc">切换到新的分支上下文</span>
</h2>
<div class="block">
<p><code>git branch</code> 命令是 Git 中的通用分支管理工具,可以通过它完成多项任务。我们先说您会用到的最多的命令 —— 列出分支、创建分支和删除分支。我们还会介绍用来切换分支的 <code>git checkout</code> 命令。
</p>
<h4>
git branch
<small>列出可用的分支</small>
</h4>
<p>没有参数是,<code>git branch</code> 会列出您在本地的分支。您所在的分支的行首会有个星号作标记。如果您开启了<a href="http://progit.org/book/ch7-1.html#colors_in_git">彩色模式</a>,当前分支会用绿色显示。
</p>
<pre>
$ git branch
* <span class="green">master</span>
</pre>
<p>此例的意思就是我们有一个叫做“master”的分支并且该分支是当前分支。当您执行 <code>git init</code> 的时候,缺省情况下 Git 就会为您创建“master”分支。但是这名字一点特殊意味都没有 —— 事实上您并不非得要一个叫做“master”的分支。不过由于它是缺省分支名的缘故绝大部分项目都有这个分支。
</p>
<h4>
git branch (branchname)
<small>创建新分支</small>
</h4>
<p>我们动手创建一个分支,并切换过去。执行 <code>git branch (branchname)</code> 即可。
<pre>
$ git branch testing
$ git branch
* <span class="green">master</span>
testing
</pre>
<p>现在我们可以看到有了一个新分支。当您以此方式在上次提交更新之后创建了新分支如果后来又有更新提交然后又切换到了“testing”分支Git 将还原您的工作目录到您创建分支时候的样子 —— 您可以把它看作一个记录您当前进度的书签。让我们实际运用看看 —— 我们用 <code>git checkout (branch)</code> 切换到我们要修改的分支。
</p>
<pre>
<b>$ ls</b>
README hello.rb
<b>$ echo 'test content' > test.txt</b>
<b>$ echo 'more content' > more.txt</b>
<b>$ git add *.txt</b>
<b>$ git commit -m 'added two files'</b>
[master 8bd6d8b] added two files
2 files changed, 2 insertions(+), 0 deletions(-)
create mode 100644 more.txt
create mode 100644 test.txt
<b>$ ls</b>
README hello.rb more.txt test.txt
<b>$ git checkout testing</b>
Switched to branch 'testing'
<b>$ ls</b>
README hello.rb
</pre>
<p>当我们切换到“测试”分支的时候我们添加的新文件被移除了。切换回“master”分支的时候它们有重新出现了。
</p>
<pre>
<b>$ ls</b>
README hello.rb
<b>$ git checkout master</b>
Switched to branch 'master'
<b>$ ls</b>
README hello.rb more.txt test.txt
</pre>
<h4>
git checkout -b (branchname)
<small>创建新分支,并立即切换到它</small>
</h4>
<p>
通常情况下您会更希望立即切换到新分支从而在该分支中操作然后当此分支的开发日趋稳定时将它合并到稳定版本的分支例如“master”中去。执行 <code>git branch newbranch; git checkout newbranch</code> 也很简单,不过 Git 还为您提供了快捷方式:<code>git checkout -b newbranch</code>
</p>
<pre>
<b>$ git branch</b>
* master
<b>$ ls</b>
README hello.rb more.txt test.txt
<b>$ git checkout -b removals</b>
Switched to a new branch 'removals'
<b>$ git rm more.txt </b>
rm 'more.txt'
<b>$ git rm test.txt </b>
rm 'test.txt'
<b>$ ls</b>
README hello.rb
<b>$ git commit -am 'removed useless files'</b>
[removals 8f7c949] removed useless files
2 files changed, 0 insertions(+), 2 deletions(-)
delete mode 100644 more.txt
delete mode 100644 test.txt
<b>$ git checkout master</b>
Switched to branch 'master'
<b>$ ls</b>
README hello.rb more.txt test.txt
</pre>
<p>如您所见,我们创建了一个分支,在该分支的上下文中移除了一些文件,然后切换回我们的主分支,那些文件又回来了。使用分支将工作切分开来,从而让我们能够在不同上下文中做事,并来回切换。
</p>
<p>
创建新分支,在其中完成一部分工作,完成之后将它合并到主分支并删除。您会觉得这很方便,因为这么做很快很容易。如此,当您觉得这部分工作并不靠谱,舍弃它很容易。并且,如果您必须回到稳定分支做些事情,也可以很方便地这个独立分支的工作先丢在一边,完成要事之后再切换回来。
</p>
<h4>
git branch -d (branchname)
<small>删除分支</small>
</h4>
<p>假设我们要删除一个分支比如上例中的“testing”分支该分支没啥特殊的内容了可以执行 <code>git branch -d (branch)</code> 把它删掉。
<pre>
<b>$ git branch</b>
* <span class="green">master</span>
testing
<b>$ git branch -d testing</b>
Deleted branch testing (was 78b2670).
<b>$ git branch</b>
* <span class="green">master</span>
</pre>
<p class="nutshell">
<b>一言以蔽之</b> 使用 <code>git branch</code> 列出现有的分支、创建新分支以及删除不必要或者已合并的分支。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-merge.html">docs</a> &nbsp;
<a target="new" href="http://progit.org/book/ch3-2.html#basic_merging">book</a>
</span>
<a name="merge">git merge</a>
<span class="desc">将分支合并到您的当前分支</span>
</h2>
<div class="block">
<p>一旦某分支有了独立内容,您终究会希望将它合并回到您的主分支。您可以使用 <code>git merge</code> 命令将任何分支合并到当前分支中去。我们那上例中的“removals”分支为例。假设我们创建了一个分支移除了一些文件并将它提交到该分支其实该分支是与我们的主分支也就是“master”独立开来的。要想将这些移除操作包含在主分支中您可以将“removals”分支合并回去。
</p>
<pre>
<b>$ git branch</b>
* <span class="green">master</span>
removals
<b>$ ls</b>
README hello.rb more.txt test.txt
<b>$ git merge removals</b>
Updating 8bd6d8b..8f7c949
Fast-forward
more.txt | 1 -
test.txt | 1 -
2 files changed, 0 insertions(+), 2 deletions(-)
delete mode 100644 more.txt
delete mode 100644 test.txt
<b>$ ls</b>
<span class="hl">README hello.rb</span>
</pre>
<h4>
更多复杂合并
</h4>
<p>当然合并并不仅仅是简单的文件添加、移除的操作Git 也会合并修改 —— 事实上,它很会合并修改。举例,我们看看在某分支中编辑某个文件,然后在另一个分支中把它的名字改掉再做些修改,最后将这俩分支合并起来。您觉得会变成一坨 shi我们试试看。
</p>
<pre>
<b>$ git branch</b>
* master
<b>$ cat hello.rb </b>
class HelloWorld
def self.hello
puts "Hello World"
end
end
HelloWorld.hello
</pre>
<p>首先我们创建一个叫做“change_class”的分支切换过去从而将重命名类等操作独立出来。我们将类名从 “HelloWorld” 改为 “HiWorld”。
</p>
<pre>
<b>$ git checkout -b change_class</b>
M hello.rb
Switched to a new branch 'change_class'
<b>$ vim hello.rb </b>
<b>$ head -1 hello.rb </b>
class HiWorld
<b>$ git commit -am 'changed the class name'</b>
[change_class 3467b0a] changed the class name
1 files changed, 2 insertions(+), 4 deletions(-)
</pre>
<p>然后,将重命名类操作提交到 “change_class” 分支中。现在,假如切换回 “master” 分支我们可以看到类名恢复到了我们切换到 “change_class” 分支之前的样子。现在,再做些修改(即代码中的输出),同时将文件名从 <code>hello.rb</code> 改为 <code>ruby.rb</code>
<pre>
<b>$ git checkout master</b>
Switched to branch 'master'
<b>$ git mv hello.rb ruby.rb</b>
<b>$ vim ruby.rb </b>
<b>$ git diff</b>
<span class="umber">diff --git a/ruby.rb b/ruby.rb
index 2aabb6e..bf64b17 100644
--- a/ruby.rb
+++ b/ruby.rb</span>
<span class="lblue">@@ -1,7 +1,7 @@</span>
class HelloWorld
def self.hello
<span class="red">- puts "Hello World"</span>
<span class="green">+ puts "Hello World from Ruby"</span>
end
end
<b>$ git commit -am 'added from ruby'</b>
[master b7ae93b] added from ruby
1 files changed, 1 insertions(+), 1 deletions(-)
rename hello.rb => ruby.rb (65%)
</pre>
<p>现在这些改变已经记录到我的 “master” 分支了。请注意,这里类名还是 “HelloWorld”而不是 “HiWorld”。然后我想将类名的改变合并过来我把 “change_class” 分支合并过来就行了。但是我已经将文件名都改掉了Git 知道该怎么办么?
</p>
<pre>
<b>$ git branch</b>
change_class
* master
<b>$ git merge change_class</b>
Renaming hello.rb => ruby.rb
Auto-merging ruby.rb
Merge made by recursive.
ruby.rb | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
<b>$ cat ruby.rb</b>
class HiWorld
def self.hello
puts "Hello World from Ruby"
end
end
HiWorld.hello
</pre>
<p>不错,它就是发现了。请注意,在这部操作,我没有遇到合并冲突,并且文件已经重命名、类名也换掉了。挺酷。
</p>
<h4>
合并冲突
</h4>
<p>那么Git 合并很有魔力,我们再也不用处理合并冲突了,对吗?不太确切。不同分支中修改了相同区块的代码,电脑自己猜不透神马的情况下,冲突就摆在我们面前了。我们看看两个分支中改了同一行代码的例子。
<p>
<pre>
<b>$ git branch</b>
* master
<b>$ git checkout -b fix_readme</b>
Switched to a new branch 'fix_readme'
<b>$ vim README </b>
<b>$ git commit -am 'fixed readme title'</b>
[fix_readme 3ac015d] fixed readme title
1 files changed, 1 insertions(+), 1 deletions(-)
</pre>
<p>我们在某分支中修改了 README 文件中的一行,并提交了。我们再在 “master” 分支中对同个文件的同一行内容作不同的修改。
</p>
<pre>
<b>$ git checkout master</b>
Switched to branch 'master'
<b>$ vim README </b>
<b>$ git commit -am 'fixed readme title differently'</b>
[master 3cbb6aa] fixed readme title differently
1 files changed, 1 insertions(+), 1 deletions(-)
</pre>
<p>有意思的来了 —— 我们将前一个分支合并到 “master” 分支,一个合并冲突就出现了。
</p>
<pre>
<b>$ git merge fix_readme</b>
Auto-merging README
CONFLICT (content): Merge conflict in README
Automatic merge failed; fix conflicts and then commit the result.
<b>$ cat README </b>
<<<<<<< HEAD
Many Hello World Examples
=======
Hello World Lang Examples
>>>>>>> fix_readme
This project has examples of hello world in
nearly every programming language.
</pre>
<p>您可以看到Git 在产生合并冲突的地方插入了标准的与 Subversion 很像的合并冲突标记。轮到我们去解决这些冲突了。在这里我们就手动把它解决。如果您要 Git 打开一个图形化的合并工具,可以看看 <a href="http://www.kernel.org/pub/software/scm/git/docs/git-mergetool.html">git 合并工具</a>(比如 kdiff3、emerge、p4merge 等)。
</p>
<pre>
<b>$ vim README </b> <span class="exp">here I'm fixing the conflict</span>
<b>$ git diff</b>
<span class="umber">diff --cc README
index 9103e27,69cad1a..0000000
--- a/README
+++ b/README</span>
<span class="lblue">@@@ -1,4 -1,4 +1,4 @@@</span>
<span class="red">- Many Hello World Examples</span>
<span class="red">-Hello World Lang Examples</span>
<span class="green">++Many Hello World Lang Examples</span>
This project has examples of hello world in
</pre>
<p>在 Git 中,处理合并冲突的时候有个很酷的提示。如果您执行 <code>git diff</code>,就像我演示的这样,它会告诉您冲突的两方,和您是如何解决的。现在是时候把它标记为已解决了。在 Git 中,我们可以用 <code>git add</code> —— 要告诉 Git 文件冲突已经解决,您必须把它写入缓存区。
</p>
<pre>
<b>$ git status -s</b>
UU README
<b>$ git add README </b>
<b>$ git status -s</b>
M README
<b>$ git commit </b>
[master 8d585ea] Merge branch 'fix_readme'
</pre>
<p>现在我们成功解决了合并中的冲突,并提交了结果
</p>
<p class="nutshell">
<b>一言以蔽之</b> 使用 <code>git merge</code> 将另一个分支并入当前的分支中去。Git 会自动以最佳方式将两个不同快照中独特的工作合并到一个新快照中去。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-log.html">文档</a> &nbsp;
<a target="new" href="http://progit.org/book/ch6-1.html#commit_ranges"></a>
</span>
<a name="log">git log</a>
<span class="desc">显示一个分支中提交的更改记录</span>
</h2>
<div class="block">
<p>
到目前为止我们已经提交快照到项目中在不同的各自分离的上下文中切换但假如我们忘了自己是如何到目前这一步的那该怎么办或者假如我们想知道此分支与彼分支到底有啥区别Git 提供了一个告诉您使您达成当前快照的所有提交消息的工具,叫做 <code>git log</code>
</p>
<p>
要理解日志log命令您需要了解当执行 <code>git commit</code> 以存储一个快照的时候都有啥信息被保存了。除了文件详单、提交消息和提交者的信息Git 还保存了您的此次提交所基于的快照。也就是,假如您克隆了一个项目,您是在什么快照的基础上做的修改而得到新保存的快照的?这有益于为项目进程提供上下文,使 Git 能够弄明白谁做了什么改动。如果 Git 有您的快照所基于的快照的话,它就能自动判断您都改变了什么。而新提交所基于的提交,被称作新提交的“父亲”。
</p>
<p>某分支的按时间排序的“父亲”列表,当您在该分支时,可以执行 <code>git log</code> 以查看。例如,如果我们在本章中操作的 Hello World 项目中执行 <code>git log</code>,我们可以看到已提交的消息。
<pre>
<b>$ git log</b>
<span class="yellow">commit 8d585ea6faf99facd39b55d6f6a3b3f481ad0d3d</span>
Merge: 3cbb6aa 3ac015d
Author: Scott Chacon &lt;schacon@gmail.com>
Date: Fri Jun 4 12:59:47 2010 +0200
Merge branch 'fix_readme'
Conflicts:
README
<span class="yellow">commit 3cbb6aae5c0cbd711c098e113ae436801371c95e</span>
Author: Scott Chacon &lt;schacon@gmail.com>
Date: Fri Jun 4 12:58:53 2010 +0200
fixed readme title differently
<span class="yellow">commit 3ac015da8ade34d4c7ebeffa2053fcac33fb495b</span>
Author: Scott Chacon &lt;schacon@gmail.com>
Date: Fri Jun 4 12:58:36 2010 +0200
fixed readme title
<span class="yellow">commit 558151a95567ba4181bab5746bc8f34bd87143d6</span>
Merge: b7ae93b 3467b0a
Author: Scott Chacon &lt;schacon@gmail.com>
Date: Fri Jun 4 12:37:05 2010 +0200
Merge branch 'change_class'
...
</pre>
<p>我们可以用 <code>--oneline</code> 选项来查看历史记录的紧凑简洁的版本。
</p>
<pre>
<b>$ git log --oneline</b>
8d585ea Merge branch 'fix_readme'
3cbb6aa fixed readme title differently
3ac015d fixed readme title
558151a Merge branch 'change_class'
b7ae93b added from ruby
3467b0a changed the class name
17f4acf first commit
</pre>
<p>
这告诉我们的是,此项目的开发历史。如果提交消息描述性很好,这就能为我们提供关于有啥改动被应用、或者影响了当前快照的状态、以及这快照里头都有啥。
</p>
<p>我们还可以用它的十分有帮助的 <code>--graph</code> 选项,查看历史中什么时候出现了分支、合并。以下为相同的命令,开启了拓扑图选项:
</p>
<pre>
<b>$ git log --oneline --graph</b>
* 8d585ea Merge branch 'fix_readme'
|\
| * 3ac015d fixed readme title
* | 3cbb6aa fixed readme title differently
|/
* 558151a Merge branch 'change_class'
|\
| * 3467b0a changed the class name
* | b7ae93b added from ruby
|/
* 17f4acf first commit
</pre>
<p>现在我们可以更清楚明了地看到何时工作分叉、又何时归并。这对查看发生了什么、应用了什么改变很有帮助,并且极大地帮助您管理您的分支。让我们创建一个分支,在里头做些事情,然后切回到主分支,也做点事情,然后看看 <code>log</code> 命令是如何帮助我们理清这俩分支上都发生了啥的。
</p>
<p>首先我们创建一个分支,来添加 Erlang 编程语言的 Hello World 示例 —— 我们想要在一个分支里头做这个,以避免让可能还不能工作的代码弄乱我们的稳定分支。这样就可以切来切去,片叶不沾身。
</p>
<pre>
<b>$ git checkout -b erlang</b>
Switched to a new branch 'erlang'
<b>$ vim erlang_hw.erl</b>
<b>$ git add erlang_hw.erl </b>
<b>$ git commit -m 'added erlang'</b>
[erlang ab5ab4c] added erlang
1 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 erlang_hw.erl
</pre>
<p>由于我们玩函数式编程很开心以至于沉迷其中又在“erlang”分支中添加了一个 Haskell 的示例程序。
</p>
<pre>
<b>$ vim haskell.hs</b>
<b>$ git add haskell.hs </b>
<b>$ git commit -m 'added haskell'</b>
[erlang 1834130] added haskell
1 files changed, 4 insertions(+), 0 deletions(-)
create mode 100644 haskell.hs
</pre>
<p>最后,我们决定还是把 Ruby 程序的类名改回原先的样子。与其创建另一个分支,我们可以返回主分支,改变它,然后直接提交。
</p>
<pre>
<b>$ git checkout master</b>
Switched to branch 'master'
<b>$ ls</b>
README ruby.rb
<b>$ vim ruby.rb </b>
<b>$ git commit -am 'reverted to old class name'</b>
[master 594f90b] reverted to old class name
1 files changed, 2 insertions(+), 2 deletions(-)
</pre>
<p>现在假设我们有段时间不做这个项目了我们做别的去了。当我们回来的时候我们想知道“erlang”分支都是啥而主分支的进度又是怎样。仅仅看分支的名字我们是无从知道自己还在里面有 Haskell 的改动的,但是用 <code>git log</code> 我们就可以。如果您在命令行中提供一个分支名字,它就会显示该分支历史中“可及”的提交,即从该分支创立起可追溯的影响了最终的快照的提交。
</p>
<pre>
<b>$ git log --oneline erlang</b>
<span class="hl">1834130 added haskell</span>
ab5ab4c added erlang
8d585ea Merge branch 'fix_readme'
3cbb6aa fixed readme title differently
3ac015d fixed readme title
558151a Merge branch 'change_class'
b7ae93b added from ruby
3467b0a changed the class name
17f4acf first commit
</pre>
<p>如此,我们很容易就看到分支里头还包括了 Haskell 代码(高亮显示了)。更酷的是,我们很容易地告诉 Git我们只对某个分支中可及的提交感兴趣。换句话说某分支中与其他分支相比唯一的提交。
</p>
<p>在此例中如果我们想要合并“erlang”分支我们需要看当合并的时候都有啥提交会作用到我们的快照上去。我们告诉 Git 的方式是,在不想要看到的分支前放一个 <code>^</code>。例如如果我们想要看“erlang”分支中但不在主分支中的提交我们可以用 <code>erlang ^master</code>,或者反之。
</p>
<pre>
<b>$ git log --oneline erlang ^master</b>
1834130 added haskell
ab5ab4c added erlang
<b>$ git log --oneline master ^erlang</b>
594f90b reverted to old class name
</pre>
<p>这为我们提供了一个良好的、简易的分支管理工具。它使我们能够非常容易地查看对某个分支唯一的提交,从而知道我们缺少什么,以及当我们要合并时,会有什么被合并进去。
</p>
<p class="nutshell">
<b>一言以蔽之</b> 使用 <code>git log</code> 列出促成当前分支目前的快照的提交历史记录。这使您能够看到项目是如何到达现在的状况的。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-tag.html">文档</a> &nbsp;
<a target="new" href="http://progit.org/book/ch2-6.html"></a>
</span>
<a name="tag">git tag</a>
<span class="desc">给历史记录中的某个重要的一点打上标签</span>
</h2>
<div class="block">
<p>
如果您达到一个重要的阶段,并希望永远记住那个特别的提交快照,您可以使用 <code>git tag</code> 给它打上标签。该 <code>tag</code> 命令基本上会给该特殊提交打上永久的书签,从而使您在将来能够用它与其他提交比较。通常,您会在切取一个发布版本或者交付一些东西的时候打个标签。
</p>
<p>比如说,我们想为我们的 Hello World 项目发布一个“1.0”版本。我们可以用 <code>git tag -a v1.0</code> 命令给最新一次提交打上(<code>HEAD</code>“v1.0”的标签。<code>-a</code> 选项意为“创建一个带注解的标签”,从而使您为标签添加注解。绝大部分时候都会这么做的。不用 <code>-a</code> 选项也可以执行的,但它不会记录这标签是啥时候打的,谁打的,也不会让你添加个标签的注解。我推荐一直创建带注解的标签。</p>
<pre>
<b>$ git tag -a v1.0 </b>
</pre>
<p>当您执行 <code>git tag -a</code> 命令时Git 会打开您的编辑器,让您写一句标签注解,就像您给提交写注解一样。
</p>
<p>现在,注意当我们执行 <code>git log --decorate</code> 时,我们可以看到我们的标签了:
</p>
<pre>
<b>$ git log --oneline --decorate --graph</b>
* 594f90b (HEAD, <span class="hl">tag: v1.0</span>, master) reverted to old class name
* 8d585ea Merge branch 'fix_readme'
|\
| * 3ac015d (fix_readme) fixed readme title
* | 3cbb6aa fixed readme title differently
|/
* 558151a Merge branch 'change_class'
|\
| * 3467b0a changed the class name
* | b7ae93b added from ruby
|/
* 17f4acf first commit
</pre>
<p>如果我们有新提交,该标签依然会待在该提交的边上,所以我们已经给那个特定快照永久打上标签,并且能够将它与未来的快照做比较。
</p>
<p>不过我们并不需要给当前提交打标签。如果我们忘了给某个提交打标签,又将它发布了,我们可以给它追加标签。在相同的命令末尾加上提交的 SHA执行就可以了。例如假设我们发布了提交 <code>558151a</code>(几个提交之前的事情了),但是那时候忘了给它打标签。我们现在也可以:</p>
<pre>
<b>$ git tag -a v0.9 558151a</b>
<b>$ git log --oneline --decorate --graph</b>
* 594f90b (HEAD, tag: v1.0, master) reverted to old class name
* 8d585ea Merge branch 'fix_readme'
|\
| * 3ac015d (fix_readme) fixed readme title
* | 3cbb6aa fixed readme title differently
|/
* 558151a (<span class="hl">tag: v0.9</span>) Merge branch 'change_class'
|\
| * 3467b0a changed the class name
* | b7ae93b added from ruby
|/
* 17f4acf first commit
</pre>
</div>
</div>
<p><a href="/zh/remotes">到 分享与更新项目 &#187;</a></p>

12
zh/cookbook.html Normal file
View File

@ -0,0 +1,12 @@
---
layout: zh_reference
---
<div class="box">
<h2>Git Cookbook</h2>
<ul>
<li>Revert a file</li>
<li>Recover a lost branch</li>
<li>Contribute to a project on GitHub</li>
<li>Undo a merge</li>
</ul>
</div>

112
zh/creating/index.html Normal file
View File

@ -0,0 +1,112 @@
---
layout: zh_reference
---
<div class="box">
<h2>获取与创建项目</h2>
<div class="block">
<p>
您得现有一个 Git 仓库,才能用它进行操作。仓库是 Git 存放您要保存的快照的数据的地方。
</p>
<p>
拥有一个 Git 仓库的途径有两种。在已有的目录中,初始化一个新的,其一。比如一个新的项目,或者一个已存在的项目,但该项目尚未有版本控制。如果您想要复制一份别人的项目,或者与别人合作某个项目,也可以从一个公开的 Git 仓库克隆,其二。本章将对两者都做介绍。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-init.html">文档</a> &nbsp;
<a target="new" href="http://progit.org/book/ch2-1.html#initializing_a_repository_in_an_existing_directory"></a>
</span>
<a name="init">git init</a>
<span class="desc">将一个目录初始化为 Git 仓库</span>
</h2>
<div class="block">
在目录中执行 <code>git init</code>,就可以创建一个 Git 仓库了。比如,我们恰好有个目录,里头有些许文件,如下:
<pre>
<b>$ cd konichiwa</b>
<b>$ ls</b>
README hello.rb
</pre>
在这个项目里头,我们会用各种编程语言写 "Hello World" 实例。到目前为止,我们只有 Ruby 的,不过,这才刚上路嘛。为了开始用 Git 对这个项目作版本控制,我们执行一下 <code>git init</code>
<pre>
<b>$ git init</b>
Initialized empty Git repository in /opt/konichiwa/.git/
# 在 /opt/konichiwa/.git 目录初始化空 Git 仓库完毕。
</pre>
现在您可以看到在您的项目目录中有个 <code>.git</code> 的子目录。这就是您的 Git 仓库了,所有有关您的此项目的快照数据都存放在这里。
<pre>
<b>$ ls -a</b>
. .. .git README hello.rb
</pre>
恭喜,现在您就有了一个 Git 仓库的架子,可以开始快照您的项目了。
<p class="nutshell">
<strong>一言以蔽之</strong>,用 <code>git init</code> 来在目录中创建新的 Git 仓库。您可以在任何时候、任何目录中这么做,完全是本地化的。
</p>
</div>
</div>
<div class="box">
<h2>
<span class="docs">
<a target="new" href="http://www.kernel.org/pub/software/scm/git/docs/git-clone.html">文档 </a> &nbsp;
<a target="new" href="http://progit.org/book/ch2-1.html#cloning_an_existing_repository"></a>
</span>
<a name="clone">git clone</a>
<span class="desc">复制一个 Git 仓库,以上下其手</span>
</h2>
<div class="block">
<p>
如果您需要与他人合作一个项目,或者想要拷贝一个项目,看看代码,您就可以克隆那个项目。执行 <code>git clone [url]</code>[url] 为您想要拷贝的项目,就可以了。
</p>
<pre>
<b>$ git clone git://github.com/schacon/simplegit.git</b>
Initialized empty Git repository in /private/tmp/simplegit/.git/
remote: Counting objects: 100, done.
remote: Compressing objects: 100% (86/86), done.
remote: Total 100 (delta 35), reused 0 (delta 0)
Receiving objects: 100% (100/100), 9.51 KiB, done.
Resolving deltas: 100% (35/35), done.
<b>$ cd simplegit/</b>
<b>$ ls</b>
README Rakefile <span class="blue">lib</span>
</pre>
<p>
上述操作将拷贝该项目的全部记录,让您本地拥有这些。并且该操作将拷贝该项目的主分支,是您能够查看代码,或编辑修改。进到该目录中,您会看到 <code>.git</code> 子目录。所有的项目数据都存在那里。
</p>
<pre>
<b>$ ls -a</b>
. .. <span class="blue">.git</span> README Rakefile <span class="blue">lib</span>
<b>$ cd .git</b>
<b>$ ls</b>
HEAD description <span class="blue">info</span> packed-refs
<span class="blue">branches hooks logs refs</span>
config index <span class="blue">objects</span>
</pre>
<p>
默认情况下Git 会按照您提供的 URL 所指示的项目的名称创建您的本地项目目录。通常就是该 URL 最后一个 <code>/</code> 之后的任何东西。如果你想要一个不一样的名字,您可以在该命令后加上它,就在那个 URL 后面。
</p>
<p class="nutshell">
<strong>一言以蔽之</strong>,使用 <code>git clone</code> 本地拷贝一个 Git 仓库,让自己能够查看该项目,或者动手修改
</p>
</div>
</div>
<p><a href="/zh/basic">接下来:简单快照 &#187;</a></p>

BIN
zh/images/snapshots.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB