第27回 長岡開発者勉強会に行ってきたよ(Git入門編)

Git入門編の内容まとめ。なかなか長いよ!

キーノート「Gitとは?そしてイベント趣旨」 @masaru_b_cl

今回のイベントとGitについての簡単な説明。

Niigata.scmに関して

新潟を拠点とするソフトウェア構成管理を扱うコミュニティ。
今回のためにでっち上げたらしいw
今後はビルドやCIなども扱って行きたいそうな。
@dictavさん、@civicさんもメンバー。メンバーなりたい方はお気軽にNiigata.scmまで。

Gitに関して
  • Gitの起源
  • Gitの特徴
  • Gitの利点
  • Gitの学習法

についての説明をしていただきました。以下は省いたところもあり。

Gitの特徴
  • DVCS
  • コミットは変更できない
  • リビジョンがSHA-1ハッシュ値
  • ブランチ、タグはポインタ
Gitの利点
  • 高速にブランチングできる
    • 作業単位にブランチ作成
    • ブランチで適宜コミット
    • メインラインにブランチをマージ
  • トピックブランチの利点
    • ブランチングをサポートするサブコマンド
      • git-now
      • git-master
      • git-flow
  • 各種コード共有サービス
    • github
    • bitbucket
    • Backlog
    • CodePlex
    • Google code
      • githubは公開用
      • bitbucketはプライベート用
      • という風に使い分けると良い(bitbucketは無料でプライベートリポジトリ作り放題)
Gitの学習法
  • 読書駆動学習
    • 入門Git
    • Gitポケットリファレンス
    • ProGit

入門Git

入門Git

Gitポケットリファレンス

Gitポケットリファレンス

導入セッション「Gitの基本操作など」 @dictav

いよいよGitの基本的な使い方についてのハンズオン。

ユーザ名とメールアドレスの設定

最初にユーザ名とメールアドレスの設定をしました。コマンドは以下の通り。

$ git config --global user.name (ユーザ名)
$ git config --global user.email (メールアドレス)

まあ、これは大抵の人は.gitconfigに既に書いてたんじゃないかなーと。
ここでconfigのオプションについての説明。

$ git config [--global|--system] --list
  • system
  • global
    • $HOME/.gitconfigに書き込まれる

で、上記では--globalを指定したので.gitconfigに書き込まれてます。

ヘルプの参照方法
$ git help

サブコマンドのヘルプが見たいときは

$ git help commit

とか。

$ git commit --help

とかでも確か見れて、これらの違いは前者がHTMLのヘルプが表示され、後者がヘルプが標準出力に出力される、とかっていう違いだったと思う。
まあ、必ずしもそうだった訳じゃなかったと思うけど。

リポジトリを初期化
$ mkdir test
$ cd test
$ git init

私は面倒なので

$ git test
$ cd test

とかやったり。大して変わらないけども。

状態遷移・リポジトリへコミット
  1. 作業ディレクト
  2. ステージングエリア
  3. リポジトリ

作業ディレクトリにファイルを作る・更新するということをして、addをすることでステージングエリアに移動し、commitで最終的にリポジトリに格納される。
というわけで先ほど作成したリポジトリに適当なファイルをコミットする。

$ echo 'test' > test.txt
$ git add test.txt
$ git commit -m "first commit"

コマンドの各行が最初に書いた、作業ディレクトリ・ステージングエリア・リポジトリに対応してますな。

ライフサイクル・状態の確認
  • 追跡されていない (untracked)
  • 変更されていない (unmodified)
  • 変更されている (modified)
  • ステージされている (staged)

ファイルのそれぞれのライフサイクルについて。


作業ディレクトリに追加しただけだとuntrackedな状態。
なのでaddでstagedな状態にし、コミットすると追跡されるようになる。


コミット直後は変更されていないのでunmodifiedな状態。
そこから変更を加えるとmodifiedな状態になるので、addでstagedな状態にしてコミット。


あと、rmなどをして追跡しないようにした場合にuntrackedな状態になる。


これがずっとくるくる回る。


現在、ファイルの状態がどうなっているのか確認するのが以下のコマンド。

$ git status

一連の流れをコマンドにすると……(出力は省略)

$ touch piyo
$ git status # untrackedな状態
$ git add piyo
$ git status # stagedな状態
$ echo 'piyo' > piyo
$ git status # staged + modifiedな状態、`echo 'piyo' > piyo`をする前の状態でstagedになっているため
$ # ここでコミットするとecho 'piyo' > piyoの結果が反映されるまえの状態でコミットされる
$ git add piyo
$ git status # stagedな状態
$ git rm piyo
$ git status # untrackedな状態

こんな感じ。記憶で書いたから間違ってる気がする。
この点、Mercurialは楽だなあと思った……だって最初にファイルをaddしたら、あとは気にせずcommitすれば良いのだもの。

ログの参照・時間を行き来する

コミットログを見るには:

$ git log

でログが見れる。


一つ前のコミットに戻るには:

$ git reset --hard HEAD~ # もしくはHEAD^

で作業ディレクトリが一つ前のコミットの状態に戻る。
ログを見ると、一つ前の状態に戻る前のコミットが表示されなくなる。


今までのHEADの移り変わりを見るには:

$ git reflog
ac99b28 HEAD@{0}: commit: change test.txt
25009ef HEAD@{1}: clone: from /Users/sasaplus1/Work/test

を実行すると一覧が表示される。
resetをする前の状態に戻る場合、

$ git reset --hard HEAD@{1}

になるはず。
今までこれを知らなかったので「resetする前の状態に戻れないじゃん!うそつき!」とか思ってた。


resetコマンドの--hard, --soft, --mixed(前者2つを指定しない場合はこれが指定される)の効果は宿題に。
後で調べるかなー。

コミット時のメッセージの書き方

コミット時はcommit -mでメッセージを指定していたが、推奨される書き方としては

$ git commit # エディタが起動する
1行目に簡易なメッセージを
2行目は空業
3行目以降に詳細なメッセージを記述

するのが良い。それと、メッセージはUTF-8なのでWindowsな人は気をつけると良い、とか。
他にChangelogの参考テンプレートなど。Changelogのための英文テンプレート集 - ぴょぴょぴょ? - Linuxとかプログラミングの覚え書き -

リポジトリのクローン・プル・プッシュ
$ git clone [url]
$ git pull
$ git push

initせずに、既に存在するリポジトリを持ってくる場合はcloneを、
変更点を持ってくる場合はpullを(そういえばfetchは……)、
変更点を渡す場合はpushを使う。

演習:Niigata.scmのサイトを作ろう

ここで演習として、Niigata.scmのサイトを作ろうというお題が。


クローンしてきたリポジトリに、

  1. 今回の参加者として自分のプロフィールページを作成
  2. そのページにプロフィール一覧ページからリンクを貼る

という作業をした後、コミット・プッシュをするという演習。


これを"ブランチを使わずに"20人でよってたかってやったおかげでログがめちゃくちゃにw
自分のプロフィールページを作るのは簡単なのだけど、一覧ページを編集してpushすると
pullしろ、と言われpullするとコンフリクトしてるからマージしろと言われ……
pushすると既に更新されていて、pullしろ(ry
_人人 人人_
> push地獄 <
 ̄Y^Y^Y^Y ̄


まあ、有識者の方々の活躍により、なんとか収束?しました。

ブランチ

ブランチの確認・作成について。

$ git branch
* master

これはmasterブランチしか存在せず、masterブランチで作業していることを表している。

$ git branch hotfix
$ git branch
  hotfix
* master

これでhotfixブランチが作成される。これだけだと作成されただけなので、hotfixブランチで作業する場合は、

$ git checkout hotfix
Switched to branch 'hotfix'
$ git branch
* hotfix
  master

となる。
ちなみに、ブランチの作成と切り替えを同時に行なうには、

$ git checkout -b hotfix

と実行する。


ブランチが必要なくなり、削除したい場合は

$ git branch -d hotfix

とする。

リベース

文章で説明するの難しい、というか自分が完全に理解してないからかも。

$ git rebase master
# コンフリクト解消
$ git commit
$ git rebase --continue

という謎のメモが残っている。

$ git init aaa && cd aaa
$ touch aaa
$ git add .
$ git commit -m "add aaa"

$ git checkout -b topic
$ touch bbb
$ git add .
$ git commit -m "add bbb"

$ git checkout master
$ touch ccc
$ git add .
$ git commit -m "add ccc"

ここで

$ git checkout topic
$ git rebase master

とするか

$ git merge topic

とするかで歴史が変わる。
前者はrebaseするため、masterの最新のパッチ扱いにするので歴史が直線になり、
後者はmergeするため、topicブランチをマージする分、歴史が枝分かれする。


トピックブランチの場合はrebaseを、バグフィックスブランチの場合はmergeを
という使い分け方が良い。(と言っていたような気がする)
歴史をどうしたいかによって使い分けるのが良いのかも。

その他

濃い内容のハンズオンだった。これでGitアレルギーもなくなったかも?
あとSourceTree便利、ツリー見るの楽しい。Ubuntuでもそういうの探したい。


今回の座席とTwitterアカウント:
http://www.seatnext.com/v/iHyRW3je