給 Git 中級使用者的 25 個小貼士

kinolee發表於2015-02-03

Andy Jeffries 給 Git 中級使用者總結分享的 25 個小貼士。你不需要去做大量搜尋,或許這些小貼士對你就很有幫助的。

我從開始使用git到現在已經差不多18個月了,以為自己已經很懂git了。直到我看到github上 Scott Chacon在 LVS, a supplier/developer of betting/gaming software 上的教學,第一天就受益匪淺。

作為一個很享受git的人,我想要分享從各種社群學到的實用經驗,讓大家不需要花費過多的功夫就能找到答案。

基本技巧

1.安裝後的第一步

安裝git後,第一件事你需要設定你的名字和郵箱,因為每次提交都需要這些資訊。

2.是基於指標的

git上的所有東西都是儲存在檔案裡的,當你建立一次提交時,它會建立一個包含你的提交資訊和相關資料(名字,郵箱,日期/時間、上一次提交等等)的檔案並連線一個樹檔案,而這個樹檔案包含了物件列表或者其他樹。這上面的物件或者blob檔案就是這次提交的實際內容(你可以認為這也是一個檔案,儘管並沒有儲存在物件裡而是儲存在樹中)。所有的檔案都以經過SHA-1計算後的檔名(譯者注:經過SHA-1計算後的數,即git中的版本號)儲存在上面。

從這裡可以看出,分支和標籤都是包含一個指向這次提交的sha-1數(版本號)簡單的檔案,這樣使用引用會變得更快和更靈活,建立一個新的分支是就像建立檔案一樣簡單,SHA – 1數(版本號)也會引用你這個分支的提交。當然,如果你使用GIT命令列工具(或者GUI)你將無法接觸這些。但真的很簡單。

你可能聽說過HEAD引用,這是一個指向你當前提交的內容的SHA-1 數(版本號)的指標。如果你正在解決合併衝突,使用HEAD不會對你的特定分支有任何改動只會指向你當前的分支。

所有分支的指標都儲存在 .git/refs/heads,HEAD指標儲存在.git/HEAD,標籤則儲存在 .git/refs/tags,有時間就去看看吧。

3.  兩個母體(Parent),當然!

當我們在日誌檔案中檢視合併提交資訊,你會看到兩個母體,第一個母體是正在進行的分支,第二個是你要合併的分支。

4.合併衝突

現在,我發現有合併衝突並解決了它,這是一件在我們編輯檔案時很正常的事。將 <<<<, ====, >>>> 這些標記移除後,並儲存你想要儲存的程式碼。有些時候在程式碼被直接替代之前,能看到衝突是件挺不錯的事。比如在兩個衝突的分支變動之前,可以用這樣的命令方式:

如果是二進位制檔案(binary),區別這些檔案並不容易。通常你會檢視每個二進位制檔案的版本,再決定使用哪個(或者在二進位制檔案編輯器中手動複製),並將其推送至特定的分支。(比如你要合併master和feature132)

另一個方法就是在git中cat檔案,你可以將其命名為另一個檔名,然後將你決定的那個檔案改為正確的檔名:

更新:感謝carls在原博評論中提醒我,可以使用 “git checkout —ours flash/foo.fla” 和“git checkout —theirs flash/foo.fla” 在不用考慮你需要合併的分支來檢查指定版本,就我個人而言,我喜歡更明確的方法,但這也是一個選擇…

記住,解決完合併衝突後要新增檔案。(我之前就犯過這樣的錯誤)

服務,分支和標註

5. 遠端服務

Git有一個非常強大的特性,就是可以有多個遠端服務端(以及你執行的一個本地倉庫)。你不需要總是進行訪問,你可以有多個服務端並能從其中一個(合併工作)讀取再寫入另一個。新增一個遠端服務端很簡單:

如果你想檢視遠端服務端的資訊你可以:

你總是能看到本地分支和遠端分支不同的地方:

你同樣也能看到遠端分支上沒有的HEAD指標的改動:

6. Tagging  標籤

在Git中有兩種型別的標註:輕量級標註和註釋型標註。

記住第二個是Git的指標基礎,兩者區別很簡單,輕量級標註是簡單命名提交的指標,你可以將其指向另一個提交。註釋型標註是一個有資訊和歷史並指向標註物件的名字指標,它有著自己的資訊,如果需要的話,可以進行GPG標記。

建立兩種型別的標籤很簡單(其中一個命令列有改動)

7. Creating Branches 建立分支

在git中建立分支是件非常簡單的事情(非常快並只需要不到100byte的檔案大小)。建立新分支並切換到該分支,通常是下面這樣的:

當然,如果你想切換到該分支,最直接的方式是使用這樣一條命令:

如果你想要重新命名本地分支,也很簡單:

更新:或者你(Brian Palmer在原博的評論中指出的)可以使用 -m來切換到“git branch”(就像Mike指出,如果你只需要一個特定的分支,就可以重新命名當前分支)

8.合併分支

以後你可能回想合併你的變動,有兩種方式可以做到這一點:

merge和rebase的區別是,merge會嘗試解決改動並建立的新的提交來融合他們。rebase則是將從你最後一次從另一個分支分離之後的改動併入,並直接沿用另一個分支的head指標。儘管如此,在你往遠端伺服器上推送分支之前,不要使用rebase。這會讓你混亂。

如果你不能確定哪個分支(哪些需要合併,哪些需要移除)。這裡有兩個git分支切換方式來幫助你:

9.遠端分支

如果你想將本地分支放置遠端服務端,你可以用這條命令進行推送:

如果你想要從服務端刪除分支:

如果你想要檢視遠端分支的狀態:

這將列出那些曾經存在而現在不存在的遠端分支,這將幫助你輕易地刪除你本地多餘的分支。

最後,如果本地追蹤遠端分支,常用方式是:

儘管這樣,Git的新版本將啟動自動追蹤,如果你使用-b來checkout:

Storing Content in Stashes, Index and File System 在stash儲存內容、索引和檔案系統

10. Stashing

在Git中你可以將當前的工作區的內容儲存到Git棧中並從最近的一次提交中讀取相關內容。以下是個簡單的例子:

很多人推薦使用git stash apply來代替pop。這樣子恢復後儲存的stash內容並不會刪除,而‘pop’恢復的同時把儲存的stash內容也刪了 ,使用git stash apply 就可以移除任何棧中最新的內容。

git可以自動建立基於當前提交資訊的指令,如果你更喜歡使用通用的資訊(相當於不會對前一次提交做任何改動)

如果你想使用某個stash(不一定是最後一個),你可以這樣將其列表顯示出來然後使用:

11.新增互動

在svn中,如果你檔案有了改動之後,然後會提交所有改動的檔案,在 Git中為了能更好的提交特定的檔案或者某個補丁,你需要在互動模式提交選擇提交的檔案的內容。

這是基於選單的互動式提示符。您可以使用命令前的數字或進入高亮字母(如果你有高亮輸入)模式。常用形式是,輸入你想執行的操作前的數字。(你可以像1或1 – 4或2、4、7的格式來執行命令)。

如果你想進入補丁模式(在互動模式中輸入p或5),同樣也可以這樣操作:

如你所見,你將在選擇新增改動的那部分檔案的底部獲得一些選項。此外,使用“?”會說明這個選項。

12. 檔案系統中的儲存/檢索

有些專案(比如Git自己的專案)需要直接在Git的檔案系統中新增額外的並不想被檢查的檔案。

讓我們開始在Git中儲存隨機檔案

比如資料庫中的物件,如果你不想讓一些物件被垃圾回收,最簡單的方式是給它加標籤:

在這裡我們設定myfile的標籤,當我們需要檢索該檔案時可以這樣:

這對開發者可能需要的但是並不想每次都去檢查的有用檔案(密碼,gpg鍵等等)很管用(特別是在生產過程中)。

Logging and What Changed? 記錄日誌和什麼改變了?

13. 檢視日誌

在不使用“git log”的情況下,你不能檢視你長期的最近提交內容,但是,仍然有一些更便於你使用的方法,比如,你可以這樣檢視單次提交變動的內容:

或者你只看檔案變動的摘要:

這個很讚的別名,可以讓你在一行命令下簡化提交,並展示不錯的圖形化分支。

14.在日誌中查詢

如果你想根據指定的作者查詢:

更新:感謝 Johannes的評論,解除了我的一些困惑,

或者你可以搜尋你提交資訊的內容:

這些強大的指令被稱為pickaxe指令,來檢查被移除或新增特定塊的內容(比如,當他們第一次出現或者被移除),新增任何一行內容都會告訴你(但是並不包括那行內容剛剛被改動)

如果你改動一個特定的檔案會怎麼樣?如:lib/foo.rb

如果你有feature/132 和ferature/145這兩個分支,並想檢視這些不在master上的分支內容。( ^ 符號是意味著非)

你同樣可以使用ActiveSupport風格的日期來縮短時間範圍:

預設會使用OR來合併查詢,但你也可改用AND(如果你有不止一個條件)

15.選擇試圖/改動的之前的版本。

根據你知道的資訊,可以按照以下方式來找到之前的版本:

注意:不像前一部分所說,在最後的插入符號意味著提交的父類,在前面的插入符號意味著不在這個分支上

16. 選擇一個方式

最簡單的方式:

你也可以省略[new],這樣將預設使用當前的HEAD指標。

Rewinding Time & Fixing Mistakes 回滾和修復錯誤

17.重置更改

如果你沒有提交你可以簡單的撤銷改動:

通常我們使用”unstage“這樣的別名來代替:

如果你已經提交了,有兩種情況:如果是最後一次提交你僅僅需要amend:

這將不執行最後一次提交,恢復你原來的內容,提交資訊將預設為你下次提交的資訊。

如果你已經提交過不止一次了並且想完全回到之前那個記錄,你可以重置分支回到指定的時間。

如果你想將分支回滾但想要SHA1數(版本號)不一樣(也許你可以將分支的HEAD指向另一個分支,或者之後的提交),你可以通過如下方式:

實際上還有個更快的方式(這樣並不會改變你的檔案複製內容,並回歸到第一次FOO的狀態並指向SHA)

18. 提交至錯誤的分支

好吧,假定你提交到master上了,但是你想提交的是名為experimental的主題分支上,如果想移除這個改動,你可以在當前建立一個分支並將head指標回滾再檢查新的分支

如果你在分支的分支的分支進行了改動將會很麻煩,那麼你需要做的就是在其他處進行分支rebase改動

19. rebase的互動

這是個很不錯的功能,我曾看過演示但一直以來並沒有真正搞懂,現在我知道了,非常簡單。假如你進行了三次提交,但是你想重新編輯它們(或者結合它們)。

然後你讓你的編輯器開啟一些指令,你需要做的就是修改指令來選擇/squash/編輯(或刪除)/提交和儲存/退出,編輯完使用git rebase —continue 來通過你的每一個指令。

如果你選擇編輯一個,它將離開你的提交狀態,所以你需要使用git commit -amend來編輯它。

注意:不要在rebase的時候提交——只能新增了之後再使用—continue, —skip 或—abort.

20. 清除

如果你在分支中提交了一些內容(也許是一些SVN上老的資原始檔)並想從歷史記錄中完全移除,可以這樣:

如果你已經將其推送至origin,並提交了一些垃圾內容,你同樣可以推送之前在本地系統這樣做:

Miscellaneous Tips 各種各樣的技巧

21.你看過的前面的引用

如果你知道你之前看到的SHA-1數(版本號),並需要進行一些重置/回滾,可以使用reflog命令查詢最近檢視的sha – 1數(版本號):

22. 分支命名

一個有趣的小技巧,不要忘記分支名不僅僅限於a-z和0-9,在名字中使用/和.用於命名偽名稱空間和版本控制,也是個不錯的主意,例如:

23. 找到Dunnit

找出誰在一個檔案中改變了一行程式碼,簡單的命令是:

有時候是上一個檔案發生了變動(如果你合併兩個檔案,或者你已經轉移到一個函式),這樣你就可以使用:

有時候需要通過點選來追蹤來回的變動,這裡有一個不錯的內建gui:

24. 資料庫維護

通常Git並不需要過多的維護,它幾乎可以自己搞定,儘管如此你也可以檢視資料庫使用的統計:

如果數值過高你可以選擇將你的克隆垃圾回收。這不會影響你推送內容或其他人,但它可以讓你的命令執行的更快,並使用更少的空間:

它也可以在執行時進行一致性檢驗:

你可以在後面新增-auto 引數(如果你在伺服器跑定時任務時),這在統計資料時是必須的。

當檢查的結果是“dangling”或“unreachable”這樣的是正常的,這通常是回滾和rebase的結果。 得到“missing” 或 “sha1 mismatch” 這樣的結果是不好的…你需要得到專業的幫助!

25. 恢復失去的分支

如果你意外的刪除一個分支,可以重新建立它:

你可以使用git reflog檢視你最近訪問過的SHA1數(版本號)

另一個方式就是使用 git fsck —lost-found ,懸空物件(dangling commit )是就是失去HEAD指標的提交,(刪除的分支只是失去了HEAD指標成為懸空物件

Done!完成!

這篇是我寫過最長的博文,希望大家能從此文中獲益,如果你有所收益或是有任何問題都可以在評論中告訴我!

相關文章