プロジェクト

全般

プロフィール

Gitの使い方

ここでは、複数開発者がソースコードを共同で作成する現場を想定し、典型的な作業手順を整理します。

構成管理者の初期作業

共有リポジトリの作成

分散型バージョン管理でも、マスターとなるリポジトリを1つ設けるのが定番です。そこで、共有リポジトリを設けます。
共有リポジトリはhttp/https/ssh/gitプロトコルでアクセスできるサーバーに置きます。

開発者がLinuxを使っているなら、sshプロトコルを使った利用が一番簡単かもしれません。
http/httpsプロトコルの場合、参照は簡単ですが変更のpushには仕掛けが必要となります(WebDAVまたはCGI)。
gitプロトコルの場合、gitサーバーをサービス起動させます。

詳細は今後記述予定

空のリポジトリ

空のリポジトリをcloneしてファイルを登録してpushすると、ブランチ指定が必要になります。なので、管理者が初期リポジトリを作成するときはファイルを少なくても1つ登録した状態にしておくのがよいです。

無視ファイルリストの作成

プロジェクトで決めた無視ファイルの定義を作成しておきます。
開発に使用するツール特有のバックアップファイル、一時ファイル、個人ファイルや、コンパイルにより生成される中間ファイルなど、リポジトリに登録して管理するのに不都合なファイルはあらかじめパターン定義しておきます。

  • #で始まる行はコメント
  • !で始まる行は残りのパターンを否定
  • /で終わる名前はディレクトリにのみ合致
  • /で始まる名前はルートディレクトリから指定
  • /がどこにも含まれない名前はシェルのglobパターンでファイル名のベース部分に合致
例を次に示します。
パターン 内容
*~ ファイル名の末尾に'~'がある全て
*.[ao] 拡張子がaまたはoのファイル
tango/ tangoディレクトリは無視
victor ファイル名victorは無視
!*.sierra 拡張子sierraのファイルは無視しない
  • http://gitignore.io/
    OS、言語、統合開発環境(IDE)の名前を入力すると、その典型的な無視ファイルリストを生成するWebアプリケーションです。

開発者の作業

記載見直し中

開発者の作業は大きくは次となります。

  1. 共有リポジトリをcloneして個人リポジトリを作成する
  2. 個人リポジトリに変更を加える
  3. 個人リポジトリの変更を共有リポジトリに登録する(トピックブランチ)
  4. (レビュー者が内容を確認する)
  5. トピックブランチの内容をmasterブランチにマージする

個人リポジトリはいくつ作ってもよいので、気軽に作成するのがお勧めです。
個人リポジトリを変更する分には共有リポジトリには影響を与えないので、好きなだけいじりまわせます。試行錯誤のブランチをいくつも作成したり、いらない変更を破棄したり、

ここでは、リポジトリ運用ポリシーがトピックブランチを要求する場合での作業を記載します。

共有リポジトリをcloneして個人リポジトリを作成する

cloneすることで、共有リポジトリのその時点のコピーが作成されます。一緒に作業ツリーも展開されます。

手順

例えば開発タスク#194に基づく変更を加える場合、共有リポジトリのmasterブランチをクローンし、トピックブランチを作成してそこへ移動します。
トピックブランチの命名規則はここではfeature/#チケット番号とします。ブランチ名でのスラッシュはディレクトリ区切りではなく、単なる文字として扱われます。

  • 共有リポジトリのmasterをクローン
    ~$ mkdir work
    ~$ cd work
    work$ git clone http://repo.example.com/git/golf
    work$ ls
    golf
    work$ cd golf
    golf$ git branch -a
    * master
    golf$
    
  • トピックブランチを作成してそこに移動
    golf$ git checkout -b topic/#194
    golf$ git branch
    * topic/#194
      master 
    golf$
    

個人リポジトリに変更を加える

gitは、作業ディレクトリの変更を直接リポジトリにコミットするのではなく、作業ツリーの変更をいったんインデックス(ステージングエリア)と呼ばれる領域に上げて、ついでインデックスの内容をリポジトリにコミットします。
subversionに慣れている人が感でgitを使うと、このあたりが混乱するのではと思います。

変更したファイルをインデックスに上げる

golf$ git add src/golf/Model.java
golf$ git add conf/golf/Model.conf
golf$

新規ファイル、変更ファイルはgit addでインデックスに上げます。

ファイルの削除

ファイルを削除するときは、git rmでインデックスに削除指示を上げます。

ファイルの移動(名前変更)

ファイルを移動・名前を変更するときは、git mvでインデックスに移動指示を上げます。

コミットする内容を事前確認する

インデックスに上げた各種変更を確認するときは、git diff --cachedを実行します。

インデックスに上げられた変更内容を一括コミットする

インデックスに上げられた内容を一括コミットするときは、git commitを実行します。

個人リポジトリの変更を共有リポジトリに登録する(トピックブランチ)

トピックブランチにおいて変更に関する一連の作業が完了した段階で、その変更をトピックブランチとして共有リポジトリに登録します。
トピックブランチは個人リポジトリで作成したので、最初はリモートへの対応付けを明示的に指定してpushします。

golf$ git push origin topic/#194
  :

originは、このリポジトリをcloneした元の共有リポジトリを指しているので、そこへブランチを指定してpushします。

実はブランチ名の指定は省略形となっています。実際には、ローカルのブランチ名:リモートのブランチ名 と指定します。コロンのどちらかは省略可能で、右側を省略する際はコロンも省略可能です。省略時は同じブランチ名が指定されたとして扱います。この例では、ローカルにあるブランチ「topic/#194」を、リモートにブランチ名「topic/#194」としてpushすることを指示しています。

トピックブランチの内容をmasterブランチにマージする

masterブランチへ移動し、最新版を反映

最初にmasterブランチを最新にしておきます。

golf$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

golf$ git pull
  :
golf$ git merge 

ここで、ブランチに変更(作業途中の未コミットファイルなど)があるとcheckoutでブランチを移動できません。作業完了させてきれいにしてからブランチを変えてください。

個人リポジトリ上でトピックブランチの変更をmasterブランチにマージ

golf$ git merge --no-ff topic/#194

--no-ffを指定するかどうかは運用のルールによります。マージしたことを記録に残す運用であれば指定します。デフォルトは--ffなのでブランチで作業した個々のコミットがそのままmasterブランチに対するコミットのように見えます(履歴が一本化)。

トピックブランチの削除

記念に残しておいてもよいですが、特に共有リポジトリ側はトピックブランチが増えてくると手間なので用済みになったら削除します。

ローカルのトピックブランチの削除
golf$ git branch --delete topic/#194
Deleted branch topic/#194 (was 1b0c4fa).
  • --delete は、省略形 -d でも可
  • マージしていないブランチはこのオプション指定では削除できない
共有リポジトリ(リモート)のトピックブランチの削除
golf$ git push --delete origin topic/#194
To http://www.torutk.com:8008/git/swe.primus
 - [deleted]         topic/#194

または、git push origin :topic/#194

マージ済みかどうかを調べる

メインのブランチ(トピックブランチをマージする先)をチェックアウトし、次のコマンドを実施するとマージ済みのブランチが表示されます。

$ git branch --merged
topic/#194
* master

マージしていないブランチを表示することもできます。

$ git branch --no-merged
topic/#181
topic/#197
hello_bra

トピックブランチ作業中にmasterが進んでしまった

masterからトピックブランチを生成し、開発作業をしている間に、masterのコミットがどんどん進んでしまい、ローカルリポジトリでトピックブランチを最新masterにマージしようとすると多数のコンフリクトや矛盾が発生します。

対処方法がいくつか想定できます。

  • 最新masterをトピックブランチにマージし、最新masterを反映したトピックブランチにアップデート
  • トピックブランチをrebase

どちらも多数のコンフリクト、矛盾をトピックブランチ開発者が整合させます。

こんなことできないかな?

ブランチを変更する

masterブランチを別なブランチとして、新たにmasterブランチを開始したい

まだ変更をコミットしていないならば、masterブランチのHEADでブランチを作成し、ブランチにチェックアウトしてから変更をコミットします。

もしmasterブランチに変更をコミットしていたら、Gitのブランチ名を変更するコマンドで対応できます。

  • 既存のmasterブランチを別名に変更します。
  • 本来masterとしたい出発点のレビジョンでブランチmasterを作成します。

ブランチの変更をなしにする

変更した管理下のファイルを元に戻す

git reset --hard HEAD

  • --hard はステージ、作業ディレクトリの変更も戻す

未追跡のファイルとディレクトリを削除する

git clean -fd

  • -f は削除実行指定
  • -d はディレクトリを削除対象

コミットを戻す

git reset --hard HEAD^

  • HEADにハット記号(^)を1つ付けた場合、HEADの一つ前のコミットに戻す


約2ヶ月前に更新