19
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Git のための最強 Bashプロンプト!

Last updated at Posted at 2018-11-01

「git bash PS1」とか「git commit 忘れる」とかで検索している君!!

なにはともあれ、このBashプロンプトを見てくれ!!どうだい、クールだろ?1

オレBash.png

「Git Bash ブランチ」とか「Git Stash Bash」とかでググると、断片的な情報が山ほど出てくる。だがこのBashプロンプトは完全版だ。私や君に必要な機能は全て備わっている。

また、後述するようにこのプロンプトでは未コミットのファイルがあると警告を表示できる。世の中には git-remindというツールがあるらしいが、このBashプロンプトを使う限りgit-remind の出番はないだろう。

機能

現在のブランチ名が表示されるから、master にコミットしちまうなんてポカは起きえない。ついでに、まれによく使うHEAD の現在のコミットIDも表示している。

ブランチ.png

また、

  • 未コミットのファイル
  • ファイルに変更
  • stageされたファイルあり
  • stashあり

といった状態も表示されるから、いちいち git を実行しなくてもいい。
git stash list なんてもう何年も使っていない。

状態.png

ついでに、個人的な好みで時刻や前回の終了コードなんかも表示している。

どうだい、お前さんも使ってみたいだろう?

イカシたプロンプトを出すコマンド

クールなBashプロンプトのGitの情報を表示するには以下のスクリプトを使えば良い。~/bin/git-ps とでもいう名前で保存して、実行権限をつけてくれ。

#!/bin/bash
set -euC

C() {
  case $1 in
    black)    echo -e -n "\033[1;30m";;
    red)      echo -e -n "\033[1;31m";;
    green)    echo -e -n "\033[1;32m";;
    yellow)   echo -e -n "\033[1;33m";;
    blue)     echo -e -n "\033[1;34m";;
    magenta)  echo -e -n "\033[1;35m";;
    cyan)     echo -e -n "\033[1;36m";;
    white)    echo -e -n "\033[1;37m";;
    *) echo -e -n "\033[0m";;
  esac
}

status() {
  local modified=0
  local cached=0
  local untracked=0

  while read -r line; do
    if [ "$line" = '_?_?_' ]; then
      untracked=1
      continue
    fi

    if [[ "$line" =~ ^_[^[:space:]]_.?_ ]]; then
      cached=1
    fi

    if [[ "$line" =~ ^_._[^[:space:]]_ ]]; then
      modified=1
    fi
  done < <(git status --short | cut -b -2 | sed -e 's/\(.\)\(.*\)/_\1_\2_/')

  if [ $modified -ne 0 ]; then
    C red
    echo -n 'M'
  fi

  if [ $cached -ne 0 ]; then
    C green
    echo -n 'C'
  fi

  if [ $untracked -ne 0 ]; then
    C red
    echo -n '?'
  fi

  if [ -n "$(git stash list)" ]; then
    C cyan
    echo -n 'S'
  fi
  C reset
}

branch() {
  local branch
  branch="$(git branch 2>/dev/null | grep '^\*' | sed -e "s/^* //")"
  if [[ "${branch}" =~ ^bug- ]]; then
    C green
  elif [[ "${branch}" =~ ^atc- ]]; then
    C cyan
  elif [[ "${branch}" =~ ^tmp ]]; then
    C magenta
  elif [[ "${branch}" = "(detached from hde/master)" ]]; then
    C yellow
  else
    C white
  fi
  echo -n "${branch}"
  C reset
}

hash() {
  git log --pretty=format:'%h' -n 1
}

git_ps() {
  if ! git status --ignore-submodules &>/dev/null; then
    return
  fi
  echo "git[$(status)]=$(branch):$(hash)"
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  git_ps
fi

プロンプトの設定方法

Bashのプロンプトは、環境変数 PS1 によって設定可能だ。

単にデフォルトのプロンプトにGitの情報を追加したいだけなら、~/.bashrc

export PS1='$(git-ps)\n[\u@\h \W]\\$ '

なんて定義を追加すればOKだ。

PS1には「\u でユーザー名」など、特殊文字が使えるが bashのプロンプトを変更するには - @IT などに一覧表がある。

また、PS1はプロンプト表示毎に評価されるから、全体をダブルクオート" ではなく ' で囲むことに注意だ。

ちなみに、こっちは私が普段使っている、完全版のPS1だ。Gitの他に、RailsやJava、Scala、たまに使うSVNなどのためのコードも含んでいる。

あとは自由にカスタマイズしてくれ!

#!/bin/bash
# PS1の設定

C() {
  case $1 in
    black)    echo -e -n "\033[1;30m";;
    red)      echo -e -n "\033[1;31m";;
    green)    echo -e -n "\033[1;32m";;
    yellow)   echo -e -n "\033[1;33m";;
    blue)     echo -e -n "\033[1;34m";;
    magenta)  echo -e -n "\033[1;35m";;
    cyan)     echo -e -n "\033[1;36m";;
    white)    echo -e -n "\033[1;37m";;
    *) echo -e -n "\033[0m";;
  esac
}

ps1_svn() {
  if ! svn info &> /dev/null; then
    return
  fi
  echo -n ' svn'
}

ps1_rails() {
  if [ -z "${RAILS_ENV-}" ]; then
    return
  fi
  echo -n " RAILS_ENV=$(C white)$RAILS_ENV$(C reset)"
}

ps1_play() {
  if [ -z "${PLAY_ENV-}" ]; then
    return
  fi
  echo -n " PLAY_ENV=$(C white)$PLAY_ENV$(C reset)"
}

ps1_skinny() {
  if [ -z "${SKINNY_ENV-}" ]; then
    return
  fi
  echo -n " SKINNY_ENV=$(C white)$SKINNY_ENV$(C reset)"
}

ps1_login() {
  echo -n "${USER}@"
  echo -n -e "$(C "cyan")$(hostname -s)$(C reset)"
}

ps1_date() {
  date +'%F %H:%M:%S'
}

ps1_exit_status() {
  local END_CODE=$1
  echo -n ' $?='
  if [ 0 -ne "${END_CODE}" ]; then
    echo -n "$(C red)${END_CODE}$(C reset)"
  else
    echo -n 0
  fi
}

ps1_git() {
  if ! git status --ignore-submodules &>/dev/null; then
    return
  fi
  echo -n ' '
  git-ps
}

ps1_java() {
  if [ -n "${JAVA_HOME}" ]; then
    local version
    version=$(java -version |& head -1 | cut -d ' ' -f 3 | tr -d '"')
    echo -n " java=$(C white)${version}$(C reset)"
  fi
}

ps1_docker() {
  if [ -z "${DOCKER_MACHINE_NAME}" ]; then
    return
  fi

  local docker_host_ip
  docker_host_ip="${DOCKER_HOST/tcp:\/\//}"
  docker_host_ip="${docker_host_ip/:*/}"
  echo -n " docker=[${docker_host_ip}]"

  if [ -n "${COMPOSE_FILE}" ]; then
    echo -n ","
    echo -n docker-compose.qa-hosted.yml | sed -e 's/^docker-compose.//' -e 's/.yml$//'
  fi
}

ps1_prompt() {
  if [ "$(id -u)" -eq 0 ]; then
    echo -n "$(C red)# $(C reset)"
  else
    echo -n "$(C "${HOST_COLOR}")$ $(C reset)"
  fi
}

ps1_path() {
  echo " $(pwd | sed -e "s|^${HOME%/}|~|")"
}

function ps1_info() {
  local END_CODE=$?
  echo "$(ps1_login)$(ps1_exit_status "$END_CODE")$(ps1_git)$(ps1_svn)$(ps1_rails)$(ps1_skinny)$(ps1_play)$(ps1_java)$(ps1_docker)"
  echo "$(ps1_date)$(ps1_path)"
}

PS1='$(ps1_info)'


# カーソル位置がずれる問題を回避するため、ここの部分だけは文字列連結にする
if [ "$(id -u)" -eq 0 ]; then
  PS1="${PS1}\n\[$(C red)\]#\[$(red)\] " # rootの場合はシャープ
else
  PS1="${PS1}\n\[$(C cyan)\]\$\[$(C reset)\] " # 非rootユーザの場合はドル
fi

export PS1

なお、私はサーバーで Bash を使用している関係上、開発用PCでも Bash を使用しています。Zsh や Fish などを使用されている方は適当に読み替えてください。

  1. ついカッとなり、いささかお見苦しい表現の記事となっておりますが、ご笑覧いただければ幸いです。

19
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?