forked from blynn/gitmagic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
branch.txt
236 lines (150 loc) · 10.4 KB
/
branch.txt
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
236
== 分支巫術 ==
即時分支合併是Git最給力的殺手鐧。
*問題* :外部因素要求必須切換場景。在發佈版本中突然蹦出個嚴重缺陷。某個特性完
成的截至日期就要來臨。在項目關鍵部分可以提供幫助的一個開發正打算離職。所有情
況逼迫你停下所有手頭工作,全力撲到到這個完全不同的任務上。
打斷思維的連續性會使你的生產力大大降低,並且切換上下文也更麻煩,更大的損失。
使用中心版本控制我們必須從中心伺服器下載一個新的工作拷貝。分散式系統的情況就
好多了,因為我們能夠在本地克隆所需要的版本。
但是克隆仍然需要拷貝整個工作目錄,還有直到給定點的整個歷史記錄。儘管Git使用文
件共享和硬連結減少了花費,項目檔案自身還是必須在新的工作目錄裡重建。
*方案* :Git有一個更好的工具對付這種情況,比克隆快多了而且節省空間: *git
branch* 。
使用這個魔咒,目錄裡的檔案突然從一個版本變到另一個。除了只是在歷史記錄裡上跳
下竄外,這個轉換還可以做更多。你的檔案可以從上一個發佈版變到實驗版本到當前開
發版本到你朋友的版本等等。
=== 老闆鍵 ===
曾經玩過那樣的遊戲嗎?按一個鍵(“老闆鍵”),屏幕立即顯示一個電子表格或別的?
那麼如果老闆走進辦公室,而你正在玩遊戲,就可以快速將遊戲藏起來。
在某個目錄:
$ echo "I'm smarter than my boss" > myfile.txt
$ git init
$ git add .
$ git commit -m "Initial commit"
我們已經創建了一個Git倉庫,該倉庫記錄一個包含特定信息的檔案。現在我們鍵入:
$ git checkout -b boss # 之後似乎沒啥變化
$ echo "My boss is smarter than me" > myfile.txt
$ git commit -a -m "Another commit"
看起來我們剛剛只是覆蓋了原來的檔案並提交了它。但這是個錯覺。鍵入:
$ git checkout master # 切到檔案的原先版本
嘿真快!這個檔案就恢復了。並且如果老闆決定窺視這個目錄,鍵入:
$ git checkout boss # 切到適合老闆看的版本
你可以在兩個版本之間相切多少次就切多少次,而且每個版本都可以獨立提交。
=== 骯髒的工作 ===
[[branch]]
比如你正在開發某個特性,並且由於某種原因,你需要回退三個版本,臨時加進幾行打
印語句來,來看看一些東西是如何工作的。那麼:
$ git commit -a
$ git checkout HEAD~3
現在你可以到處加醜陋的臨時代碼。你甚至可以提交這些改動。當你做完的時候,
$ git checkout master
來返回到你原來的工作。看,所有未提交變更都結轉了。
如果你後來想保存臨時變更怎麼辦?簡單:
$ git checkout -b dirty
只要在切換到主分支之前提交就可以了。無論你什麼時候想回到髒的變更,只需鍵入:
$ git checkout dirty
我們在前面章節討論加載舊狀態的時候,曾經接觸過這個命令。最終我們把故事說全:
檔案改變成請求的狀態,但我們必須離開主分支。從現在開始的任何提交都會將你的文
件提交到另一條不同的路,這個路可以之後命名。
換一個說法,在checkout一個舊狀態之後,Git自動把你放到一個新的,未命名的分支,
這個分支可以使用 *git checkout -b* 來命名和保存。
=== 快速修訂 ===
你正在做某件事的當間,被告知先停所有的事情,去修理一個新近發現的臭蟲,這個臭
蟲在提交 `1b6d...`:
$ git commit -a
$ git checkout -b fixes 1b6d
那麼一旦你修正了這個臭蟲:
$ git commit -a -m "Bug fixed"
$ git checkout master
並可以繼續你原來的任務。你甚至可以“合併”到最新修訂:
$ git merge fixes
=== 合併 ===
一些版本控制系統,創建分支很容易,但把分支合併回來很難。使用Git,合併簡直是家
常便飯,以至于甚至你可能對其發生沒有察覺。
我們很久之前就遇到合併了。 *pull* 命令取出提交併合並它們到你的當前分支。如果
你沒有本地變更,那這個合併就是一個“快進”,相當於中心式版本控制系統裡的一個
弱化的獲取最新版本操作。但如有本地變更,Git將自動合併,並報告任何衝突。
通常,一個提交只有一個“父提交”,也叫前一個提交。合併分支到一起產生一個至少
有兩個父的提交。這就引出了問題: `HEAD~10` 真正指哪個提交?一個提交可能有多個
父,那我們跟哪個呢?
原來這個表示每次選擇第一個父。這是可取的,因為在合併時候當前分支成了第一個父;
多數情況下我們只關注我們在當前分支都改了什麼,而不是從其他分支合併來的變更。
你可以用插入符號來特別指定父。比如,顯示來自第二個父的日誌:
$ git log HEAD^2
你可以忽略數字以指代第一個父。比如,顯示與第一個父的差別:
$ git diff HEAD^
你可以結合其他類型使用這個記號。比如:
$ git checkout 1b6d^^2~10 -b ancient
開始一個新分支 ``ancient'' ,表示第一個父的第二個父的倒數第十次提交的狀態。
=== 不間斷工作流 ===
經常在硬件項目裡,計劃的第二步必須等第一步完成才能開始。待修的汽車傻等在車庫
裡,直到特定的零件從工廠運來。一個原型在其可以構建之前,可能苦等晶片成型。
軟件項目可能也類似。新功能的第二部分不得不等待,直到第一部分發佈並通過測試。
一些項目要求你的代碼需要審批才能接受,因此你可能需要等待第一部分得到批准,才
能開始第二部分。
多虧了無痛分支合併,我們可以不必遵循這些規則,在第一部分正式準備好前開始第二
部分的工作。假設你已經將第一部分提交並發去審批,比如說你現在在主分支。那麼分
岔:
$ git checkout -b part2
接下來,做第二部分,隨時可以提交變更。只要是人就可能犯錯誤,經常你將回到第一
部分在修修補補。如果你非常幸運,或者超級棒,你可能不必做這幾行:
$ git checkout master # 回到第一部分
$ 修復問題
$ git commit -a # 提交變更
$ git checkout part2 # 回到第二部分
$ git merge master # 合併這些改動
最終,第一部分獲得批准:
$ git checkout master # 回到第一部分
$ submit files # 對世界發佈
$ git merge part2 # 合併第二部分
$ git branch -d part2 # 刪除分支“part2”
現在你再次處在主分支,第二部分的代碼也在工作目錄。
很容易擴展這個技巧,應用到任意數目的部分。它也很容易追溯分支:假如你很晚才意
識到你本應在7次提交前就創建分支。那麼鍵入:
$ git branch -m master part2 # 重命名“master”分支為“part2”。
$ git branch master HEAD~7 # 以七次前提交建一個新的“master”。
分支 `master` 只有第一部分內容,其他內容在分支 `part2` 。 我們現在後一個分支;
我們創建了 `master` 分支還沒有切換過去,因為我們想繼續工作在 `part2` 。這是不
尋常的。直到現在,我們已經在創建之後切換到分支,如:
$ git checkout HEAD~7 -b master # 創建分支,並切換過去。
=== 重組雜亂 ===
或許你喜歡在同一個分支下完成工作的方方面面。你想為自己保留工作進度並希望其他
人只能看到你仔細整理過後的提交。開啟一對分支:
$ git branch sanitized # 為乾淨提交創建分支
$ git checkout -b medley # 創建並切換分支以進去工作
接下來,做任何事情:修臭蟲,加特性,加臨時代碼,諸如此類,經常按這種方式提交。
然後:
$ git checkout sanitized
$ git cherry-pick medley^^
應用分支 ``medley'' 的祖父提交到分支 ``sanitized'' 。通過合適的挑選(像選櫻桃
那樣)你可以構建一個只包含成熟代碼的分支,而且相關的提交也組織在一起。
=== 管理分支 ===
列出所有分支:
$ git branch
預設你從叫 ``master'' 的分支開始。一些人主張別碰“master”分支,而是創建你自
己版本的新分支。
選項 *-d* 和 *-m* 允許你來刪除和移動(重命名)分支。參見 *git help branch* 。
分支``master'' 是一個有用的慣例。其他人可能假定你的倉庫有一個叫這個名字的分
支,並且該分支包含你項目的官方版本。儘管你可以重命名或抹殺 ``master'' 分支,
你最好還是尊重這個約定。
=== 臨時分支 ===
很快你會發現你經常會因為一些相似的原因創建短期的分支:每個其它分支只是為了保
存當前狀態,那樣你就可以直接跳到較老狀態以修復高優先順序的臭蟲之類。
可以和電視的換台做類比,臨時切到別的頻道,來看看其它台那正放什麼。但並不是簡
單地按幾個按鈕,你不得不創建,檢出,合併,以及刪除臨時分支。幸運的是,Git已經
有了和電視機遙控器一樣方便的快捷方式:
$ git stash
這個命令保存當前狀態到一個臨時的地方(一個隱藏的地方)並且恢復之前狀態。你的
工作目錄看起來和你開始編輯之前一樣,並且你可以修復臭蟲,引入之前變更等。當你
想回到隱藏狀態的時候,鍵入:
$ git stash apply # 你可能需要解決一些衝突
你可以有多個隱藏,並用不同的方式來操作他們。參見 *git help slash* 。也許你已
經猜到,Git維護在這個場景之後的分支以執行魔法技巧.
=== 按你希望的方式工作 ===
你可能猶疑于分支是否值得一試。畢竟,克隆也几乎一樣快,並且你可以用 *cd* 來在
彼此之間切換,而不是用Git深奧的命令。
考慮一下瀏覽器。為什麼同時支持多標籤和多窗口?因為允許兩者同時接納納了多種風
格的用戶。一些用戶喜歡只保持一個打開的窗口,然後用標籤瀏覽多個網頁。一些可能
堅持另一個極端:任何地方都沒有標籤的多窗口。一些喜好處在兩者之間。
分支類似你工作目錄的標籤,克隆類似打開的瀏覽器新窗口。這些是本地操作很快,那
為什麼不試着找出最適合你的組合呢?Git讓你按你確實所希望的那樣工作。