forked from blynn/gitmagic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
grandmaster.txt
226 lines (139 loc) · 9.22 KB
/
grandmaster.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
== Git大師技 ==
到現在,你應該有能力查閲 *git help* 頁,並理解几乎所有東西。然而,查明解決特
定問題需要的確切命令可能是乏味的。或許我可以省你點功夫:以下是我過去曾經需要
的一些食譜。
=== 源碼發佈 ===
就我的項目而言,Git完全跟蹤了我想打包並發佈給用戶的檔案。創建一個源碼包,我運
行:
$ git archive --format=tar --prefix=proj-1.2.3/ HEAD
=== 提交變更 ===
對特定項目而言,告訴Git你增加,刪除和重命名了一些檔案很麻煩。而鍵入如下命令會容易的多:
$ git add .
$ git add -u
Git將查找當前目錄的檔案並自己算出具體的情況。除了用第二個add命令,如果你也打
算這時提交,可以運行`git commit -a`。關於如何指定應被忽略的檔案,參見 *git
help ignore* 。
你也可以用一行命令完成以上任務:
$ git ls-files -d -m -o -z | xargs -0 git update-index --add --remove
這裡 *-z* 和 *-0* 選項可以消除包含特殊字元的檔案名引起的不良副作用。注意這個
命令也添加應被忽略的檔案,這時你可能需要加上 `-x` 或 `-X` 選項。
=== 我的提交太大了! ===
是不是忽視提交太久了?痴迷地編碼,直到現在才想起有源碼控制工具這回事?提交一
系列不相關的變更,因為那是你的風格?
別擔心,運行:
$ git add -p
為你做的每次修改,Git將展示給你變動的代碼,並詢問該變動是否應是下一次提交的一
部分。回答“y”或者“n”。也有其他選項,比如延遲決定;鍵入“?”來學習更多。
一旦你滿意,鍵入
$ git commit
來精確地提交你所選擇的變更(階段變更)。確信你沒加上 *-a* 選項,否則Git將提交
所有修改。
如果你修改了許多地方的許多檔案怎麼辦?一個一個地查看變更令人沮喪,心態麻木。
這種情況下,使用 *git add -i* , 它的界面不是很直觀,但更靈活。敲幾個鍵,你可
以一次決定階段或非階段性提交幾個檔案,或查看並只選擇特定檔案的變更。作為另一
種選擇,你還可以運行 *git commit --interactive* ,這個命令會在你操作完後自動
進行提交。
=== 索引:Git的中轉區域 ===
當目前為止,我們已經忽略Git著名的'索引‘概念,但現在我們必須面對它,以解釋上
面發生的。索引是一個臨時中轉區。Git很少在你的項目和它的歷史之間直接倒騰數據。
通常,Git先寫數據到索引,然後拷貝索引中的數據到最終目的地。
例如, *commit -a* 實際上是一個兩步過程。第一步把每個追蹤檔案當前狀態的快照放
到索引中。第二步永久記錄索引中的快照。 沒有 *-a* 的提交只執行第二步,並且只在
運行不知何故改變索引的命令才有意義,比如 *git add* 。
通常我們可以忽略索引並假裝從歷史中直接讀並直接寫。在這個情況下,我們希望更好
地控制,因此我們操作索引。我們放我們變更的一些的快照到索引中,而不是所有的,
然後永久地記錄這個小心操縱的快照。
=== 別丟了你的HEAD ===
HEAD好似一個游標,通常指向最新提交,隨最新提交向前移動。一些Git命令讓你來移動
它。 例如:
$ git reset HEAD~3
將立即向回移動HEAD三個提交。這樣所有Git命令都表現得好似你沒有做那最後三個提交,
然而你的檔案保持在現在的狀態。具體應用參見幫助頁。
但如何回到將來呢?過去的提交對將來一無所知。
如果你有原先Head的SHA1值,那麼:
$ git reset 1b6d
但假設你從來沒有記下呢?別擔心,像這些命令,Git保存原先的Head為一個叫
ORGI_HEAD的標記,你可以安全體面的返回:
$ git reset ORIG_HEAD
=== HEAD捕獵 ===
或許ORG_HEAD不夠。或許你剛認識到你犯了個歷史性的錯誤,你需要回到一個早已忘記
分支上一個遠古的提交。
預設,Git保存一個提交至少兩星期,即使你命令Git摧毀該提交所在的分支。難點是找
到相應的哈希值。你可以查看在.git/objects裡所有的哈希值並嘗試找到你期望的。但
有一個更容易的辦法。
Git把算出的提交哈希值記錄在“.git/logs”。這個子目錄引用包括所有分支上所有活
動的歷史,同時檔案HEAD顯示它曾經有過的所有哈希值。後者可用來發現分支上一些不
小心丟掉提交的哈希值。
The reflog command provides a friendly interface to these log files. Try
命令reflog為訪問這些日誌檔案提供友好的介面,試試
$ git reflog
而不是從reflog拷貝粘貼哈希值,試一下:
$ git checkout "@{10 minutes ago}"
或者撿出後五次訪問過的提交,通過:
$ git checkout "@{5}"
更多內容參見 *git help rev-parse* 的``Specifying Revisions''部分。
你或許期望去為已刪除的提交設置一個更長的保存周期。例如:
$ git config gc.pruneexpire "30 days"
意思是一個被刪除的提交會在刪除30天後,且運行 *git gc* 以後,被永久丟棄。
你或許還想關掉 *git gc* 的自動運行:
$ git config gc.auto 0
在這種情況下提交將只在你手工運行 *git gc* 的情況下才永久刪除。
=== 基于Git構建 ===
依照真正的UNIX風格設計,Git允許其易於用作其他程序的底層組件,比如圖形界面,
Web界面,可選擇的命令行界面,補丁管理工具,導入和轉換工具等等。實際上,一些
Git命令它們自己就是站在巨人肩膀上的腳本。通過一點修補,你可以定製Git適應你的
偏好。
一個簡單的技巧是,用Git內建alias命令來縮短你最常使用命令:
$ git config --global alias.co checkout
$ git config --global --get-regexp alias # 顯示當前別名
alias.co checkout
$ git co foo # 和“git checkout foo”一樣
另一個技巧,在提示符或窗口標題上打印當前分支。調用:
$ git symbolic-ref HEAD
顯示當前分支名。在實際應用中,你可能最想去掉“refs/heads/”並忽略錯誤:
$ git symbolic-ref HEAD 2> /dev/null | cut -b 12-
子目錄 +contrib+ 是一個基于Git工具的寶庫。它們中的一些時時會被提升為官方命令。
在Debian和Ubuntu,這個目錄位於 +/usr/share/doc/git-core/contrib+ 。
一個受歡迎的居民是 +workdir/git-new-workdir+ 。通過聰明的符號連結,這個腳本創
建一個新的工作目錄,其歷史與原來的倉庫共享:
$ git-new-workdir an/existing/repo new/directory
這個新的目錄和其中的檔案可被視為一個克隆,除了既然歷史是共享的,兩者的樹自動
保持同步。不必合併,推入或拉出。
=== 大膽的特技 ===
這些天,Git使得用戶意外摧毀數據變得更困難。但如若你知道你在做什麼,你可以突破
為通用命令所設的防衛保障。
*Checkout*:未提交的變更會導致撿出失敗。銷毀你的變更,並無論如何都checkout一
個指定的提交,使用強制標記:
$ git checkout -f HEAD^
另外,如果你為撿出指定特別路徑,那就沒有安全檢查了。提供的路徑將被不加提示地
覆蓋。如你使用這種方式的檢出,要小心。
*Reset*: 如有未提交變更重置也會失敗。強制其通過,運行:
$ git reset --hard 1b6d
*Branch*: 引起變更丟失的分支刪除會失敗。強制刪除,鍵入:
$ git branch -D dead_branch # instead of -d
類似,通過移動試圖覆蓋分支,如果隨之而來有數據丟失,也會失敗。強制移動分支,鍵入:
$ git branch -M source target # 而不是 -m
不像checkout和重置,這兩個命令延遲數據銷毀。這個變更仍然存儲在.git的子目錄裡,
並且可以通過恢復.git/logs裡的相應哈希值獲取(參見上面 上面“HEAD獵捕”)。默
認情況下,這些數據會保存至少兩星期。
*Clean*: 一些Git命令拒絶執行,因為它們擔心會重裝未納入管理的檔案。如果你確信
所有未納入管理的檔案都是消耗,那就無情地刪除它們,使用:
$ git clean -f -d
下次,那個討厭的命令就會工作!
=== 阻止壞提交 ===
愚蠢的錯誤污染我的倉庫。最可怕的是由於忘記 *git add* 而引起的檔案丟失。較小
的罪過是行末追加空格並引起合併衝突:儘管危害少,我希望浙西永遠不要出現在公開
記錄裡。
不過我購買了傻瓜保險,通過使用一個_鈎子_來提醒我這些問題:
$ cd .git/hooks
$ cp pre-commit.sample pre-commit # 對舊版本Git,先運行chmod +x
現在Git放棄提交,如果檢測到無用的空格或未解決的合併衝突。
對本文檔,我最終添加以下到 *pre-commit* 鈎子的前面,來防止缺魂兒的事:
if git ls-files -o | grep '\.txt$'; then
echo FAIL! Untracked .txt files.
exit 1
fi
幾個git操作支持鈎子;參見 *git help hooks* 。我們早先激活了作為例子的
*post-update* 鈎子,當討論基于HTTP的Git的時候。無論head何時移動,這個鈎子都會
運行。例子腳本post-update更新Git在基于Git並不知曉的傳輸協議,諸如HTTP,通訊時
所需的檔案。