Qiitaに掲載したGit記事の裏話と、ちゃんとした説明
雑感::artdig
序
Qiitaに3編に渡って「Qiitaっぽい」Git記事を掲載した。
Qiitaっぽく書くために非常に苦労したし、そのために説明を著しく省いたので、ここでストレス解消しておこうと思う。
裏話
Windowsのきつさ
とにかくWindowsが素直にいかないのがものすごく壁だったし、Windowsユーザー向けに細かく説明するのはかなりしんどかった。
単にWindowsだと手順が多いとかならまだしも、「そのようにする理由をちゃんと理解しようとするとハードルが高い」という要素が多くて、単純にWindowsでやるほうが難易度が高いのだ。 言われた通りに実行するだけならそこまで難しいものではないし、Qiitaの読者はだいたいそんな感じだと思っているが、私としてはすっきりしない。
SSH経由のオリジンリポジトリの話ではさらにきつく、WindowsのOpenSSHサーバーの用意自体がまあまあ面倒な上に単純にSSHサーバーを用意しただけでは収まらないので、結局WSL2を使った上にポートフォワーディングまでしている。
「宅内に中古PCでいいからLinuxのサーバーを用意しておきなさい」と言いたくなる気持ちを何度飲み込んだことか。
現実的な話としては、Windows PCしかない環境の人にはクラウドドライブ同期を強く勧めたい。 というか、実用だけの話ならそこで話を終わらせていたが、SSHアクセスの話をしないと話自体が進まないので苦しみを乗り越えることになった。
WSL2 + Archlinuxが割と救い
Archlinuxは長期的に見た場合他のディストリビューションよりもずっと環境が安定しているので、Archlinuxをターゲットにした説明の有効期限は他のディストリビューションよりも基本的に長い。 しかも、Archlinuxの場合は他のディストリビューションと比べてかなり端的に書ける。 この違いが割と大きい。
Linux上で動作させたいものを動かす環境を用意する簡単な方法としてArchlinuxは非常に使いやすいし、例示もしやすい。
説明の基準の選定
全く触れなかったのはstash
, blame
あたり。
使えると便利ではあるけれど、stash
する場合は複数の状態を把握した上で並行させるということが必要になってGit運用自体が難しくなるから、そもそも直列に進む話にしたいがために省いた。
blame
を行うときはblame
を行う目的、つまり「コードの問題の追跡」という話が必要になり、趣旨から大きく外れるためにしていない。
ブランチ周りの話もそうで、「そもそも問題を発生させないように操作手順を徹底しろ」というのが基本スタンス。 Gitだとそこまで気にならないけど、Mercurialだとこれはめちゃくちゃ重要になる。
Windows環境でのPowerShell操作
実はほとんどはCopilotに相談して書いている。
実際Windows環境で試しながらやってはいるけど、私はPowerShellができないので。
SSHの話
実はSSHの話だけで300行くらいいったので、1度バッサリとカットしている。
最終的にSSH部分も具体的に書いているからいらなかったと言う人もいるかもしれないが、実際は「なんで」みたいなツッコミへの予防線としても機能するので、必要だったと思っている。
ちゃんと説明する
Git for Windowsのインストール手順
Infomation
GNU GPLのライセンス許諾。
GNU GPLについて説明したら大長編になってしまうから、知らない人は各々調べること。
Select Destination Location
インストール先の選択。
Select Components
コンポーネントというか、連携機能の設定をするかどうかという面が大きい。
基本的には右クリックからOpen Git Bash here
するのが定石だから、Windows Explorer intergration > Open Git Bash here
は絶対に入れておきたい。
Add Git Bash Profile to Windows Terminal
も魅力的。
Select Start Menu Folder
スタートメニュー内のフォルダ名。
Windows 11ではどうなるんだろうね?
Choosing the default editor used by Git
unix感覚で言えばVimを使うようにすればいいし、Vimが組み込まれているのだからそうすれば良いでデフォルトなのは納得するのだけど、Gitを知らないWindowsユーザーにVimを意識させるのは厳しすぎる。
ここでの選択はテキストエディタのインストールを伴わないので、「あなたの環境と希望を理解して選択してください」になるのだけど、話を簡単にするならnotepadになる。
Adjusting the name of the initial branch in new repositories
Gitのデフォルトのデフォルトブランチ名はmaster
だが、ポリコレ的にmain
にするとかいうよくわからない流れがあり、それに屈するかどうかという質問である。
master
を維持する意志力を持たない人には、私はdoctor
をおすすめしたい😉
Adjusting your PATH environment
Gitが同梱するものをどこで使えるようにするか。
Use Git from Git Bash only
は完全に環境に閉じ込める。
Use Git and optional Unix tools from the Command Prompt
は、想定したようには動作しない上に互換性問題を発生させうるからやめといたほうがいい。
そういうことをしたいならPPTを使うほうがまだ良い。
Choosing HTTPS transport backend
Git for Windowsにバンドルされている(MSYS2環境の)OpenSSLを使うか、WindowsネイティブなsChannelを使うかの選択。
相当深いレベルでしか違いが出てこないし、その場合はWSLで使うとかのほうが好ましかったりするから、OpenSSLを指定するのはsChannelに明確な不満がある場合に限られてくる。
Configuring the line encoding conversions
改行コードはCRLF(U+000D U+000A), LF(U+000A), CR(U+000D)の3種類がありうるのだが、現代ではWindowsだけがCRLF、それ以外はLFであると考えて良い。
Gitはプラットフォームを制限しないが、Git内のコンテンツがプラットフォームに依存する問題を発生させる可能性がある。 そのうち、改行コードについて便利に扱う機能の選択である。
- Checkout Windows-style, commit Unix-style line endings
- ワーキングツリーに展開するときはLFをCRLFにし、リポジトリ上ではCRLFをLFにする
- ワーキングツリーはWindowsスタイルにして、リポジトリ内はunixスタイルにしてくれる
- 基本的にWindowsで扱いやすい形式だけど、unix文化に由来するアプリで編集したりするなら邪魔になることも
- Checkout as-is, commit Unix-style line endings
- コミットするときだけワーキングツリー上のCRLFをLFに変換する
- Vimのようなunix環境由来のエディタを使う場合などに便利
- Checkout as-is, commit as-is
- 変換しない
- ちゃんとline-ending管理できる人向け
Configuring the terminal emulator to use with Git Bash
Git Bash here
したときの端末をMinTTY(MSYS2の端末)かcmd.exeかを選べる。
cmd.exeは必要な機能が大変欠けているので、ほぼMinTTY一択。 Windows Terminalが選択できるようになったら少し変わってくるかもしれない。
Choose the default behavior of git pull
git pull
の挙動設定。
自分で調べてもらったほうがいい。
Choose a credential helper
私も詳しくない。
Confuguring extra options
Enable symbolic linksはsymlinkを有効にするんだけど、ユーザーが無制限に作れるunix-likeなシステムと違ってWindowsは特別な権限が必要になるので、結局デフォルト設定のままが良い。
Windows sshd手順の意味
WindowsをGitのsshdホストにしようとした場合、Gitのsshdホストとして
- sshでログインできる
- sshからgitにアクセスできる
- gitが要求するunix的なファイルシステム環境がある
を満たす必要がある。
まず、「sshでログインできる」を満たすための手順がWindowsだと大変なのだが、Windowsにログインしただけではgit
は使えないし、Git BashはMSYS2で動作するようになっているから動くのであって、これを満たすためにはWindowsにsshログインしたときにMSYS2経由でgit
が起動できるようにする必要があり、だいぶhackishになる。
だったら最初から環境ワンセット揃っているLinux環境のほうがいいし、WSLを使えばWindowsホストであっても利用できる、というのが説明の流れ。
WSL環境にSSHでログインした場合、そこは完全なLinux環境として扱えるので、基本的にその話自体はLinuxと揃う。 が、問題はその条件を満たすまでの状態を整えることだ。
まずWSLのLinuxホストが起動している、というのは当然の前提。勝手には起動しない。 Linuxホストが起動していれば、自動実行されるようになっているsshdはその時点で起動する。 だから、Linux側の手順はWSLだからどうというのはほとんどない。
だが、WSLのOpenSSHサーバーへはホストであるWindowsからは直接つながる(WSLインスタンスのアドレスを指定せずlocalhost
で通る)けれど、外部ホストからはつながらない。
なので、物理インターフェイスから仮想インターフェイスへのルートが必要になる。
最初は次のように書いていた。
ここでWindowsの
2222
からWSL Archlinuxの22
へつなぐ方法が必要なのだが、比較的簡単なのはWindows側からSSHのポートフォワーディングをする方法。Windows側で鍵を作る。
-t ed25519 -f %USERPROFILE%\.ssh\forwarding_ed25519 ssh-keygen
これで
%USERPROFILE%\.ssh\forwarding_ed25519.pub
に公開鍵が生えるので、これをWSL Archlinuxの/home/gitter/.ssh/authorized_keys
の1行として書いて保存する。これはroot
ユーザーからsu - gitter cd mkdir .ssh chmod 700 .ssh nano .ssh/authorized_keys
のようにする。
そしたらWindows側で次のようにする。 これは、プロセスとして残しておく必要があり、またWSLのArchlinuxが起動している必要がある。 つまり、
- Windowsの起動
- WSL Archlinuxの起動
- ポートフォワーディングの起動
という手順が必要である。
-gfN -L 2222:localhost:22 -i ~/.ssh/forwarding_ed25519 gitter@localhost ssh
これで外部ホストからポート
2222
でArchlinuxへ接続可能になった。
が、これで良いことに気づいた。
=2222 listenaddress=0.0.0.0 connectport=22 connectaddress=127.0.0.1 netsh interface portproxy add v4tov4 listenport
ので編集した。
要はどちらも外部のホストからWindows経由でアクセスしたものをWSLのsshdポートに飛ばそうとしている。
クライアント -> Windows:2222 -> WSL:22
ポート転送することでこの経路を作った。
だが、このままではWindows:2222
へのアクセスが遮断されてしまうので、Windows Defenderによるファイアウォールの通過が必要だ。
-DisplayName "WSL SSH" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 2222 New-NetFirewallRule
鍵ファイル
鍵ファイルは流用せずログインするターゲットごとに作るのが原則。
一方、特定サイト内で同一の人物であることを認証する上では同一のものを使うべき。
つまり通常の場合、id_$type
をLAN内のホストのみに使用し、外部サービスには個別の鍵を用意するほうが良い。
ちなみに、数が多くなるなら~/.ssh
直下でないほうが良い。
これは、オファーする鍵が多くなりすぎないようにするためだ。
オファーできる回数には限りがあるため、候補を片っ端からだしてしまうとPermission Deniedになる原因になる。
IdentitiesOnly
ssh_config
のIdentitiesOnly
は、指定したキーファイルのみを認証に使用する。
これは、~/.ssh
以下にたくさんキーがあったり、エージェントに多数のキーを登録したりしている状況で必須になってくる。
鍵ファイルが増えてくると必然的に発生するので、基本的にIdentityFile
とセット運用してつけておくのが安心。
Windowsパスでのチルダ
~
はunixシェルの場合シェルが解釈するのでプログラム側には依存しない。
で、その上でなのだけど、ssh
は設定に書かれた~
を解釈するが、ssh-keygen
は解釈しない、らしい。
確かめていないが、これのせいでWindowsの話が複雑に。
悪いのは、シェルが展開しないWindowsである。
sshd_configの安全設定
正直なところ、安全な鍵を使っていれば鍵が漏洩しない限りOpenSSHの公開鍵認証を突破される可能性は皆無と言って良い。
AnthenticationMethods publickey
は認証を公開鍵認証のみにするため、これだけで十分安全である。
DenyUsers root
はどちらかというと攻撃に対する負荷軽減のためというのが大きい。
PasswordAuthentication
は認証方式password
のみに影響するわけではない。
そして、これをnoにすれば安全ということでもない。
AuthenticationMethods
がpublickey
のみである場合、PasswordAuthentication
を参照することはないため設定する意味はない。
commitしてから操作しなさい
Gitではuntrackedなファイルはブランチを切り替えたときもuntrackedのまま残され、一方管理されているものはブランチ切り替えに合わせて切り替わり、未コミットの内容があるときはブランチの切り替えができない。
変更を横に置くstash
というのもあるが一人で作業する分には「常にcommitして切り替える、分岐するにしても歴史は同期的に前に進み続ける」というポリシーでやるのが圧倒的に事故がない。
ちなみに、Gitだとそこまででもないが、Mercurialは本当にそうしないとしんどいことになる。
Gitホスティングの権限をもっと掘り下げる
unixシステムのアカウントを理解していないと難しいところだが、まずオリジンGitリポジトリをjohn
が所有しているとする。
この状態のとき、通常リポジトリを更新できるのはjohn
だけである。
ほかのユーザーにも更新できるようにしようとすると、ユーザーの共有という不適切な運用が必要になる。
だから、変更をjohn
に集約するために、john
にpatchを送る、という方式になる。
仮にリポジトリがcomitterを複数持っていたとしても、comitterにpatchを送る方式には変わりないし、comitterによるリポジトリの変更を限定的にするのも難しい。
Git自体がそもそもunixのファイルシステムと権限管理に依存した作りをしており、わかりやすいコラボレーション作業スタイルにあまり適合しない。
だったらGitの持っているネイティブ管理を使わずに、webアプリのコントロールに集約してしまえば良い、というのがGitホスティングソフトウェアの動作。
システムユーザーは専用ユーザー(だいたいgit
)に集約してしまい、リポジトリへのアクセスはGitホスティングソフトウェアを経由するようにすることで、システムとは別レイヤーのユーザー管理を適用することができる。
そして、これによりGit自体では難しいブランチ単位のコントロールも可能なわけだ。
実際のGitホスティングの使われ方
DevOpsプラットフォーム系
Azure DevOps, AWS CodeCommit, Cloud Source Repositoriesを比べた場合、Azure DevOpsはある程度利用者がいる(17350社程度らしい)が、AWS CodeCommitは新規受付停止、Cloud Source RepositoriesはGoogleも積極的に推進もせず「Googleの次の明日消えるサービス候補」レベルになっている。
公開事例や市場調査を見る限り、Azure, AWS, GCPユーザーであってもそれぞれの標準Gitサービスを積極的にインテグレーション目的で使うという動きは限定的で、実際はGitHub, BitBucket, GitLabを使うというのが現実的状況となっている。
GitHub
選択肢として最も有力視されるのはGitHubである。 GitHubは圧倒的な知名度、シェアを背景とし、またGitホスティングの先駆けであることもあって「Git=GitHub」という誤解をしている人も少なくない。
GitHubはデファクトスタンダードであり、「特段の理由がなければGitHubを選ぶ」という状況は多く見られる。 「鶏が先か、卵が先か」の話ではあるが、企業側がGitHub利用を前提とした採用活動をし、求職者側もポートレートとしてGitHubを利用することもあるから、エンジニアキャリアとしてもGitHubありきになっている側面もある。
採用にあたってOSS活動を行っている開発者を評価する指標としてもGitHubの機能を用いたりするから、OSS活動をする場合にもGitHubで行ったほうがリターンが大きいということでOSSリポジトリもGitHubにより集まりやすい背景がある。 もちろん、広くcontributeを受けたい場合はユーザーアカウント数が多いGitHubで展開したほうが広がりやすいという単純にOSSプロジェクト的な理由もある。
これは、「動画投稿をするならYouTubeにしたほうが良い」というのと似た側面である。
デファクトスタンダードであるが故に、もし会社でGitHub以外を採用しようとするならば、「GitHubではない理由」を説明する必要が発生する可能性が高いだろう。
BitBucket
比較的弱い理由でも採用されやすいのはBitBucketだ。 世界で約1500万人の開発者、100万のチームが利用しているといい、GitHubやGitLabほどではないがそれなりにシェアを持っている。
JiraやConfluenceを利用する企業は多い、つまりはAtlassian製品の契約を持っている企業は多い。 この時点でBitBucketを使う下地はあり、ここにAtlassian製品との連携を重視する視点が入れば採用される可能性が出てくる。
実際、BitBucketを利用するならAtlassian製品の中でワークフローを完結させやすく、かなり便利。Jiraの課題とコミットの自動リンクや、Confluenceページへのコード埋め込み、Bitbucket PipelinesによるCI/CDなど、他製品との一体感は非常に高い。 個人的な意見を加えるなら、BitBucketはチーム作業での権限管理やプルリクエストのディスカッション機能が洗練されており、BitBucketを使う環境に就いたならば幸運だと思う。
難点として挙げるなら、求人票の採用要件には「GitHubでの経験」あるいは「GitHabまたはGitLabでの経験」が挙げられることが多く、BitBucketを用いたチーム開発の経験が書類上のアピールになりにくい。 キャリアに反映させるにはGitの知識やGitでのチーム開発作業のスキルを持っていることをアピールするなど工夫が必要になる。
GitLab
GitLabはGitホスティングサービスであると同時にセルフホスト可能なGitホスティングソフトウェアでもあるため、GitHubやBitBucketとはやや異なるレイヤーで捉える必要がある。
GitLabは「GitHubでない選択肢」を求めたときの第一候補としてgitlab.comのユーザーが非常に多い。 数百万ユーザーと数千のOSSプロジェクトという数は、GitHubとは比べてものにならないが、それでも第二の選択肢としての存在感は確かだ。
もうひとつは、企業内でのクローズドリポジトリ運用として、「セルフホストできるGitHub」のようなニュアンスで採用されることが多いことだ。 これは、GitLabの知名度が他のGitホスティングソフトウェアよりも高いということもあるだろう。
セルフホスト型GitLabが採用される背景は、単なるGitHub嫌いや逆張りという理由もなくはないだろうけれども、多くの場合はセキュリティ要件やコンプライアンス準拠といった理由である。
一方で、OSSコミュニティがself-hostedで使うGitホスティングソフトウェアとしては採用例は少なめ。 理由は、やはりGitLabというソフトウェアがRuby on Railsベースで重めのアプリケーションであることにあるだろう。 サーバーコストをかけにくいOSSコミュニティではリソース要件がCPU・メモリ・ストレージのどこをとっても高いソフトウェアの運用はインフラ費用的にしんどいし、GitLabは大きく複雑なソフトウェアであり、依存コンポーネント数が多く月次アップデートなど運用面での負担も大きいことが採用のハードルを押し上げている。
Gitea/Forgejo
Gitea/Forgejoは軽量なGitホスティングソフトウェアである、というのが根底にある。
Gitホスティングサービスを展開する上でも負担が少ないし、OSSプロジェクトが自分でホストするにしても負担が少ない。 そして、だいたいにしてもGitea/Forgejoが採用されるのには「軽量」という明確な採用理由がある。
軽量さについてはGitホスティングプラットフォーム Forgejoを建てるで詳しく述べた。
ただ、元の記事の主旨は「これからGitでのチーム開発に備えたいエンジニア」に向けたものだ。 Gitea/Forgejoの採用数は、リストされた他の選択肢と比べれば高いが、実際にそのようなエンジニアがGitea/Forgejoを使って仕事をすることになる可能性は本当に低いので、詳しい説明をする必要はないと判断した。