Git 入門
Elementryどの開発者にも経験がある — 何かを変えたら何もかも動かなくなって、何をしたか思い出せない、あの沈む感覚。Git はそんな気持ちを二度と感じないようにするためのツールだ。コードに加えたすべての変更の完全な履歴を保持し、恐怖なく自由に実験でき、他の開発者と一緒に作業することを格段に楽にしてくれる。
Git とは何か
Git はバージョン管理システム(version control system)だ — 時間の経過とともにファイルの集合に加えたすべての変更を記録するソフトウェアだ。プロジェクト全体の非常に詳細な「元に戻す履歴」として考えると分かりやすい。いつでも確認したり、共有したり、巻き戻したりできる。
頻繁に目にするいくつかの用語:
- リポジトリ(repository)または リポ(repo)とは、Git が追跡しているフォルダとその変更の完全な履歴のことだ。
- コミット(commit)とはプロジェクトの特定の瞬間の保存済みスナップショットだ。
- リモート(remote)はリポジトリの別の場所(通常はサーバー)に保存されたコピーで、チームで共有する。
初めて Git をセットアップする
最初のコミットをする前に、Git に自分が誰かを教える。作成したすべてのコミットに名前とメールアドレスを付けるので、他の人が各変更を誰がしたか見られる。
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
一度実行すると Git がマシン上で覚えてくれる。--global フラグは設定が一つの特定のプロジェクトだけでなく、使用するすべてのリポジトリに適用されることを意味する。
リポジトリを取得する
既存のリポジトリをクローンする
最も一般的な出発点はクローン(cloning)だ — 完全な履歴を含む既存のリポジトリをマシンにダウンロードする。
git clone https://github.com/some-user/some-project.git
これにより、すべてのプロジェクトファイルを含む some-project/ という新しいフォルダが作られる。クローン元の URL は自動的に origin という名前のリモートとして保存されるため、Git は後で変更を送受信する場所を知っている。
新しいリポジトリを始める
最初からプロジェクトを始める場合は、プロジェクトフォルダに移動して実行する:
git init
Git はそのフォルダの追跡を開始する。次に、GitHub や GitLab などのホスティングプラットフォームでリポジトリを作ってから、手動でリモートを追加する必要がある(詳しくは下記)。
リモートでの認証
Git がプッシュ、プル、またはプライベートリポジトリのクローンのためにリモートと通信するとき、サーバーは誰であるかを知る必要がある。主に二つの方法がある。
HTTPS:ユーザー名とトークン
HTTPS の URL は上の git clone の例のようなものだ。HTTPS でプッシュやプルをすると、Git はユーザー名とパーソナルアクセストークン(personal access token、PAT)を求める — プラットフォームの設定で生成する長い文字列だ。GitHub や GitLab を含むほとんどのプラットフォームは何年も前からアカウントのパスワードを直接受け付けなくなった。PAT がその代替だ。
この方法は機能するが、面倒になってくる。プッシュのたびにトークンを入力するかペーストするのは、すぐに排除したくなる摩擦だ。
SSH:標準的なアプローチ
SSH が日常的に開発者が使う方法だ。トークンの代わりにキーペアに依存する — マシンに留まる秘密鍵と、ホスティングプラットフォームに一度登録する公開鍵だ。Git がリモートに接続するとき、マシンは秘密鍵を使って自動的に身元を証明する — 入力不要だ。
SSH キーペアの生成とプラットフォームへの登録は SSH 入門 でカバーしている。それが済んだら、HTTPS URL の代わりに SSH URL を使ってクローンする:
# HTTPS — 動くが、プッシュのたびにトークンを求められる
git clone https://github.com/some-user/some-project.git
# SSH — 一度だけのキーセットアップ後はパスワードプロンプトなし
git clone git@github.com:some-user/some-project.git
初期セットアップ後、push と pull は静かに機能する。本格的な作業を始める前にセットアップしておくべき方法だ。
Git が使う三つの領域
この三つの領域を理解することが、Git で混乱しないための鍵だ。加えたすべての変更はこの順序を通る:
- ワーキングツリー(working tree)— コードエディターで編集する、ディスク上の実際のファイル。
- ステージングエリア(staging area、インデックスとも呼ぶ)— 次のコミットに入れる変更を組み立てる保留エリア。
- リポジトリ(repository)— 非表示の
.gitフォルダ内に保存された、すべてのコミットの永続的な記録。
変更はワーキングツリーからステージングエリアに git add で、ステージングエリアからリポジトリに git commit で移動する。
コミットを作る
変更をステージする
まず、次のコミットに含める変更を Git に伝える:
git add main.rs # 一つのファイルをステージ
git add . # 現在のフォルダのすべての変更したファイルをステージ
ステージングによって意図的になれる:三つのファイルを変えたが、そのうち二つだけがこのコミットに属するなら、その二つだけをステージして三つ目は後回しにする。
スナップショットを保存する
ステージされた内容に満足したら、何をしたかを説明する短いメッセージでコミットを作る:
git commit -m "Add greeting function"
良いコミットメッセージは変更を簡潔に現在形で表すものだ:「Fix crash on empty input」、「Add login page」、「Remove unused imports」。明確なメッセージは後でプロジェクトの履歴を理解するのをずっと楽にする。
状況を確認する
作業中に常に使う二つのコマンド:
git status # 変更したファイルとステージされているものを表示
git log --oneline # 最近のコミットのコンパクトな一覧を表示
典型的な git log --oneline の出力は次のような感じだ:
a3f2c1e Add greeting function
b8e0d4a Fix crash on empty input
c12f90b Initial commit
各行が一つのコミットだ。左の短い文字と数字の文字列はコミットのハッシュ(hash)— そのスナップショットに対する Git の固有 ID。右のテキストがメッセージだ。
リモートを操作する
コミットをプッシュする
ローカルにコミットした後、git push でそれらをリモートに送る:
git push origin main
origin はリモートの名前で、main はプッシュ先のブランチ(branch)だ(ブランチについては次のセクションで説明する)。これにより、リポジトリへのアクセス権を持つ他の全員に作業が見えるようになる。
変更をプルする
チームメイトがコミットをプッシュしたら、git pull でそれをローカルコピーに取り込む:
git pull origin main
git pull は二つのステップを一つにまとめたもの:まずリモートから新しいコミットをフェッチ(fetch)して、次にそれらをローカルブランチに適用する。
適用せずにフェッチする
何かを適用する前にリモートで何が変わったか見たい場合は git fetch を使う:
git fetch origin
これはローカルファイルに触れずに Git のリモートの状態の内部的な知識を更新する。何が届いたかを確認して次に何をするか決められる — 何かの途中で予期せぬ pull にフローを中断されたくないときに便利だ。
ブランチ
動いているコードを壊すリスクなく新しい機能を追加したいとする。ブランチ(branch)がまさにその問題を解決する:分岐した時点まで共通の履歴を共有する、独立した開発のラインだ。
リポジトリは常に一つのブランチから始まる — 一般的に main と名付けられる。新しいブランチを作ると、コミットが main に影響を与えない独自の開発ラインが手に入る — 意図的に統合するまで。
ブランチを作って切り替える
git switch -c feature-login # 新しいブランチを作ってそこに一度で切り替える
または二つのステップで行う場合:
git branch feature-login # ブランチを作る
git switch feature-login # それに切り替える
ブランチ一覧を表示する
git branch
横にアスタリスク(*)があるブランチが今いる場所だ。
ブランチをリモートにプッシュする
ブランチが他の人と共有できる状態になったら:
git push origin feature-login
ブランチを統合する
機能が完成したら、その変更をメインブランチに統合する必要がある。一般的なアプローチが二つあり、ほとんどのプロジェクトは一方を一貫して使う。
マージ
マージ(merging)は一方のブランチの変更を別のブランチに統合する。更新したいブランチに切り替えて、そこに別のブランチをマージする:
git switch main
git merge feature-login
Git は二つの履歴のラインを結びつけるマージコミット(merge commit)を作る。後でコミット履歴を見ると、二つのブランチがどこで分岐してどこで統合されたか明確にわかる。
リベース
リベース(rebasing)はよりクリーンな線形の履歴を作る代替手段だ。マージコミットを作る代わりに、最初からそこで書いたかのようにコミットをターゲットブランチの上に再生する:
git switch feature-login
git rebase main
これにより、feature-login のコミットが main の最新コミットの直後に現れ、間にマージコミットがない。履歴は一目で読みやすくなるが、ブランチがいつ分岐したかの記録は失われる。
マージとリベースのどちらが客観的に優れているわけではない — チームが一つの慣習を選んでそれに従うだけだ。プロジェクトに参加したら、すでに何をしているかを確認してそれに合わせる。
Git プロバイダー:GitHub と GitLab {#git-providers-github-and-gitlab}
Git 自体は自分のコンピューターで動くただのツールだ。Git プロバイダー(Git provider)はリモートリポジトリをホストして、その上にコラボレーション機能を重ねるウェブプラットフォームだ。
GitHub
GitHub(github.com)はオープンソースの世界で最も広く使われているプラットフォームだ。Rust のコンパイラー、標準ライブラリ、このカリキュラムを通じて使うほぼすべての公開パッケージが GitHub にある。コードのホスティング以外に、GitHub が提供するもの:
- プルリクエスト(pull request)— 変更を提案してマージ前にチームメイトにレビューしてもらう方法。
- イシュー(issue)— バグ、機能、議論のビルトインのトラッカー。
- GitHub Actions — プッシュするたびにテストを実行したり、ドキュメントをビルドしたり、プロジェクトをデプロイしたりできる自動化されたワークフロー。
GitLab
GitLab(gitlab.com)はソフトウェア開発ライフサイクル全体をカバーする強力な代替サービスだ。GitHub と同じコアのコラボレーション機能 — マージリクエスト(GitLab でのプルリクエストの呼び方)、イシュー、CI/CD パイプライン — を提供し、自分のサーバーにインストールして動かすこともできる。このセルフホスティング機能は、コードをサードパーティのサービスではなくオンプレミスに保ちたい企業に人気がある。
どちらのプラットフォームも同じ Git プロトコルを使うため、clone、push、pull、fetch はどちらを使っても同一に動く。違いはほぼウェブインターフェイスと周辺ツールにある。
まとめ
- Git はすべての変更をリポジトリ内の一連のコミットとして保存するバージョン管理システムだ。
git config --global user.nameとgit config --global user.emailで一度だけ身元を設定する。git clone <url>で既存のリポジトリをダウンロードし、git initで新しいリポジトリを始める。- 変更は三つの領域を通る:ワーキングツリー → ステージングエリア(
git add)→ リポジトリ(git commit)。 git statusで変更されたものとステージされているものを表示し、git log --onelineでコミット履歴を表示する。git pushでコミットをリモートに送り、git pullでリモートのコミットをフェッチして一歩で適用する。git fetchはリモートの変更を適用せずにダウンロードして、まず確認できる。- リモートは HTTPS(パーソナルアクセストークン)または SSH(キーペア)で認証する。SSH が標準的なアプローチで、一度のセットアップ後は認証情報不要だ。
- ブランチで機能を隔離して開発できる。
git switch -c <name>で作って切り替える。 - マージ(
git merge)はマージコミットでブランチ履歴を結合し、リベース(git rebase)は線形の履歴のためにコミットを再生する。 - GitHub と GitLab が Git リポジトリをホストして他者と協力するための最も一般的なプラットフォームだ。
次のステップ
Git をツールキットに加えて、すでに学んだシェルコマンドと合わせれば、すべての開発者が日々の作業で使う基盤が揃った。最初の本格的なコードを書く準備ができている — Rust を学び始めるには Basis シリーズへ。