
注意:這裡介紹的指令中有的包含方括号(例如:git add -p [file_name])。在這些例子中,你應該用你自己的數字、辨別符等替代方括号裡的内容,并且去掉方括号。
<a target="_blank"></a>
如果你在指令行環境中運作git指令,每次都手動地逐個輸入指令是一件很無聊的事。為此,你可以花幾分鐘時間配置一下git指令的自動補全功能。
在*nix系統運作下列指令下載下傳自動補全腳本:
cd ~
curl https://raw.github.com/git/git/master/contrib/completion/git-completion.bash -o ~/.git-completion.bash
然後,添加下面的行到你的~/.bash_profile檔案:
if [ -f ~/.git-completion.bash ]; then
. ~/.git-completion.bash
fi
盡管我之前已經提到過,但我還是想再強調一下:如果你想使用完整的git特性,你絕bi應該切換到指令行環境。
你是不是對出現在你git庫裡面的編譯生成檔案(比如.pyc)感到很無語?或者你是不是很厭惡不小心将他們添加到了git?直接看這裡,這裡有一個方法可以讓你告訴git忽略所有這些檔案和目錄。隻需要建立一個名字為.gitignore的檔案,裡面列出你不想要git跟蹤的檔案和目錄。可以用感歎号(!)列出例外情況。
*.pyc
*.exe
my_db_config/
!main.pyc
當事情出了亂子時立馬責怪别人這是人類的天性。如果你的伺服器程式不能正常工作了,要找出罪魁禍首是非常簡單的--隻需要執行git blame。這個指令告訴你檔案裡的每一行的作者是誰,最後改動那一行的送出,以及送出的時間戳。
git blame [file_name]
git blame demonstration
在下面的截圖裡,你可以看到在一個更大的庫裡這個指令的輸出是什麼樣的:
git blame on the atutor repository
在之前的教程裡,我們已經看過了如何使用git log指令。不管怎樣,有3個選項你應該知道。
--oneline - 壓縮每次的送出資訊,隻保留一個縮減的hash值和說明文字,然後把這些都展示在一行裡。
--graph - 這個選項将在左邊畫出一個文字界面的送出曆史圖。如果你隻有一個分支,用這個選項檢視曆史時是沒什麼意義的。
--all - 顯示所有分支曆史。
這是這3個選項合起來使用的效果:
use of git log with all, graph and oneline
假設你送出了一些不需要的東西,然後你進行了hard重置回到之前的狀态。後來,你發現在這個過程中你丢失了其他一些重要的資訊,你想要把這些資訊找回來,或者至少可以檢視一下這些資訊。這就需要git reflog幫忙。
簡單的git log隻能告訴你最近的送出,這個送出的父送出,父送出的父送出,等等。但是git reflog是一個head指向的送出的清單。記住,這個清單依賴于你自己的本地操作環境,它不是庫的一部分,也不包含在push或者merge中。
如果執行git log指令,可以看到送出曆史,這是我的庫的一部分:
project history
但是,git reflog指令顯示了一個被我用hard重置丢掉的送出(b1b0ee9-head@{4}).
git reflog
通常依據特性來送出是一個好的實踐方法,意思是說,每一個送出都隻添加一個特性或者修複一個bug。想一下如果你一次修複了兩個bug或者添加了兩個特性但是都還沒有逐個送出該怎麼辦。這種場景下,你可以将他們一起送出。但是有一個更好的辦法:單獨暫存這些檔案,然後分開送出。
讓我們假設你對一個檔案做了多個更改,然後想讓這些更改分開送出。這時,我們用帶-p的添加指令。
git add -p [file_name]
我們來試試這種用法。我添加了3個新行到file_name,但是我隻想讓第1行和第3行出現在我的送出裡。讓我們看看git diff的輸出是什麼樣的。
changes in repo
然後,我們看看帶-p選項的add指令會發生什麼。
running add with -p
看起來git認為所有的更改都是同一個目的的一部分,是以把他們分組到同一個塊裡。這時,你可以:
輸入 y 暫存塊
輸入 n 不暫存塊
輸入 e 手動編輯塊
輸入 d 退出或者跳轉到下一個檔案
輸入 s 分割塊
在我們這個例子中,我們想把這個塊分割成更小的部分,然後選擇其中一些忽略另外一些。
adding all hunks
如你所見,我們已經逐個添加了第1和第3行,忽略了第2行。你可以看到庫的狀态并且進行一次送出。
repository after selectively adding a file
為了進行核查或者發起一個合并請求(這經常發生在開源項目裡),對代碼進行了修改送出。但在最後代碼被接受之前,你也許會需要修改你的代碼。于是你修改代碼,但是下一次核查的時候又一次需要進行修改。不知不覺中,你就已經有了好幾個送出。理論上你應該用rebase指令把他們合并起來。
git rebase -i head~[number_of_commits]
如果你想合并最後的兩次送出,你應該運作下面的指令。
git rebase -i head~2
一旦你運作這個指令,你将進入一個互動式界面,它将詢問你想要合并哪些送出。你pick(揀選)最近的送出然後squash(合并)舊的送出。
git squash interactive
接着你應該提供一個對新送出的說明。這個過程會重寫你的送出曆史。
adding a commit message
假設你正在修複一個bug或者添加一個特性,突然你被要求展示一下你的工作成果。你現在的工作還沒有完成,不夠進行一次送出。這時,git stash指令可以用來急救一下。stash指令跟蹤你所有的更改,然後把他們儲藏起來以便以後使用。指令如下-
git stash
可以多次儲藏更改,檢視儲藏清單,你可以運作下面的指令:
git stash list
stash list
如果你想取消儲藏,覆寫目前的更改,你可以通過下面的指令使用儲藏:
git stash apply
在最後的這個截圖裡,你可以看到每個儲藏都有一個辨別符,是一個唯一的數字(盡管在這裡我們隻有一個儲藏)。如果你想使用某個儲藏,你在apply指令後面加上這個唯一的辨別符:
git stash apply stash@{2}
after un-stashing changes
盡管reflog是一種檢查丢失送出的方法,大型的庫裡卻不太實用。這個時候,應該用fsck(檔案系統檢查)指令。
git fsck --lost-found
git fsck results
這裡你可以看到一個丢失的送出。你可以通過git show [commit_hash] 檢視送出的更改或者通過運作git merge [commit_hash]指令進行恢複。
git fsck跟reflog指令相比有一個優點。假設你删除了一個遠端分支,然後clone了這個庫。用fsck指令你可以找到并且恢複這個删除的遠端分支。
之前我已經存記下了那些最優雅的git指令。但是目前為止,cherry-pick指令是我最喜歡的git指令,因為它直白的名字和實用的功能!
最簡單的情況下,cherry-pick從另一個分支裡選出單獨的一個送出,然後合并到目前分支。如果你正并行工作在兩個或者更多的分支上,你也許會發現一個存在于所有分支上的bug。如果你解決了一個分支上的這個bug,你可以揀選這個對應的送出應用到其他分支上,而不會弄亂其他檔案或者送出。
讓我們來考慮一個可以使用這個指令的場景。我有兩個分支,我想揀選b20fd14: cleaned junk這個送出到另一個分支上。
before cherry pick
我切換到想要應用這個揀選出來的送出的分支,然後運作下面的指令:
git cherry-pick [commit_hash]
after cherry pick
盡管這次我們很幹淨的用了cherry-pick指令,但你應該知道這個指令經常會引起沖突,是以請小心使用。
到了這裡,我們結束了這個能使你git能力提升一個級别的清單。git是最好的版本控制器,它能完成你能想象到的任何事情。是以,經常試着用git挑戰你自己。一不小心你就會學到很多新東西。
原文釋出時間:2014-07-25
本文來自雲栖合作夥伴“linux中國”