at posts/single.html

Subversion ユーザーが GitHub を使ってみたよ (その1: 自分のプロジェクト編)

目次

書いていたら長くなったので、複数の日記に分けて書く。

GitHub とは

GitHub は自分のリポジトリを公開できるサービス。 Twitter のように他の人を follow して、その人がどんなコードを公開しているのかを知ることもできる。 最近では多くのオープンソースプロジェクトが GitHub にホスティングしているので、ちゃんと使い方を覚えておきたいところ。 tDiary の開発用リポジトリも GitHub に移行したしね。

Git や GitHub を使ってみて分かったのは、まずは利用シーンに合わせた使い方「だけ」を覚えることが重要ということ。 Git はコマンドの種類が多いんだけど、いちどに全部を覚えようとすると大変。 便利なコマンドは慣れてから覚えるとして、最初は基本的な操作ができればいいやという気持ちでちょうどいい。

公開リポジトリが1つの場合の構成

まずは、自分で作ったプログラムを公開する場合から。 たいていは1つの公開リポジトリをGitHub上に用意して、そのリポジトリへ1台以上のPCからアクセスする。 集中リポジトリ型の Subversion と似た使い方になるので、最初はこの形態が取っつきやすいだろう。 なお、 GitHub では最近 organizationsという、1つのリポジトリをみんなで使う仕組みが提供された。 参加者が限られているのであれば organizations でも同じ構成になるだろう。 また、 GitHub で公開されている他人のプロジェクトを使いたいだけという時は、この図から git push を除いたフローになる。 (参考: github で人のコードをいじる「前」にforkする必要はない

GitHub 上に新しいリポジトリを作るには、トップページの右側にある "New Repository" をクリックする。 リポジトリ名や説明を入力すると、 GitHub 上にリポジトリが作られる。 Subversion での svnadmin create と同じイメージ。

初期設定

「GitHub 入門」でググったら、1年前の日記 (GitHub を使ってみた) が出てきた。 僕はこの時に初期設定を済ませちゃったけど、まだな人は英語なんてわかんねーよ!!ってな人へ贈るGithub入門 for MacOSを読んでおけばOK。

主な作業は以下のとおり。

  • git のインストール
  • git コマンドでのユーザ名とメールアドレスの設定
  • GitHub へのアカウント登録
  • GitHub で使うアイコン画像の登録(任意)
  • 公開鍵の登録(公開鍵を持っていない人は鍵ペアの作成から)

リポジトリの複製 (git clone)

GitHub に作成したリポジトリを自分の PC へ複製するには、 git clone コマンドを使う。 Subversion では svn co <リポジトリのURL> でリポジトリをチェックアウトするのと同じ。 ただし、 Git は分散バージョン管理システムなので、チェックアウトではなくリポジトリそのものがコピーされる。

$ git clone git@github.com:machu/test.git
Initialized empty Git repository in /Users/machu/work/test/.git/

GitHub では1つのリポジトリに対して、3種類のプロトコルでのアクセス方法がある。 自分のリポジトリの場合は SSH を選択する。 HTTP と Git Read-Only はいずれも読み込み専用。 Git Read-Only のほうが効率がよい。

  • SSH (git@github.com:machu/test.git) … リポジトリへの読み書きが可能。他人のリポジトリでは(アクセス権が与えられていない限り)選択できない。
  • HTTP (https://machu@github.com/machu/test.git) … リポジトリへの読み込みが可能。書き込みはできない。
  • Git Read-Only (git://github.com/machu/test.git) … リポジトリへの読み込みが可能。書き込みはできない。

リモートリポジトリ (GitHub) への反映 (git push)

git clone でローカルに複製したリポジトリに対して、ファイルを編集する。 ローカルでの操作は基本操作編を参照。 ローカルといえどリモートのリポジトリと何も変わらないので、 git commit や git diff で操作できる。 このときの操作はローカルで完結していて、リモート側のリポジトリへは影響を与えない。

作業が一段落したら、 git push コマンドを使ってローカルのリポジトリへの変更を GitHub 側のリポジトリへと反映させる。

$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 209 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:machu/test.git
 * [new branch]      master -> master

リモートリポジトリ (GitHub) からの取得 (git pull)

GitHub への反映には git push を使ったけど、逆に GitHub から最新のコミットを取得するには git pull を使う。 Subversion でいう svn update と同じ。 2台以上のマシンで開発する場合は、 git pull で GitHub から最新のコミットを取得し、ローカルで修正し、 git push で GitHub へ反映するというフローになる。

$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From github.com:machu/test
 + db57cb3...a68e87c master     -> origin/master  (forced update)
Auto-merging a
Merge made by recursive.

ローカルとリモートで別々に修正していると、自動的にファイルがマージされる。 同じ箇所を編集するなどでマージに失敗すると、手動でマージしないといけないのも svn update と同じ。

リモートリポジトリ origin とデフォルトブランチ master

注意深く読んでいた人は気がついたかもしれないけど、 git push で GitHub へ反映するときに origin と master という2つの引数を指定している。

$ git push origin master

git push の書式は以下の通り。

$ git push <リモートリポジトリ名> <ブランチ名>

つまり、先ほどのコマンドは origin というリポジトリに master というブランチを push してね、という命令になる。 Subversion はリポジトリが1つなのでわざわざリモートリポジトリ名を指定する必要はないけど、 Git は複数のリポジトリと連携するためにリモートリポジトリ名を指定する必要がある。

origin というのは、複製元リポジトリ (今回は git@github.com:machu/test.git) の別名。 git では clone コマンドでリポジトリを複製したときに、自動的に複製元のリモートリポジトリ名に origin という別名が付けられる。 Subversion ではリポジトリの指定に URL を入力しなければいけなかったけど、 Git では別名を付けることで入力を短くできるようになっている。 そのため、以下のようにリポジトリ名をそのまま書いても、同じ意味になる。

$ git push git@github.com:machu/test.git master

master は git でのデフォルトのブランチ名。 Subversion での trunk に相当する。

git でのブランチとリポジトリ

ところで、 git pull の時は git pull origin master と指定していなかった。 実は git push origin master も、2回目からは git push とだけ指定すればいい。 git push で引数を省略すると、ローカルリポジトリとリモートリポジトリの両方にあるブランチを対象に push を実行する。 最初の git push でリポジトリとブランチ名を明記したのは、最初はリモートのリポジトリに1つもブランチが存在しないから。 1回目の push で GitHub 上にも master ブランチが作られるので、 2回目以降はブランチ名を指定しなくてOKになる。

なんだか細かい話だけど、新しいブランチを作ってリモートリポジトリにコピーする場合に、この原理を知っておくと迷わずにすむ。

$ git checkout -b bugfix  # bugfix ブランチを作成
(bugfixブランチでの作業)
$ git push origin new_branch   # bugfix ブランチをリモートリポジトリに push (初回のみブランチ名の指定が必要)

また、リモートリポジトリのブランチを削除する場合にも、 git push コマンドを応用する。ブランチ名の前のコロンに注目。

$ git push origin :new_branch

このコマンドはかなり分かりにくい。 ここで解説すると長くなるので、興味があれば Pro Git のリモートブランチの削除や入門 Git の P.222 を参照。 とりあえずは暗記でもいいと思う。

リモートリポジトリの情報を見る

origin と実際のリポジトリ名の対応は、 .git/config ファイルに書かれている。 url の値が origin に対応するリポジトリ名になる。

[remote "origin"]
        fetch = +refs/heads/*:refs/remotes/origin/*
        url = git@github.com:machu/test.git

また、 git remote コマンドで、リモートリポジトリの情報を確認できる。 これは svn info に似ている。

$ git remote show
origin
$ git remote show origin
* remote origin
  Fetch URL: git@github.com:machu/test.git
  Push  URL: git@github.com:machu/test.git
  HEAD branch: master
  Remote branches:
    master tracked
    new    tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local refs configured for 'git push':
    master pushes to master (up to date)
    new    pushes to new    (up to date)
ここまでのまとめ
  • 基本操作は git clone (svn co), git pull (svn update), git push (svn commit) の3つだけ
  • 複製元のリポジトリには origin という別名が付けられる (git remote show origin で情報を見られる)
  • デフォルトのブランチ名は master (subversion の trunk に相当)

関連する日記