讓 Shell 命令提示符顯示 Git 分支名稱

緣起

在本地環(huán)境( iTerm2 + zsh) 使用終端工具操作 Git 時(shí), 能夠顯示"當(dāng)前文件夾名稱"以及" Git 分支名稱"(如下圖).


shell_git_01.jpg

這種設(shè)置非常有用, 尤其是需要頻繁切換分支時(shí), 能夠避免操作錯(cuò)誤的分支.
但是使用遠(yuǎn)程服務(wù)器和 Vagrant 虛擬機(jī)時(shí)沒有這個(gè)功能.


解決

上網(wǎng)搜索, 在一個(gè)博客上找到解決方案.

在 Shell 的配置文件中添加下面代碼:

function git-branch-name {
  git symbolic-ref HEAD 2>/dev/null | cut -d"/" -f 3
}
function git-branch-prompt {
  local branch=`git-branch-name`
  if [ $branch ]; then printf " [%s]" $branch; fi
}
PS1="\u@\h \[\033[0;36m\]\W\[\033[0m\]\[\033[0;32m\]\$(git-branch-prompt)\[\033[0m\] \$ "

注意: 上面的 git symbolic-ref HEAD 2>/dev/null | cut -d"/" -f 3 可以改成 git symbolic-ref --short -q HEAD, 更簡潔, 而且測試有效. 謝謝風(fēng)之去向_c305的建議;
為了讓大家可以比較前后, 原來的代碼就不修改了;

因?yàn)檫h(yuǎn)程服務(wù)器使用的是 bash, 所以配置文件在 ~/.bashrc, 添加上面的代碼之后, 輸入 source ~/.bashrc 使配置立即生效.

PS. 可以通過echo $SHELL 命令可以查看系統(tǒng)當(dāng)前使用的 Shell; 如果使用的是 /bin/zsh,配置文件在 ~/.zshrc, 使用 source ~/.bashrc 來使 zsh 的配置立即生效)

最終的效果是:


shell_git_02.jpg

解讀代碼

第 1 部分

function git-branch-name {
  git symbolic-ref HEAD 2>/dev/null | cut -d"/" -f 3
}

git symbolic-ref 是 Git 的命令, 表示"符號引用 (symbolic reference), 指向目前所在的分支. 比如命令 git symbolic-ref HEAD 會輸出當(dāng)前的分支, 輸出樣式像這樣: refs/heads/dev

命令執(zhí)行有兩種輸出, 一種是正常輸出, 一種是錯(cuò)誤輸出. shell 把正常輸出標(biāo)記為 1, 錯(cuò)誤輸出標(biāo)記為 2.
在非 git 工作目錄下氓奈,‘git symbolic-ref HEAD‘會輸出一個(gè)錯(cuò)誤.

/dev/null 文件在被用作重定向輸出時(shí), 表示輸出被直接丟棄; 被用作重定向輸入時(shí), 表示文件結(jié)束.

那么 2>/dev/null 的作用就是:

  • 在非 git 工作目錄下,‘git symbolic-ref HEAD‘ 會輸出一個(gè)錯(cuò)誤, 錯(cuò)誤會輸出到 /dev/null, 即不顯示
  • 在 git 工作目錄下, ‘git symbolic-ref HEAD‘ 會正常輸出, 提示符會顯示當(dāng)前分支
  • 也就是說"只有在 git 工作目錄下時(shí), 提示符才會顯示當(dāng)前分支, 否則什么都不顯示"

cut 是 Shell 命令, 表示剪下文本文件的數(shù)據(jù); cut -d"/" -f 3 表示分隔符是 /, 以此分隔符來識別分割文本, 取出第 3 段數(shù)據(jù);

所以, git symbolic-ref HEAD 識別出的結(jié)果是 refs/heads/dev, cut/ 為分隔符分割文本, 分別是 refsheadsdev, 然后取出第 3 段數(shù)據(jù), 就是 dev(當(dāng)前的分支名稱)

第 2 部分

function git-branch-prompt {
  local branch=`git-branch-name`
  if [ $branch ]; then printf " [%s]" $branch; fi
}

local 在文檔中的解釋是:

The local command creates an [incr Tcl] object that is local to the current call frame. When the call frame goes away, the object is auto-matically deleted. This command is useful for creating objects that are local to a procedure.

那么 local 應(yīng)該是用于聲明"局部變量"的. 查閱資料得知, Shell 中函數(shù)定義的變量默認(rèn)是"全局變量", 所以如果要聲明"局部變量", 需要用 local 顯示聲明;

local branch=`git-branch-name`

是指把函數(shù) git-branch-name 獲得的值賦給 branch 變量;
注意, 在 Shell 中, 聲明變量時(shí)不需要加 $, 而且 = 符號兩邊不能加空格, 在引用變量時(shí), 則需要加上 $, 這就是為什么后面 if [ $branch ]; 需要加 $ 符號的原因.

if [ $branch ]; then printf " [%s]" $branch; fi 表示: 如果存在 $branch 變量, 則將該變量做為字符串打印出來; (PS: shell 的控制結(jié)構(gòu)中, ifelse 判斷語句的開頭是 if, 結(jié)尾是 fi,

第 3 部分

PS1 是 Shell 中的一個(gè)特殊變量, 用來表示"提示符", 該變量的可選參數(shù)包括:

  • \d: 顯示日期, 格式為"星期 月 日"
  • \h: 顯示簡寫主機(jī)名秘车。如默認(rèn)主機(jī)名 "localhost"
  • \t: 顯示 24 小時(shí)制時(shí)間, 格式為 "HH:MM:SS"
  • \T: 顯示 12 小時(shí)制時(shí)間, 格式為 "HH:MM:SS"
  • \A: 顯示 24 小時(shí)制時(shí)間, 格式為 "HH:MM"
  • \u: 顯示當(dāng)前用戶名
  • \w: 顯示當(dāng)前所在目錄的完整名稱
  • \W: 顯示當(dāng)前所在目錄的最后一個(gè)目錄
  • \#: 執(zhí)行的第幾個(gè)命令
  • \$: 提示符, 如果是 root 用戶會顯示提示符為 "#", 如果是普通用戶會顯示提示符為 $

Shell 輸出樣式設(shè)置:

  • \33[0m 關(guān)閉所有屬性
  • \33[1m 設(shè)置高亮度
  • \33[4m 下劃線
  • \33[5m 閃爍
  • \33[7m 反顯
  • \33[8m 消隱
  • \33[30m -- \33[37m 設(shè)置前景色
  • \33[40m -- \33[47m 設(shè)置背景色

所以 PS1="\u@\h \[\033[0;36m\]\W\[\033[0m\]\[\033[0;32m\]\$(git-branch-prompt)\[\033[0m\] \$ " 的解讀如下:

組成部分是:

  • \u@\h 表示顯示"當(dāng)前用戶名"和"主機(jī)名", 用 @ 符號連接;
  • \W 顯示當(dāng)前所在目錄;
  • \$(git-branch-prompt) 表示使用前面 git-branch-prompt() 函數(shù)的結(jié)果;
  • 最后一個(gè) \$ 表示是 root 用戶會顯示提示符為 "#", 如果是普通用戶會顯示提示符為 $;

顏色設(shè)置是:

  • \[\033[0;36m\]\W\[\033[0m\] 剔除轉(zhuǎn)義字符應(yīng)該是 \033[0;36m \W \033[0m. 嘗試打印 echo -e "\033[0;36m 我是目錄名稱 \033[0m", 輸出結(jié)果是
    shell_color_set_01.jpg
  • \[\033[0;32m\]\$(git-branch-prompt)\[\033[0m\]剔除轉(zhuǎn)義字符應(yīng)該是 \033[0;32m $(git-branch-prompt) \033[0m, 嘗試打印echo -e "\033[0;32m 我是分支名稱 \033[0m ", 輸出結(jié)果是
    shell_color_set_02.jpg

參考資料


文章歷史


如果你覺得我的文章對你有用, 請打個(gè)"喜歡", 或者給些改進(jìn)的建議 _

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钧嘶,一起剝皮案震驚了整個(gè)濱河市躁倒,隨后出現(xiàn)的幾起案子幔亥,更是在濱河造成了極大的恐慌只锻,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件紫谷,死亡現(xiàn)場離奇詭異,居然都是意外死亡捐寥,警方通過查閱死者的電腦和手機(jī)笤昨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來握恳,“玉大人瞒窒,你說我怎么就攤上這事∠缤荩” “怎么了崇裁?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵匕坯,是天一觀的道長。 經(jīng)常有香客問我拔稳,道長葛峻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任巴比,我火速辦了婚禮术奖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘轻绞。我一直安慰自己采记,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布政勃。 她就那樣靜靜地躺著唧龄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奸远。 梳的紋絲不亂的頭發(fā)上既棺,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天,我揣著相機(jī)與錄音然走,去河邊找鬼援制。 笑死,一個(gè)胖子當(dāng)著我的面吹牛芍瑞,可吹牛的內(nèi)容都是我干的晨仑。 我是一名探鬼主播,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼拆檬,長吁一口氣:“原來是場噩夢啊……” “哼洪己!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起竟贯,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤答捕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后屑那,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拱镐,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年持际,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沃琅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,918評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蜘欲,死狀恐怖益眉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤郭脂,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布年碘,位于F島的核電站,受9級特大地震影響展鸡,放射性物質(zhì)發(fā)生泄漏屿衅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一娱颊、第九天 我趴在偏房一處隱蔽的房頂上張望傲诵。 院中可真熱鬧,春花似錦箱硕、人聲如沸拴竹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽栓拜。三九已至,卻和暖如春惠昔,著一層夾襖步出監(jiān)牢的瞬間幕与,已是汗流浹背杖们。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工嫌佑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留质和,地道東北人寓辱。 一個(gè)月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像太示,于是被迫代替她去往敵國和親镀钓。 傳聞我的和親對象是個(gè)殘疾皇子病毡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評論 2 361

推薦閱讀更多精彩內(nèi)容