本記事は「エーピーコミュニケーションズ Advent Calendar 2022」の2日目のエントリとなります。
Gitを使う作業を個人に与えられたOSアカウントで行う分には何も不都合はないけれど、共用サーバーの共用アカウントを複数人で使用する場合、コミット時の名前やリモートリポジトリへの認証の設定を工夫しないと他の人と設定が混じるので注意が必要。
よくあるユースケースとしては、プロダクション環境やステージング環境で作業用のOSアカウントをプロジェクトメンバ毎に作らずに、運用に使用する最小限の作業・管理用アカウントしかホスト上にない、とか。場合によっては開発環境でも。
イメージとしては、作業ホストはAWSのEC2上でec2-user
ユーザーをプロジェクトメンバ全員で共用するような感じ。でもGitのリモートリポジトリはGitHubやGitLab上にプロジェクトメンバ個人ごとのアカウントがある、という構成。
「私はこうやってる」という話なので、こっちの方法が簡単だよーとかあったら教えてください。($HOME
を更新するのは影響が大きそうなので避けてます)
- (おさらい) 普通にGitを使う場合のユーザー設定
- (解決策1) リポジトリ単位のユーザー設定
- (解決策2) 環境変数を使ったGitユーザー設定
- 共用アカウント環境におけるGit + SSHの個人設定
- その他のGit便利設定(git-prompt)
- 設定の確認
- 参考
- 環境
(おさらい) 普通にGitを使う場合のユーザー設定
Gitのリポジトリを作るかGitHubからリポジトリをクローンして、何も設定してない状態でコミットしようとすると、
Author identity unknown *** Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name" to set your account's default identity. Omit --global to set the identity only in this repository.
みたいなエラーメッセージが表示される。
出力されている通りにユーザー名とメールアドレスを設定するとコミット時のユーザー名・アドレスが記録されるようになるが、このコマンドを実行すると、実行ユーザーのホームディレクトリ直下の.gitconfig
ファイルに設定が保存される。
$ git config --global user.name zaki $ cat $HOME/.gitconfig [user] name = zaki
これはOSのアカウントが自分専用であれば何も問題ないが、前述の通り共用アカウント環境で設定すると他の利用者(例えばプロジェクトメンバ)も同じ設定になってしまうし、逆に他の利用者がその人の名前で設定しまうと、自分のコミットが他の利用者の名前になってしまい都合が非常に悪い。
(解決策1) リポジトリ単位のユーザー設定
「Gitリポジトリ作成(またはクローン)のあと」に、git config
のオプションで--global
でなく--local
を付与してユーザー設定することで、$HOME/.gitconfig
でなく、リポジトリローカルの.git/config
へ設定保存できる。
$ git config --local user.name zaki $ cat .git/config : : [user] name = zaki
このファイルの設定内容は$HOME/.gitconfig
より優先されるので、OSアカウントの設定にかかわらずにクローンしたリポジトリ内に設定されたユーザー名でコミットを実行できるため、他の利用者の設定と区別できる。
(※ あくまでクローンしたリポジトリは自分しか使わないという前提で…)
ただしこの方法にも事故りやすい以下の欠点がある。
- クローンするたびに
git config --local
を使ったユーザー設定が必要で面倒 git config --local
するのを忘れてかつ、$HOME/.gitconfig
に他の利用者の設定があると気付かないうちに他の利用者名でコミットしてしまう
後者については、コミット直後であれば--amend
と--author
を使って比較的修正は簡単だけど、いくつもコミットがある場合はrebase
が必要なのでちょっと大変。この場合は「git commit author 変更」あたりでググると情報がヒットする。
(解決策2) 環境変数を使ったGitユーザー設定
git config
を使った設定の欠点を回避する方法としては、環境変数の設定が個人的にはお勧め。
git config --global
はもちろんgit config --local
の必要もないのでクローンの度に設定する必要がない$HOME/.gitconfig
が存在していても設定を上書きする
設定する環境変数は以下の通り。ユーザー名とメールアドレスでCommiterとAuthorの2つずつある。
(ComitterとAuthorの違いはググってね)
- GIT_AUTHOR_NAME
- GIT_COMMITTER_NAME
- GIT_AUTHOR_EMAIL
- GIT_COMMITTER_EMAIL
ただしこの環境変数の設定を$HOME/.bashrc
とかのシェル起動時に設定するファイルで行うと(全利用者が同じユーザー設定になってしまって)無意味なので、ちょっと面倒だけど「自分用の環境変数ファイルを別途作成」し、ログインのたびに読み込むようにする。
私の場合はいつもホスト上に$HOME/(自分の名前)-work/
というディレクトリを作って、そこに個人用設定ファイルなどを作成してる。環境変数の場合はだいたいいつもenv.source
というファイルに記述している。
(名前にそんなに意味はなくてsource
コマンドで読み込むから、程度。rc
の方が良いかもね。実際のところsou[tab]
より.
の方がタイプが速いのでsource
コマンドは使ってない笑)
Gitコミット関連の環境変数はこんな感じ。
export GIT_AUTHOR_NAME=zaki export GIT_COMMITTER_NAME=zaki export GIT_AUTHOR_EMAIL=zaki@email.example.org export GIT_COMMITTER_EMAIL=zaki@email.example.org
この設定が必要な作業ホストへSSH接続するクライアントが自分専用アカウント($HOME/.ssh/config
を自分専用にイジれる個人用に貸与されたPCなど)なのであれば、次のような設定でSSH接続後に任意のコマンドを自動実行することもできる。
Host target hostname 192.168.0.0 identityfile ~/.ssh/id_rsa RemoteCommand . ~/zaki-work/env.source; bash RequestTTY true
共用アカウント環境におけるGit + SSHの個人設定
結論から言うと、環境変数GIT_SSH_COMMAND
を使って設定すれば良い感じにできる。
共用アカウント環境のコミット時のユーザー設定は前述の通り環境変数を使って良い感じに個人設定できるけど、リモートリポジトリへプッシュするときに困ったのがSSHの設定(というか秘密鍵設定)。デフォルトでは$HOME/.ssh/config
を参照するし、ssh
実行時に設定ファイルを変更したい場合は-F
オプションでファイル変更できるけどgit
実行時にSSHの設定ファイルを指定する専用オプションもぱっと見では見当たらず。かといってHTTPSでリモートリポジトリ設定すると、認証情報をリポジトリURLへ埋め込むかpush/pullの度に毎回入力するハメになるため煩わしい。
そこで使うのが試行錯誤した結果、環境変数GIT_SSH_COMMAND
を使うことで、Git実行時に参照するSSHの設定ファイル(デフォルト$HOME/.ssh/config
)をカスタムするオプションを渡すことができる。
具体的には、例えばSSHの設定ファイルとしてデフォルトでなく$HOME/zaki-work/.ssh/config
を使用したい場合(ssh
の場合であれば-F $HOME/zaki-work/.ssh/config
とする場合)は、以下の通り。
export GIT_SSH_COMMAND="ssh -F $HOME/zaki-work/.ssh/config"
これで、GitコマンドからSSHを使う場合に$HOME/zaki-work/.ssh/config
を参照して実行できる。
$HOME/zaki-work/.ssh/config
ファイルには、$HOME/.ssh/config
と同じ書式で自分が使用したい秘密鍵やユーザー名などを設定すればOK。
Host github.com identityfile ~/zaki-work/.ssh/my_id_rsa
GIT_SSH_COMMAND
に直接鍵ファイルのパスも指定できるけどssh_config
ファイルを指定しておくといろいろ設定の幅が広がると思う。
秘密鍵へのアクセスについては共用アカウントの利用者は全員見ることができるけどそこは妥協点(どう考えても仕方ない)。そもそも個人アカウントがあったとしても同じホストでrootに昇格できるなら条件は同じ。
その他のGit便利設定(git-prompt)
共用アカウントで「自分用環境変数ファイル」を読み込んだときにPS1
環境変数を細工してプロンプトを変化させておけば、自分用の環境がセットされていることが分かりやすい。
そこで、設定自体は共用アカウント特有の内容じゃないけど、git promptを使用し便利なGitリポジトリの状態を表示するプロンプトも設定しておくと一石二鳥。
設定を共用アカウント全体でやるなら他利用者とネゴっておきましょう。
インストールは通常はGitHubにあるソースを直接ダウンロードしてるが、疎通のない環境であればコピペで作成するのも可。
curl -L https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh -o .git-prompt.sh chmod 755 .git-prompt.sh
主な設定は以下。(.git-prompt.sh
が~/zaki-work
以下にある場合の設定)
if [ -f ~/zaki-work/.git-prompt.sh ]; then source ~/zaki-work/.git-prompt.sh PS1='\[\e[31m\]$(__git_ps1 "(%s) ")\[\e[0m\]'"$PS1" GIT_PS1_SHOWDIRTYSTATE=true GIT_PS1_SHOWUNTRACKEDFILES=true GIT_PS1_SHOWSTASHSTATE=true GIT_PS1_SHOWCONFLICTSTATE=yes GIT_PS1_SHOWUPSTREAM=auto fi
プロンプトがこのようになり、今いるブランチや、未コミットのファイルやコンフリクトの有無などを表示してくれる。
(master *%>) [zaki@cloud-dev dev]$
環境変数を使った主な表示フラグについては以下。
設定 | 効果 |
---|---|
GIT_PS1_SHOWDIRTYSTATE | unstage(* )、staged(+ )のファイルの変更の有無を表示 |
GIT_PS1_SHOWUNTRACKEDFILES | untrackedなファイルの有無を文字'%`で表示 |
GIT_PS1_SHOWSTASHSTATE | stashの有無を文字$ で表示 |
GIT_PS1_SHOWCONFLICTSTATE | yes にすると未解決のコンフリクトが残ってる場合にCONFLICT 表示 |
GIT_PS1_SHOWUPSTREAM | auto にするとHEADとupstream(リモートリポジトリ)との差分の有無を確認できる。未pushがあるかどうか等 |
ちなみにture
をセットしている環境変数は、false
にするとオフになるわけでなく、「空欄で無ければ有効」という動作。無効にするには環境変数を削除するか、空白文字をセットする。
その他の設定や詳細についてはソースのコメント参照。
設定の確認
Gitの設定ファイルによる現在の設定値は以下のコマンドで確認可能。
git config -l
--global
や--local
を付与することで、設定箇所個別に確認もできる。
git config --system -l git config --global -l git config --local -l
ただしあくまで設定ファイルの状態が出力されるため、環境変数による上書きはこのコマンドでは確認できない。
環境変数の設定はenv | grep -i git
などで確認するしかない(多分)のでその点は注意。
参考
manの日本語訳ページは便利だけど古い場合が多いので気を付けましょう:)
(SSHとか便利な新機能が結構あったりするけど20世紀版とかヒットするので)
環境
- OS: Fedora 35
- Git: git version 2.37.3