forked from MarkLodato/visual-git-guide
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index-zh-tw.html
235 lines (150 loc) · 13 KB
/
index-zh-tw.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>圖解Git</title>
<link rel='stylesheet' type='text/css' href='visual-git-guide.css'>
<script type="text/javascript" src='visual-git-guide.js'></script>
</head>
<body onload="replace_all_PNGs();">
<h1 id="top">圖解Git</h1>
<div id="language-box">
<a>其他語言:</a>
<ul>
<li><a href='index-de.html'>Deutsch</a></li>
<li><a href='index-en.html'>English</a></li>
<li><a href='index-es.html'>Español</a></li>
<li><a href='index-fr.html'>Français</a></li>
<li><a href='index-it.html'>Italiano</a></li>
<li><a href='index-ja.html'>日本語</a></li>
<li><a href='index-ko.html'>한국어</a></li>
<li><a href='index-ko.html'>Polski</a></li>
<li><a href='index-pt.html'>Português</a></li>
<li><a href='index-ru.html'>Русский</a></li>
<li><a href='index-sk.html'>Slovenčina</a></li>
<li><a href='index-vi.html'>Tiếng Việt</a></li>
<li><a href='index-zh-cn.html'>简体中文</a></li>
<li class="selected">正體中文</li>
</ul>
</div>
<p id="link-to-png">如果圖片不能顯示,試試<a href="?no-svg">非SVG版</a></p>
<p id="link-to-svg">SVG圖片已被停用
<a href="index.html">(重新啟用SVG)</a></p>
<p>此頁圖解git中的最常用命令。如果你稍微理解git的工作原理,這篇文章能夠讓你理解的更透徹。
如果你想知道這個網站怎樣產生,請前往<a href='http://github.com/MarkLodato/visual-git-guide'>GitHub
repository</a>。</p>
<h2 id="contents">正文</h2>
<ol>
<li><a href="#basic-usage">基本使用</a></li>
<li><a href="#conventions">規範</a></li>
<li><a href="#commands-in-detail">命令詳解</a>
<ol>
<li><a href="#diff">Diff</a></li>
<li><a href="#commit">Commit</a></li>
<li><a href="#checkout">Checkout</a></li>
<li><a href="#detached">Detached HEAD(匿名分支提交)</a></li>
<li><a href="#reset">Reset</a></li>
<li><a href="#merge">Merge</a></li>
<li><a href="#cherry-pick">Cherry Pick</a></li>
<li><a href="#rebase">Rebase</a></li>
</ol>
</li>
<li><a href="#technical-notes">技術說明</a></li>
</ol>
<h2 id="basic-usage">基本使用</h2>
<div class="center"><img src='basic-usage.svg.png'></div>
<p>上面的四條命令在工作目錄、暫存目錄(也叫做索引)和倉庫之間複製檔案。</p>
<ul>
<li><code>git add <em>files</em></code> 把指定檔案放入暫存區域。</li>
<li><code>git commit</code> 給暫存區域產生快照並提交。</li>
<li><code>git reset -- <em>files</em></code> 用來撤銷最後一次<code>git add <em>files</em></code>,你也可以用<code>git reset</code>
撤銷所有暫存區域檔案。</li>
<li><code>git checkout -- <em>files</em></code> 把檔從暫存區域複製到工作目錄,用來放棄本地修改。</li>
</ul>
<p>你可以用 <code>git reset -p</code>, <code>git checkout -p</code>, or
<code>git add -p</code>進入互動模式。</p>
<p>也可以跳過暫存區域直接從倉庫取出檔案或者直接提交代碼。</p>
<div class="center"><img src='basic-usage-2.svg.png'></div>
<ul>
<li><code>git commit -a </code> 相當於執行 <tt>git add</tt>
把所有目前的目錄下的檔加入暫存區域再執行。<tt>git commit</tt>.</li>
<li><code>git commit <em>files</em></code> 進行一次包含最後一次提交加上工作目錄中檔快照的提交。並且檔被添加到暫存區域。</li>
<li><code>git checkout HEAD -- <em>files</em></code> 回滾到複製最後一次提交。</li>
</ul>
<h2 id="conventions">規範</h2>
<p>後文中以下面的形式使用圖片。</p>
<div class="center"><img src='conventions.svg.png'></div>
<p>綠色的5位元字元表示提交的ID,分別指向父節點。分支用橘色顯示,分別指向特定的提交。目前分支由附在其上的<em>HEAD</em>標識。
這張圖片裡顯示最後5次提交,<em>ed489</em>是最新提交。 <em>master</em>分支指向此次提交,另一個<em>maint</em>分支指向祖父提交節點。</p>
<h2 id="commands-in-detail">命令詳解</h2>
<h3 id="diff">Diff</h3>
<p>有許多種方法查看兩次提交之間的變動。下面是一些範例。</p>
<div class="center"><img src='diff.svg.png'></div>
<h3 id="commit">Commit</h3>
<p>提交時,git用暫存區域的檔建立一個新的提交,並把此時的節點設為父節點。然後把目前分支指向新的提交節點。下圖中,目前分支是<em>master</em>。
在執行命令之前,<em>master</em>指向<em>ed489</em>,提交後,<em>master</em>指向新的節點<em>f0cec</em>並以<em>ed489</em>作為父節點。</p>
<div class="center"><img src='commit-master.svg.png'></div>
<p>即便目前分支是某次提交的祖父節點,git會同樣操作。下圖中,在<em>master</em>分支的祖父節點<em>maint</em>分支進行一次提交,產生了<em>1800b</em>。
這樣,<em>maint</em>分支就不再是<em>master</em>分支的祖父節點。此時,<a href='#merge'>合併</a> (或者 <a href='#rebase'>衍合</a>) 是必須的。</p>
<div class="center"><img src='commit-maint.svg.png'></div>
<p>如果想更改一次提交,使用 <code>git commit --amend</code>。git會使用與目前提交相同的父節點進行一次新提交,舊的提交會被取消。</p>
<div class="center"><img src='commit-amend.svg.png'></div>
<p>另一個例子是<a href="#detached">分離HEAD提交</a>,後文講。</p>
<h3 id="checkout">Checkout</h3>
<p>checkout命令用於從歷史提交(或者暫存區域)中拷貝檔到工作目錄,也可用於切換分支。</p>
<p>當給定某個檔案名(或者打開-p選項,或者檔案名和-p選項同時打開)時,git會從指定的提交中拷貝檔到暫存區域和工作目錄。比如,<code>git checkout HEAD~ foo.c</code>會將提交節點<em>HEAD~</em>(即目前提交節點的父節點)中的<code>foo.c</code>複製到工作目錄並且加到暫存區域中。(如果命令中沒有指定提交節點,則會從暫存區域中拷貝內容。)注意目前分支不會發生變化。</p>
<div class="center"><img src='checkout-files.svg.png'></div>
<p>當不指定檔案名,而是給出一個(本地)分支時,那麼<em>HEAD</em>標識會移動到那個分支(也就是說,我們“切換”到那個分支了),然後暫存區域和工作目錄中的內容會和<em>HEAD</em>對應的提交節點一致。新提交節點(下圖中的a47c3)中的所有檔都會被複製(到暫存區域和工作目錄中);只存在於老的提交節點(ed489)中的文件會被刪除;不屬於上述兩者的檔會被忽略,不受影響。</p>
<div class="center"><img src='checkout-branch.svg.png'></div>
<p>如果既沒有指定檔案名,也沒有指定分支名,而是一個標籤、遠端分支、SHA-1值或者是像<em>master~3</em>類似的東西,就得到一個匿名分支,稱作<em>detached HEAD</em>(被分離的<em>HEAD</em>標識)。這樣可以很方便地在歷史版本之間互相切換。比如說你想要編譯1.6.6.1版本的git,你可以執行<code>git checkout v1.6.6.1</code>(這是一個標籤,而非分支名),編譯,安裝,然後切換回另一個分支,比如說<code>git checkout master</code>。然而,當提交操作涉及到“分離的HEAD”時,其行為會略有不同,詳情見在<a href="#detached">下面</a>。</p>
<div class="center"><img src='checkout-detached.svg.png'></div>
<h3 id="detached">HEAD標識處於分離狀態時的提交操作</h3>
<p>當<em>HEAD</em>處於分離狀態(不依附于任一分支)時,提交操作可以正常進行,但是不會更新任何已命名的分支。(你可以認為這是在更新一個匿名分支。)</p>
<div class="center"><img src='commit-detached.svg.png'></div>
<p>一旦此後你切換到別的分支,比如說<em>master</em>,那麼這個提交節點(可能)再也不會被引用到,然後就會被放棄掉了。注意這個命令之後就不會有東西引用<em>2eecb</em>。</p>
<div class="center"><img src='checkout-after-detached.svg.png'></div>
<p>但是,如果你想保存這個狀態,可以用命令<code>git checkout -b <em>name</em></code>來建立一個新的分支。</p>
<div class="center"><img src='checkout-b-detached.svg.png'></div>
<h3 id="reset">Reset</h3>
<p>reset命令把目前分支指向另一個位置,並且有選擇的變動工作目錄和索引。也用來在從歷史倉庫中複製檔到索引,而不動工作目錄。</p>
<p>如果不給選項,那麼目前分支指向到那個提交。如果用<code>--hard</code>選項,那麼工作目錄也更新,如果用<code>--soft</code>選項,那麼都不變。</p>
<div class="center"><img src='reset-commit.svg.png'></div>
<p>如果沒有給出提交點的版本號,那麼預設用<em>HEAD</em>。這樣,分支指向不變,但是索引會回溯到最後一次提交,如果用<code>--hard</code>選項,工作目錄也同樣。</p>
<div class="center"><img src='reset.svg.png'></div>
<p>如果給了檔案名(或者 <code>-p</code>選項), 那麼工作效果和帶檔案名的<a href='#checkout'>checkout</a>差不多,除了索引被更新。</p>
<div class="center"><img src='reset-files.svg.png'></div>
<h3 id="merge">Merge</h3>
<p>merge 命令把不同分支合併起來。合併前,索引必須和目前提交相同。如果另一個分支是目前提交的祖父節點,那麼合併命令將什麼也不做。
另一種情況是如果目前提交是另一個分支的祖父節點,就會導致<em>fast-forward</em>合併。指向只是簡單的移動,並產生一個新的提交。</p>
<div class="center"><img src='merge-ff.svg.png'></div>
<p>否則就是一次真正的合併。預設把目前提交(<em>ed489</em> 如下所示)和另一個提交(<em>33104</em>)以及他們的共同祖父節點(<em>b325c</em>)進行一次<a
href='http://en.wikipedia.org/wiki/Three-way_merge'>三方合併</a>。結果是先保存目前的目錄和索引,然後和父節點<em>33104</em>一起做一次新提交。
</p>
<div class="center"><img src='merge.svg.png'></div>
<h3 id="cherry-pick">Cherry Pick</h3>
<p>cherry-pick命令"複製"一個提交節點並在目前的分支做一次完全一樣的新提交。</p>
<div class="center"><img src='cherry-pick.svg.png'></div>
<h3 id="rebase">Rebase</h3>
<p>衍合是合併命令的另一種選擇。合併把兩個父分支合併進行一次提交,提交歷史不是線性的。衍合在目前分支上重演另一個分支的歷史,提交歷史是線性的。
本質上,這是線性化的自動的 <a href='#cherry-pick'>cherry-pick</a></p>
<div class="center"><img src='rebase.svg.png'></div>
<p>上面的命令都在<em>topic</em>分支中進行,而不是<em>master</em>分支,在<em>master</em>分支上重演,並且把分支指向新的節點。注意舊提交沒有被引用,將被回收。</p>
<p>要限制回滾範圍,使用<code>--onto</code>選項。下面的命令在<em>master</em>分支上重演目前分支從<em>169a6</em>以來的最近幾個提交,即<em>2c33a</em>。</p>
<div class="center"><img src='rebase-onto.svg.png'></div>
<p>同樣有<code>git rebase --interactive</code>讓你更方便的完成一些複雜操作,比如放棄、重排、修改、合併提交。沒有圖片體現這些,細節看這裡:<a
href='http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html#_interactive_mode'>git-rebase(1)</a></p>
<h2 id="technical-notes">技術說明</h2>
<p>檔案內容並沒有真正存儲在索引(<em>.git/index</em>)或者提交物件中,而是以blob的形式分別存儲在資料庫中(<em>.git/objects</em>),並用SHA-1值來校驗。
索引檔用識別碼列出相關的blob檔以及別的資料。對於提交來說,以樹(<em>tree</em>)的形式存儲,同樣用對於的雜湊值識別。樹對應著工作目錄中的資料夾,樹中包含的
樹或者blob物件對應著相應的子目錄和檔案。每次提交都存儲下它的上一級樹的識別碼。</p>
<p>如果用detached HEAD提交,那麼最後一次提交會被the reflog for HEAD引用。但是過一段時間就失效,最終被回收,與<code>git commit --amend</code>或者<code>git
rebase</code>很像。</p>
<hr>
<p>Copyright © 2010,
<a href='mailto:[email protected]'>Mark Lodato</a>.
Traditional Chinese translation © 2015,
<a href='https://github.com/PeterDaveHello'>Peter Dave Hello</a>.
</p>
<p><a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/3.0/us/"><img alt="" src="https://i.creativecommons.org/l/by-nc-sa/3.0/us/80x15.png"/></a> 本著作系採用<a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/3.0/us/">創用CC 姓名標示-非商業性-相同方式分享3.0 美國授權條款</a>授權。</p>
</body>
</html>