如第一章所言,用git config
配置 Git,要做的第一件事就是設(shè)置名字和郵箱地址:
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
從現(xiàn)在開始,你會(huì)了解到一些類似以上但更為有趣的設(shè)置選項(xiàng)來自定義 Git。
先過一遍第一章中提到的 Git 配置細(xì)節(jié)。Git 使用一系列的配置文件來存儲(chǔ)你定義的偏好,它首先會(huì)查找/etc/gitconfig
文件,該文件含有 對(duì)系統(tǒng)上所有用戶及他們所擁有的倉(cāng)庫(kù)都生效的配置值(譯注:gitconfig是全局配置文件), 如果傳遞--system
選項(xiàng)給git config
命令, Git 會(huì)讀寫這個(gè)文件。
接下來 Git 會(huì)查找每個(gè)用戶的~/.gitconfig
文件,你能傳遞--global
選項(xiàng)讓 Git讀寫該文件。
最后 Git 會(huì)查找由用戶定義的各個(gè)庫(kù)中 Git 目錄下的配置文件(.git/config
),該文件中的值只對(duì)屬主庫(kù)有效。 以上闡述的三層配置從一般到特殊層層推進(jìn),如果定義的值有沖突,以后面層中定義的為準(zhǔn),例如:在.git/config
和/etc/gitconfig
的較量中, .git/config
取得了勝利。雖然你也可以直接手動(dòng)編輯這些配置文件,但是運(yùn)行git config
命令將會(huì)來得簡(jiǎn)單些。
Git 能夠識(shí)別的配置項(xiàng)被分為了兩大類:客戶端和服務(wù)器端,其中大部分基于你個(gè)人工作偏好,屬于客戶端配置。盡管有數(shù)不盡的選項(xiàng),但我只闡述 其中經(jīng)常使用或者會(huì)對(duì)你的工作流產(chǎn)生巨大影響的選項(xiàng),如果你想觀察你當(dāng)前的 Git 能識(shí)別的選項(xiàng)列表,請(qǐng)運(yùn)行
$ git config --help
git config
的手冊(cè)頁(yè)(譯注:以man命令的顯示方式)非常細(xì)致地羅列了所有可用的配置項(xiàng)。
Git默認(rèn)會(huì)調(diào)用你的環(huán)境變量editor定義的值作為文本編輯器,如果沒有定義的話,會(huì)調(diào)用Vi來創(chuàng)建和編輯提交以及標(biāo)簽信息, 你可以使用core.editor
改變默認(rèn)編輯器:
$ git config --global core.editor emacs
現(xiàn)在無論你的環(huán)境變量editor被定義成什么,Git 都會(huì)調(diào)用Emacs編輯信息。
如果把此項(xiàng)指定為你系統(tǒng)上的一個(gè)文件,當(dāng)你提交的時(shí)候, Git 會(huì)默認(rèn)使用該文件定義的內(nèi)容。 例如:你創(chuàng)建了一個(gè)模板文件$HOME/.gitmessage.txt
,它看起來像這樣:
subject line
what happened
[ticket: X]
設(shè)置commit.template
,當(dāng)運(yùn)行git commit
時(shí), Git 會(huì)在你的編輯器中顯示以上的內(nèi)容, 設(shè)置commit.template
如下:
$ git config --global commit.template $HOME/.gitmessage.txt
$ git commit
然后當(dāng)你提交時(shí),在編輯器中顯示的提交信息如下:
subject line
what happened
[ticket: X]
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: lib/test.rb
#
~
~
".git/COMMIT_EDITMSG" 14L, 297C
如果你有特定的策略要運(yùn)用在提交信息上,在系統(tǒng)上創(chuàng)建一個(gè)模板文件,設(shè)置 Git 默認(rèn)使用它,這樣當(dāng)提交時(shí),你的策略每次都會(huì)被運(yùn)用。
core.pager指定 Git 運(yùn)行諸如log
、diff
等所使用的分頁(yè)器,你能設(shè)置成用more
或者任何你喜歡的分頁(yè)器(默認(rèn)用的是less
), 當(dāng)然你也可以什么都不用,設(shè)置空字符串:
$ git config --global core.pager ''
這樣不管命令的輸出量多少,都會(huì)在一頁(yè)顯示所有內(nèi)容。
如果你要?jiǎng)?chuàng)建經(jīng)簽署的含附注的標(biāo)簽(正如第二章所述),那么把你的GPG簽署密鑰設(shè)置為配置項(xiàng)會(huì)更好,設(shè)置密鑰ID如下:
$ git config --global user.signingkey <gpg-key-id>
現(xiàn)在你能夠簽署標(biāo)簽,從而不必每次運(yùn)行git tag
命令時(shí)定義密鑰:
$ git tag -s <tag-name>
正如第二章所述,你能在項(xiàng)目庫(kù)的.gitignore
文件里頭用模式來定義那些無需納入 Git 管理的文件,這樣它們不會(huì)出現(xiàn)在未跟蹤列表, 也不會(huì)在你運(yùn)行git add
后被暫存。然而,如果你想用項(xiàng)目庫(kù)之外的文件來定義那些需被忽略的文件的話,用core.excludesfile
通知 Git 該文件所處的位置,文件內(nèi)容和.gitignore
類似。
該配置項(xiàng)只在 Git 1.6.1及以上版本有效,假如你在Git 1.6中錯(cuò)打了一條命令,會(huì)顯示:
$ git com
git: 'com' is not a git-command. See 'git --help'.
Did you mean this?
commit
如果你把help.autocorrect
設(shè)置成1(譯注:?jiǎn)?dòng)自動(dòng)修正),那么在只有一個(gè)命令被模糊匹配到的情況下,Git 會(huì)自動(dòng)運(yùn)行該命令。
Git能夠?yàn)檩敵龅侥憬K端的內(nèi)容著色,以便你可以憑直觀進(jìn)行快速、簡(jiǎn)單地分析,有許多選項(xiàng)能供你使用以符合你的偏好。
Git會(huì)按照你需要自動(dòng)為大部分的輸出加上顏色,你能明確地規(guī)定哪些需要著色以及怎樣著色,設(shè)置color.ui
為true來打開所有的默認(rèn)終端著色。
$ git config --global color.ui true
設(shè)置好以后,當(dāng)輸出到終端時(shí),Git 會(huì)為之加上顏色。其他的參數(shù)還有false和always,false意味著不為輸出著色,而always則表明在任何情況下都要著色,即使 Git 命令被重定向到文件或管道。Git 1.5.5版本引進(jìn)了此項(xiàng)配置,如果你擁有的版本更老,你必須對(duì)顏色有關(guān)選項(xiàng)各自進(jìn)行詳細(xì)地設(shè)置。
你會(huì)很少用到color.ui = always
,在大多數(shù)情況下,如果你想在被重定向的輸出中插入顏色碼,你能傳遞--color
標(biāo)志給 Git 命令來迫使它這么做,color.ui = true
應(yīng)該是你的首選。
color.*
想要具體到哪些命令輸出需要被著色以及怎樣著色或者 Git 的版本很老,你就要用到和具體命令有關(guān)的顏色配置選項(xiàng),它們都能被置為true
、false
或always
:
color.branch
color.diff
color.interactive
color.status
除此之外,以上每個(gè)選項(xiàng)都有子選項(xiàng),可以被用來覆蓋其父設(shè)置,以達(dá)到為輸出的各個(gè)部分著色的目的。例如,讓diff輸出的改變信息以粗體、藍(lán)色前景和黑色背景的形式顯示:
$ git config --global color.diff.meta “blue black bold”
你能設(shè)置的顏色值如:normal、black、red、green、yellow、blue、magenta、cyan、white,正如以上例子設(shè)置的粗體屬性,想要設(shè)置字體屬性的話,可以選擇如:bold、dim、ul、blink、reverse。
如果你想配置子選項(xiàng)的話,可以參考git config
幫助頁(yè)。
雖然 Git 自己實(shí)現(xiàn)了diff,而且到目前為止你一直在使用它,但你能夠用一個(gè)外部的工具替代它,除此以外,你還能用一個(gè)圖形化的工具來合并和解決沖突從而不必自己手動(dòng)解決。有一個(gè)不錯(cuò)且免費(fèi)的工具可以被用來做比較和合并工作,它就是P4Merge(譯注:Perforce圖形化合并工具),我會(huì)展示它的安裝過程。
P4Merge可以在所有主流平臺(tái)上運(yùn)行,現(xiàn)在開始大膽嘗試吧。對(duì)于向你展示的例子,在Mac和Linux系統(tǒng)上,我會(huì)使用路徑名,在Windows上,/usr/local/bin
應(yīng)該被改為你環(huán)境中的可執(zhí)行路徑。
下載P4Merge:
http://www.perforce.com/perforce/downloads/component.html
首先把你要運(yùn)行的命令放入外部包裝腳本中,我會(huì)使用Mac系統(tǒng)上的路徑來指定該腳本的位置,在其他系統(tǒng)上,它應(yīng)該被放置在二進(jìn)制文件p4merge
所在的目錄中。創(chuàng)建一個(gè)merge包裝腳本,名字叫作extMerge
,讓它帶參數(shù)調(diào)用p4merge
二進(jìn)制文件:
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/p4merge.app/Contents/MacOS/p4merge $*
diff包裝腳本首先確定傳遞過來7個(gè)參數(shù),隨后把其中2個(gè)傳遞給merge包裝腳本,默認(rèn)情況下, Git 傳遞以下參數(shù)給diff:
path old-file old-hex old-mode new-file new-hex new-mode
由于你僅僅需要old-file
和new-file
參數(shù),用diff包裝腳本來傳遞它們吧。
$ cat /usr/local/bin/extDiff
#!/bin/sh
[ $# -eq 7 ] && /usr/local/bin/extMerge "$2" "$5"
確認(rèn)這兩個(gè)腳本是可執(zhí)行的:
$ sudo chmod +x /usr/local/bin/extMerge
$ sudo chmod +x /usr/local/bin/extDiff
現(xiàn)在來配置使用你自定義的比較和合并工具吧。這需要許多自定義設(shè)置:merge.tool
通知 Git 使用哪個(gè)合并工具;mergetool.*.cmd
規(guī)定命令運(yùn)行的方式;mergetool.trustExitCode
會(huì)通知 Git 程序的退出是否指示合并操作成功;diff.external
通知 Git 用什么命令做比較。因此,你能運(yùn)行以下4條配置命令:
$ git config --global merge.tool extMerge
$ git config --global mergetool.extMerge.cmd \
'extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'
$ git config --global mergetool.trustExitCode false
$ git config --global diff.external extDiff
或者直接編輯~/.gitconfig
文件如下:
[merge]
tool = extMerge
[mergetool "extMerge"]
cmd = extMerge \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"
trustExitCode = false
[diff]
external = extDiff
設(shè)置完畢后,運(yùn)行diff命令:
$ git diff 32d1776b1^ 32d1776b1
命令行居然沒有發(fā)現(xiàn)diff命令的輸出,其實(shí),Git 調(diào)用了剛剛設(shè)置的P4Merge,它看起來像圖7-1這樣:
Figure 7-1. P4Merge.
當(dāng)你設(shè)法合并兩個(gè)分支,結(jié)果卻有沖突時(shí),運(yùn)行git mergetool
,Git 會(huì)調(diào)用P4Merge讓你通過圖形界面來解決沖突。
設(shè)置包裝腳本的好處是你能簡(jiǎn)單地改變diff和merge工具,例如把extDiff
和extMerge
改成KDiff3,要做的僅僅是編輯extMerge
腳本文件:
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/kdiff3.app/Contents/MacOS/kdiff3 $*
現(xiàn)在 Git 會(huì)使用KDiff3來做比較、合并和解決沖突。
Git預(yù)先設(shè)置了許多其他的合并和解決沖突的工具,而你不必設(shè)置cmd。可以把合并工具設(shè)置為:kdiff3、opendiff、tkdiff、meld、xxdiff、emerge、vimdiff、gvimdiff。如果你不想用到KDiff3的所有功能,只是想用它來合并,那么kdiff3正符合你的要求,運(yùn)行:
$ git config --global merge.tool kdiff3
如果運(yùn)行了以上命令,沒有設(shè)置extMerge
和extDiff
文件,Git 會(huì)用KDiff3做合并,讓通常內(nèi)設(shè)的比較工具來做比較。
格式化與空白是許多開發(fā)人員在協(xié)作時(shí),特別是在跨平臺(tái)情況下,遇到的令人頭疼的細(xì)小問題。由于編輯器的不同或者Windows程序員在跨平臺(tái)項(xiàng)目中的文件行尾加入了回車換行符,一些細(xì)微的空格變化會(huì)不經(jīng)意地進(jìn)入大家合作的工作或提交的補(bǔ)丁中。不用怕,Git 的一些配置選項(xiàng)會(huì)幫助你解決這些問題。
假如你正在Windows上寫程序,又或者你正在和其他人合作,他們?cè)赪indows上編程,而你卻在其他系統(tǒng)上,在這些情況下,你可能會(huì)遇到行尾結(jié)束符問題。這是因?yàn)閃indows使用回車和換行兩個(gè)字符來結(jié)束一行,而Mac和Linux只使用換行一個(gè)字符。雖然這是小問題,但它會(huì)極大地?cái)_亂跨平臺(tái)協(xié)作。
Git可以在你提交時(shí)自動(dòng)地把行結(jié)束符CRLF轉(zhuǎn)換成LF,而在簽出代碼時(shí)把LF轉(zhuǎn)換成CRLF。用core.autocrlf
來打開此項(xiàng)功能,如果是在Windows系統(tǒng)上,把它設(shè)置成true
,這樣當(dāng)簽出代碼時(shí),LF會(huì)被轉(zhuǎn)換成CRLF:
$ git config --global core.autocrlf true
Linux或Mac系統(tǒng)使用LF作為行結(jié)束符,因此你不想 Git 在簽出文件時(shí)進(jìn)行自動(dòng)的轉(zhuǎn)換;當(dāng)一個(gè)以CRLF為行結(jié)束符的文件不小心被引入時(shí)你肯定想進(jìn)行修正,把core.autocrlf
設(shè)置成input來告訴 Git 在提交時(shí)把CRLF轉(zhuǎn)換成LF,簽出時(shí)不轉(zhuǎn)換:
$ git config --global core.autocrlf input
這樣會(huì)在Windows系統(tǒng)上的簽出文件中保留CRLF,會(huì)在Mac和Linux系統(tǒng)上,包括倉(cāng)庫(kù)中保留LF。
如果你是Windows程序員,且正在開發(fā)僅運(yùn)行在Windows上的項(xiàng)目,可以設(shè)置false
取消此功能,把回車符記錄在庫(kù)中:
$ git config --global core.autocrlf false
Git預(yù)先設(shè)置了一些選項(xiàng)來探測(cè)和修正空白問題,其4種主要選項(xiàng)中的2個(gè)默認(rèn)被打開,另2個(gè)被關(guān)閉,你可以自由地打開或關(guān)閉它們。
默認(rèn)被打開的2個(gè)選項(xiàng)是trailing-space
和space-before-tab
,trailing-space
會(huì)查找每行結(jié)尾的空格,space-before-tab
會(huì)查找每行開頭的制表符前的空格。
默認(rèn)被關(guān)閉的2個(gè)選項(xiàng)是indent-with-non-tab
和cr-at-eol
,indent-with-non-tab
會(huì)查找8個(gè)以上空格(非制表符)開頭的行,cr-at-eol
讓 Git 知道行尾回車符是合法的。
設(shè)置core.whitespace
,按照你的意圖來打開或關(guān)閉選項(xiàng),選項(xiàng)以逗號(hào)分割。通過逗號(hào)分割的鏈中去掉選項(xiàng)或在選項(xiàng)前加-
來關(guān)閉,例如,如果你想要打開除了cr-at-eol
之外的所有選項(xiàng):
$ git config --global core.whitespace \
trailing-space,space-before-tab,indent-with-non-tab
當(dāng)你運(yùn)行git diff
命令且為輸出著色時(shí),Git 探測(cè)到這些問題,因此你也許在提交前能修復(fù)它們,當(dāng)你用git apply
打補(bǔ)丁時(shí)同樣也會(huì)從中受益。如果正準(zhǔn)備運(yùn)用的補(bǔ)丁有特別的空白問題,你可以讓 Git 發(fā)警告:
$ git apply --whitespace=warn <patch>
或者讓 Git 在打上補(bǔ)丁前自動(dòng)修正此問題:
$ git apply --whitespace=fix <patch>
這些選項(xiàng)也能運(yùn)用于衍合。如果提交了有空白問題的文件但還沒推送到上流,你可以運(yùn)行帶有--whitespace=fix
選項(xiàng)的rebase
來讓Git在重寫補(bǔ)丁時(shí)自動(dòng)修正它們。
Git服務(wù)器端的配置選項(xiàng)并不多,但仍有一些饒有生趣的選項(xiàng)值得你一看。
Git默認(rèn)情況下不會(huì)在推送期間檢查所有對(duì)象的一致性。雖然會(huì)確認(rèn)每個(gè)對(duì)象的有效性以及是否仍然匹配SHA-1檢驗(yàn)和,但 Git 不會(huì)在每次推送時(shí)都檢查一致性。對(duì)于 Git 來說,庫(kù)或推送的文件越大,這個(gè)操作代價(jià)就相對(duì)越高,每次推送會(huì)消耗更多時(shí)間,如果想在每次推送時(shí) Git 都檢查一致性,設(shè)置 receive.fsckObjects
為true來強(qiáng)迫它這么做:
$ git config --system receive.fsckObjects true
現(xiàn)在 Git 會(huì)在每次推送生效前檢查庫(kù)的完整性,確保有問題的客戶端沒有引入破壞性的數(shù)據(jù)。
如果對(duì)已經(jīng)被推送的提交歷史做衍合,繼而再推送,又或者以其它方式推送一個(gè)提交歷史至遠(yuǎn)程分支,且該提交歷史沒在這個(gè)遠(yuǎn)程分支中,這樣的推送會(huì)被拒絕。這通常是個(gè)很好的禁止策略,但有時(shí)你在做衍合并確定要更新遠(yuǎn)程分支,可以在push命令后加-f
標(biāo)志來強(qiáng)制更新。
要禁用這樣的強(qiáng)制更新功能,可以設(shè)置receive.denyNonFastForwards
:
$ git config --system receive.denyNonFastForwards true
稍后你會(huì)看到,用服務(wù)器端的接收鉤子也能達(dá)到同樣的目的。這個(gè)方法可以做更細(xì)致的控制,例如:禁用特定的用戶做強(qiáng)制更新。
規(guī)避denyNonFastForwards
策略的方法之一就是用戶刪除分支,然后推回新的引用。在更新的 Git 版本中(從1.6.1版本開始),把receive.denyDeletes
設(shè)置為true:
$ git config --system receive.denyDeletes true
這樣會(huì)在推送過程中阻止刪除分支和標(biāo)簽 — 沒有用戶能夠這么做。要?jiǎng)h除遠(yuǎn)程分支,必須從服務(wù)器手動(dòng)刪除引用文件。通過用戶訪問控制列表也能這么做,在本章結(jié)尾將會(huì)介紹這些有趣的方式。
更多建議: