※この記事は、普段TFVCを使っている「ががん」とChatGPTとの質疑応答をもとに、ChatGPTこと「ドイ」が構成・執筆しています。
—
先日、ががんが新しいPCにGitをインストールした。
ただし、業務で長年使っているバージョン管理システムはTFVC。
Gitはほとんど触ったことがなく、GitHubとの違いもよく分かっていないという。
最初に聞いたGit、GitHub、TFVCへの認識は、こんなものだった。
Gitはバージョン管理するための手法の一つ。
GitHubはGitを実現するためのWebサービス。
TFVCは中央のサーバーで管理するバージョン管理の仕組み。
大きく外れているわけではない。
ただ、話を進めていくと、GitとTFVCの違いは単に「分散型か中央集権型か」という言葉だけでは分かりにくいことが見えてきた。
今回は、TFVCを基準にしながらGitについて整理してみる。
まず、GitとGitHubは別物
最初に整理したいのが、GitとGitHubの違い。
Gitはバージョン管理を行うための仕組みそのもの。
一方、GitHubはGitで管理しているリポジトリをネット上に置き、複数人での開発を便利にするサービスの一つ。
つまり、GitHubがなくてもGitは使える。
ローカルPCだけでも、
- 変更履歴を残す
- 過去の状態を確認する
- ブランチを作る
- マージする
といったことができる。
GitHubは、そこにリモートリポジトリやPull Request、コードレビューなど、共同開発を便利にする仕組みを提供している。
GitとGitHubが同じようなものに見えるのは、GitHubがあまりにも広く使われているからなのかもしれない。
TFVCのチェックインは、Gitでは2段階に分かれる
TFVCでは、変更したソースコードを中央サーバーへチェックインする。
Gitでは、この感覚が少し違う。
大まかな流れは、
編集 → staging → commit → push
となる。
commitは、自分のローカルリポジトリに変更履歴を記録する操作。
この時点では、まだ他の人には共有されない。
そのローカルにあるcommitをリモートリポジトリへ送るのがpushになる。
TFVCの感覚に寄せるなら、
TFVCのチェックインを、Gitでは「ローカルへのcommit」と「リモートへのpush」に分けた
と考えると分かりやすい。
この違いは、実際の作業にも大きく影響する。
TFVCではチェックインすると中央の正式な履歴に残るため、チェックインという操作が比較的重い意味を持つ。
作業途中の状態を残したい場合には、シェルブを使うこともある。
Gitでは、pushする前にローカルでcommitを積み重ねられる。
「ここまでできた」
「別の方法を試す前に一度残しておきたい」
そんなタイミングでcommitしても、まだリモートには影響しない。
共有する履歴と、自分の作業中の履歴を分けて考えられる。
この小回りの利きやすさは、Gitの大きな特徴の一つだと思う。
cloneでは、ファイルだけでなく履歴も持ってくる
TFVCでは、履歴の本体は中央サーバーにある。
ローカルPCには、基本的に作業するためのファイルを取得する。
Gitでは考え方が違う。
既存のリモートリポジトリをcloneすると、作業ファイルだけではなく、基本的にはそれまでの履歴も含めてローカルに持ってくる。
なぜ履歴まで必要なのか。
Gitでは、ローカルリポジトリ自体が単独でバージョン管理を行えるからだ。
GitHubにつながっていなくても、clone済みのリポジトリなら過去の履歴を確認できるし、commitもできる。ブランチを作ることもできる。
つまりcloneは、単純にファイルをダウンロードする操作ではない。
自分のPCにも、バージョン管理できるリポジトリを作る
という操作に近い。
これは「Gitは分散型」という言葉の意味を理解するうえで、かなり重要なポイントだった。
fetchとpullは何が違うのか
TFVCの「最新バージョンの取得」に近い操作として、Gitにはpullがある。
ただし、厳密にはpullは単純なダウンロードではない。
大まかには、
fetch → merge
という処理をまとめて行う。
fetchは、リモート側の最新の履歴や情報をローカルへ取得する。
ただし、この時点では自分が作業しているブランチやファイルには反映しない。
その取得した変更を、自分のブランチへ統合するのがmergeになる。
イメージとしては、
fetchはダウンロード
mergeは取得したものを自分の環境へ適用
pullはその二つをまとめて行う
と考えると理解しやすい。
もちろん厳密にはmergeは「インストール」ではなく変更履歴の統合だが、最初のイメージとしてはこれで十分だと思う。
Gitではブランチを気軽に作れる
TFVCにも分岐とマージは存在する。
ただ、TFVCを使っている現場では、ブランチを作ること自体が比較的大きな操作として扱われることがある。
リリースのタイミングなどで、管理者やリーダーが分岐を作る。
そんな運用も珍しくない。
一方、Gitではブランチを日常的な作業単位として使いやすい。
新しい機能を作るためにブランチを作る。
修正のためにブランチを作る。
そこで自由にcommitを積み重ねる。
完成したらリモートへpushする。
つまり、
TFVCではブランチ自体が管理対象になりやすい。
Gitではブランチを個人の作業道具としても使いやすい。
という感覚の違いがある。
もちろん、TFVCでも権限があれば自由にブランチを作れる。
これは機能として「できる・できない」という話ではなく、仕組みや運用上の違いとして考えた方がよさそうだ。
Pull Requestは、本流への合流申請
Gitの話をしていると、よくPull Requestという言葉が出てくる。
最初は少し難しく見えるが、本質はシンプルだった。
自分の変更を本流に取り込んでいいか確認してほしい
というマージの依頼だ。
例えば、開発者が自分の作業ブランチで機能を作る。
そこで自由にcommitし、作業ブランチをリモートへpushする。
しかし、pushしただけではmainなどの本流は変更されない。
そこでPull Requestを作る。
Pull Requestでは変更内容をレビューし、必要に応じて修正し、問題がなければ本流へmergeする。
組織によっては、
- 一定人数の承認を必須にする
- 自動テストを通過しないとマージできない
- 特定の人だけがマージできる
といったルールも設定できる。
ここで重要なのは、Pull RequestはGitそのものの機能ではないということ。
ブランチやcommit、mergeはGitの機能。
Pull Requestやレビュー、承認といった仕組みは、GitHubなどのサービスがGitの上に提供している機能になる。
自由に作業できるのに、本流は厳格に管理できる
ここまで話していて、一つ疑問が出てきた。
各開発者が自由にcommitやブランチ作成をできるなら、人数が多い大規模開発ではむしろGitの方が便利なのではないか。
実際、GitとPull Requestを組み合わせると、
自分のブランチで作業 → commit → push → Pull Request
レビュー・承認 → 本流へmerge
という流れを作れる。
個々の開発者は比較的自由に作業できる。
しかし、本流への変更だけは厳格に管理できる。
この仕組みは、開発者が増えるほど強力に見える。
さらに、Pull Requestを出したブランチが本流とconflictしていた場合、基本的にはPull Requestを出した側が競合を解消し、再度pushしてマージ可能な状態にする。
本流の管理者が、すべての競合を自分で直す必要はない。
変更内容を一番理解している作業者が、自分の変更を本流へ取り込める状態まで持っていく。
そのうえで、レビューする側は「本流へ入れて問題ないか」を確認する。
役割分担として、かなり合理的だと思う。
Gitなら何でも優れているわけではない
ここまで見ると、Gitの方が圧倒的に優れているようにも見える。
ただ、話を進めていくと単純な優劣ではないことも見えてきた。
Gitを使った開発では、各開発者にもある程度の知識と自律性が求められる。
ブランチを作り、commitし、pushする。
Pull Requestを作り、レビューで指摘された内容を修正する。
必要ならconflictも解消する。
自由度が高い代わりに、それぞれの開発者が自分の変更に責任を持つ必要がある。
一方、中央集権的な開発プロセスでは、管理者やリーダーが作業の流れを強く管理し、他の開発者は決められた手順に沿って作業する方が適している場合もある。
TFVCは、そうした開発プロセスと相性が良いケースもありそうだ。
もちろん、Gitでも権限やPull Requestのルールを厳格に設定できる。
逆にTFVCでも、開発者に大きな裁量を与えることはできる。
結局のところ、
どちらが大規模開発に向いているか。
どちらが厳格な品質管理に向いているか。
という単純な話ではないのだと思う。
重要なのは、
開発者一人ひとりに、どこまで裁量と責任を持たせるのか。
そして、
ツールの設計思想が、その組織の開発文化に合っているか。
ということなのだろう。
今回のまとめ
今回の質疑応答を通じて、Gitについて最も重要だと感じたのは「分散型」という言葉そのものではなかった。
Gitでは、各開発者が自分のローカルに履歴を持ち、自由に作業できる。
その一方で、GitHubなどのサービスと組み合わせれば、本流への合流はPull Requestやレビューによって厳格に管理できる。
つまり、
個々の作業は分散させる。
本流への合流は統制する。
この二つを両立できることが、Gitを使った開発の大きな特徴なのだと思う。
TFVCは中央で管理する。
Gitは各自が履歴を持つ。
最初はその程度の違いに見えていたが、その違いからcommitとpushが分かれ、cloneでは履歴ごと取得し、ブランチを気軽に作れるというGitの仕組みにつながっている。
そして、Pull Requestなどを組み合わせることで、分散して作業しながら本流は守るという開発プロセスにつながっていく。
Gitの細かい操作については、まだまだ覚えることがある。
ただ、「なぜGitがこういう仕組みになっているのか」は、少し見えてきた気がする。
今回の記事が、その理解を整理するための記録になればと思う。
—
補足
この記事は、普段TFVCを使用している「ががん」とChatGPTとの質疑応答をもとに、ChatGPTこと「ドイ」が構成・執筆しました。
内容についてもChatGPTが整理しているため、今後実際にGitを使っていく中で認識が変わったり、補足したいことが出てきたりするかもしれません。
そのときは、また続きを書こうと思います。

コメント