Chienomi

Qiitaに掲載したGit記事の裏話と、ちゃんとした説明

雑感::artdig

  • TOP
  • Articles
  • 雑感
  • Qiitaに掲載したGit記事の裏話と、ちゃんとした説明

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側で鍵を作る。

ssh-keygen -t ed25519 -f %USERPROFILE%\.ssh\forwarding_ed25519

これで%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が起動している必要がある。 つまり、

  1. Windowsの起動
  2. WSL Archlinuxの起動
  3. ポートフォワーディングの起動

という手順が必要である。

ssh -gfN -L 2222:localhost:22 -i ~/.ssh/forwarding_ed25519 gitter@localhost

これで外部ホストからポート2222でArchlinuxへ接続可能になった。

が、これで良いことに気づいた。

netsh interface portproxy add v4tov4 listenport=2222 listenaddress=0.0.0.0 connectport=22 connectaddress=127.0.0.1

ので編集した。

要はどちらも外部のホストからWindows経由でアクセスしたものをWSLのsshdポートに飛ばそうとしている。

クライアント -> Windows:2222 -> WSL:22

ポート転送することでこの経路を作った。 だが、このままではWindows:2222へのアクセスが遮断されてしまうので、Windows Defenderによるファイアウォールの通過が必要だ。

New-NetFirewallRule -DisplayName "WSL SSH" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 2222

鍵ファイル

鍵ファイルは流用せずログインするターゲットごとに作るのが原則。

一方、特定サイト内で同一の人物であることを認証する上では同一のものを使うべき。

つまり通常の場合、id_$typeをLAN内のホストのみに使用し、外部サービスには個別の鍵を用意するほうが良い。

ちなみに、数が多くなるなら~/.ssh直下でないほうが良い。 これは、オファーする鍵が多くなりすぎないようにするためだ。

オファーできる回数には限りがあるため、候補を片っ端からだしてしまうとPermission Deniedになる原因になる。

IdentitiesOnly

ssh_configIdentitiesOnlyは、指定したキーファイルのみを認証に使用する。

これは、~/.ssh以下にたくさんキーがあったり、エージェントに多数のキーを登録したりしている状況で必須になってくる。 鍵ファイルが増えてくると必然的に発生するので、基本的にIdentityFileとセット運用してつけておくのが安心。

Windowsパスでのチルダ

~はunixシェルの場合シェルが解釈するのでプログラム側には依存しない。

で、その上でなのだけど、sshは設定に書かれた~を解釈するが、ssh-keygenは解釈しない、らしい。 確かめていないが、これのせいでWindowsの話が複雑に。

悪いのは、シェルが展開しないWindowsである。

sshd_configの安全設定

正直なところ、安全な鍵を使っていれば鍵が漏洩しない限りOpenSSHの公開鍵認証を突破される可能性は皆無と言って良い。

AnthenticationMethods publickey

は認証を公開鍵認証のみにするため、これだけで十分安全である。

DenyUsers root

はどちらかというと攻撃に対する負荷軽減のためというのが大きい。

PasswordAuthentication認証方式passwordのみに影響するわけではない。 そして、これをnoにすれば安全ということでもない。 AuthenticationMethodspublickeyのみである場合、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を使って仕事をすることになる可能性は本当に低いので、詳しい説明をする必要はないと判断した。