最終更新日

バージョン管理システム Git の使い方

… 最初にここは読んで下さい。あとは必要に応じて読んで下さい。

はじめに

Git はファイルのバージョンを管理し、 コマンドひとつで必要なファイルのコピーを行なってくれるプログラムです。 Git を利用すれば、以前のバージョンが記録されているので、 間違った更新をしてしまったときや記憶装置の障害があったときなどにも、 以前のバージョンを取り戻すことができます。 また、複数のコンピュータで作業をするときのファイルのコピーにも便利です。

次のようなトラブルを未然に防ぐのに有効です。

同じようなバージョン管理システムと呼ばれているソフトウェアに CVS や Subversion, mercurial (hg), darcs といったものがあります。

一般に、バージョン管理システムは、数人で共同でプログラムを作成するときに、 更新の衝突が起こらないようにするために開発されたものです。 衝突とは、ある人が更新した部分を他の人が(誤って)古いバージョンのものに戻してしまう、 といった現象を指します。 しかし、一人で使っても便利なプログラムです。

バージョン管理システムはリポジトリー(repository・倉庫)と呼ばれる場所に、 以前のバージョンの情報を含めたすべてのファイルの情報を貯蔵します。 バージョン管理システムのなかでも Git は分散バージョン管理システムと呼ばれます。 ネットワークに接続していない環境でも、 各コンピュータがリポジトリーを持っているため、 バージョン管理システムの機能を利用できるという特徴があります。

Git のインストール

学科のサーバーの gin (gin.eng.kagawa-u.ac.jp) や stfile (stfile.eng.kagawa-u.ac.jp) には既に Git がインストールされています。ここでは、Git の Windows 環境でのインストール方法を説明します。

Windows の Git クライアントはいくつかありますが、ここでのお勧めは SourceTree です。

SourceTree を使う場合

Git の GUI をもつクライアントとしては SourceTree をおすすめします。このページから、インストーラーをダウンロードして実行してください。

また、SourceTree から「ターミナル」ボタンをクリックすると、 Git コマンドが使えるコマンドプロンプトを起動できます。

Git for Windows を使う場合

このページから、 インストーラーをダウンロードして実行してください。Git for Windows は Git のコマンドラインのクライアントです。

インストールが終了するとデスクトップやスタートメニューの中に、 「Git Bash」というアイコンができています。これをダブルクリックすると、 Git のコマンドが実行可能なシェル(Windows でいうところのコマンドプロンプト)が現れます。

Cygwin を使う場合

コマンドラインのクライアントを使用する場合、 Windows では、Cygwin に入っている Git を使うこともできます。Cygwin とは Windows 環境に移植された UNIX のソフトウェアを集めたパッケージです。

Cygwin は http://www.cygwin.com/ からダウンロードできます。「Install Cygwin」というリンクをクリックして、 setup-x86_64.exe(64 bit 版の場合)というリンクをクリックすると、 クリックするとダウンロードが始まります。ダウンロードした setup-x86_64.exe というプログラムを実行するとインストールが始まります。 途中 “Choose A Download Site” というところで、追加のファイルを ダウンロードするサイトを選ぶ必要があります。 適当な日本のサイトを選んでおけば良いでしょう。 (ただし、どうも途中でフリーズするサイトがあるようなので、 その場合は一旦キャンセルして、他のサイトでやり直しましょう。)

インストールは基本的に「次へ」を押して行くだけです。ただし途中、 “Select Packages” というところで、 「Devel」のなかの「git」をクリックして、 チェックの入っている状態にしておく必要があります。 また同じところで「Net」のなかの「openssh」もチェックしておきます (すると「openssl」なども同時にチェックの入った状態になるはずです)。

インストールが終了するとデスクトップやスタートメニューの中に、 「Cygwin 〜」というアイコンができています。これをダブルクリックすると、 Git や SSH のコマンドが実行可能なシェル(Windows でいうところのコマンドプロンプト)が現れます。

SourceTree のターミナル、Git for Windows と Cygwin に共通の注意

SourceTree のターミナル、Git Bash や Cygwin の環境では、パスの区切りは Windows 流の「¥」ではなく UNIX と同じ「/」であり、 アルファベットの大文字と小文字は区別されることに注意する必要があります。

Cygwin の場合の注意

また、Cygwin の環境では Windows のあるフォルダ(既定値では C:¥cygwin64¥)をルート(/)としてみなして、 基本的にはその下にあるファイルしか見えないようになっています。 しかし、実は /cygdrive/c という名前で Windows の C:¥ が見えるようになっています。 これを利用すれば「ドキュメント」の下のディレクトリーを Cygwin の Git で管理することも可能です。

日本語などを含むファイル名に関する注意

なお、最近は(文字コードが UTF-8 に統一されてきているため)ほとんど心配ないと思いますが、 Git で管理するファイル名やディレクトリー名に日本語などを使うと、サーバー (UNIX) とクライアント (通常 Windows) の文字コードの違いで文字化けする可能性があります。はじめは安全のため、Git で管理するファイル名やディレクトリー名は英数字など、キーボードから直接打てる文字に限定し、 まずはあまり重要でないファイルで、日本語の入ったファイル名で問題ないか、確認してください。

リポジトリーの作成

ここでは、Git を最初に使う時にしておかなければならない事柄を説明します。

以下では、自分の PC(Git Bash または cygwin)での作業のプロンプトは mypc$ で、 stfile での作業のプロンプトは stfile$ で表します。

SourceTree などの GUI クライアントを使う場合でも、 コマンドラインとボタンとの対応はすぐにわかると思いますので、 以下ではコマンドラインでの使用法を説明します。

リポジトリーの作成(リモートリポジトリーを先に作成する場合)

Git を使うためには何よりも前にリポジトリーを初期化する必要があります。 リモートリポジトリーが必要になることがわかっている場合(他の人と共用したり、 自宅と研究室でファイルを共有したりする場合)、先にリモートリポジトリーを作って、 (その空のリボジトリーを)clone するほうが楽です。その方法は、 ベアリポジトリーの作成(GitHub または Bitbucket)または、 ベアリポジトリーの作成(stfile)と、 リポジトリーのクローンを見てください。

リポジトリーの作成(ローカルリポジトリーを先に作成する場合)

以下の例では、まず自分の PC に Git リポジトリーを作成し、その後サーバー (stfile.eng.kagawa-u.ac.jp)に、gennaiという ユーザーでリポジトリーのクローンを作成しようとしていると仮定します。

Git を使うためには何よりも前にリポジトリーを初期化する必要があります。 初期化は、リポジトリーを作成したいディレクトリーに移動して、 init というコマンドを用います。 例えば、myproject というフォルダでリポジトリーを作成したいときは、 次のようにします。

mypc$ cd myproject
mypc$ git init  

実はこのとき、作業ディレクトリーに リポジトリーの実体の .git と いうディレクトリーができています。リポジトリーはまだ空です。つまり、 履歴を管理しているファイルはまだありません。

その他に以下のようなコマンドを、リポジトリーを作成したときに実行しておくことを推奨します。

mypc$ git config core.filemode false
mypc$ git config core.autocrlf input

前者はファイルモード (rwx) の変更を git が無視するように設定します。 後者は、Windows からファイルをコミットするときだけ、改行コードを変換します。

Git の日常的使用

ファイルの追加

作業用ディレクトリーに新しいファイルを作成しても自動的にはリポジトリーに 登録されません。 ファイルをリポジトリーに登録するためには、 add というコマンドを使います。 ディレクトリーを追加する場合は、 ディレクトリーの中にあるファイルを add する必要があります。

例えば、myproject というフォルダとその中の memo.txt, image.png, photo.jpg を追加する場合は、myproject フォルダに移動して、 次のようなコマンドを入力します。

mypc$ git add memo.txt image.png photo.jpg

なお、実際に新しいファイルがリポジトリーに登録されるのは、この後に git commit を行なう時です。

ファイルのコミット

ファイルを新しく追加したり、ファイルを編集した結果、 作業用ディレクトリーのファイルの方がリポジトリーのファイルより新しくなったとき、 リポジトリーに最新版を登録することをコミットといいます。

mypc$ git commit -a

というコマンドで、更新されたファイルを自動的に検索し、 リポジトリーに登録することができます。 コミットする前にコメントの入力を促すためにエディターが起動されますが、 これが面倒な時は、

mypc$ git commit -a -m "Comment Here" 
のように、-m オプションのあとにコメントを指定します。 ちなみにこのコメント中に日本語を使用する場合、文字コードが UTF-8 になっていることを確認してください。それが確認できない場合は、 文字化けの可能性があるため、日本語を使うことはお勧めしません。 (cygwin の場合、
echo $LANG
として、ja_JP.UTF-8 と表示されれば OK です。また、SourceTree からコミットすると、UTF-8 になるようです。)

.gitignore

C 言語などでプログラムを作成するときの .obj, .exe という拡張子のファイルや、 ΤΕΧで論文を作成するときの .dvi, .aux .log ファイルなどは、 それぞれ .c.tex といった拡張子を持つファイルから生成されるので、 リポジトリーに追加する必要のないファイルです。 これらのファイルが存在すると 「リポジトリーに追加されていないファイルがありますよ」 というメッセージがいちいち出力されるので、 少しうっとうしいことがあります。 そこで、そのフォルダ(今の実行例では myproject フォルダ)に .gitignore というファイルを作成して、 これらのファイルを無視するようにできます。ファイル名の指定には、 下の例のように * を使ったワイルドカードを用いることができます。

.gitignore ファイルの例
*.dvi
*.aux
*.log
*.class
*.obj
*.exe

.gitignore は再帰的に適用されます。つまり、 トップディレクトリーに上のような記述をしておくと、 サブディレクトリーの hoge.exe なども無視されます。

ファイルの削除

余計なファイルをリポジトリーに追加してしまったとき、 ファイルの削除は rm というコマンドを用います。

mypc$ git rm ファイル名  

もちろんファイルを削除した後は、その変更を commit しておきます。

git の管理対象からは外したいけれど、ファイルを残しておきたいときは、 --cached オプションを使います。

mypc$ git rm --cached ファイル名  

ファイルの移動

ファイル名の変更や移動は mv というコマンドを用います。

mypc$ git mv memo.txt data.txt

もちろんファイルを移動した後は、その変更を commit しておきます。

リポジトリーの状況の確認

リポジトリーの状況を確認するためには、status というコマンドを用います。

mypc$ git status

どのファイルが add されていないか、commit されていないか、 などがわかるように表示されます。

リポジトリーの履歴の確認

ログ(過去の履歴)を見るには log コマンドを使います。 次のような形式で、commit したときのメッセージと日時、ハッシュ値が表示されます。

mypc$ git log
commit ad653f345115e12d2645eec1e4a85910d97e7e47
Author: XXXX YYYY 
Date:   Fri Dec 16 00:17:12 2016 +0900

    debug XXX

commit e0f42d5eb270214ddbcf4a194fde017400556286
Author: XXXX YYYY
Date:   Fri Dec 9 23:50:40 2016 +0900

    code cleaning

commit aaaed38c2e3711df09610fc4c912e8d163135c11
Author: XXXX YYYY
…

ハッシュ値というのは上記の ad653f345115e12d2645eec1e4a85910d97e7e47, e0f42d5eb270214ddbcf4a194fde017400556286 などで、各 commit に固有の整数値です。

過去のバージョンの取出し

過去のバージョンのファイルを取り出すためには、 checkout というコマンドを用います。

mypc$ git checkout ハッシュ値

ハッシュ値git log コマンドで得られる、各コミット に固有の整数値です。 ハッシュ値をフルに指定する必要はありません。ハッシュ値の上位の桁の、 他のハッシュ値と区別できるだけの長さを与えれば十分です。

なお、git checkout を用いて、過去のバージョンに戻したとき、 そこから、commit, add などの操作をしないようにします。 ファイルの中身を調べる、ファイルを編集してテストする(ただし、commit しない)、リポジトリー外にファイルのコピーをとる、などに留めてください。 (git のさらに深い知識がないと元の状態に戻せなくなります。)

[重要] 過去のバージョンから、最新のバージョンにまた戻すときは、 次のコマンドを用います。

mypc$ git checkout master

一つ前のバージョンに戻す

過去のバージョンを一時的に取り出すのではなく、直前のコミットを打ち消して、 一つ前のバージョンに戻したいときは revert というコマンドを用います。

mypc$ git revert ハッシュ値

ハッシュ値git log コマンドで得られる、直前のコミットの値です。

revert は直前のコミットをなかったことにするわけではなく、 逆向きの編集をした、という新しいコミットを追加します。

コミットを完全になかったことにして、履歴まで消してしまうコマンド(reset)もあるにはあるのですが、 危険度が高いのでここでは紹介しません。

コミットの訂正

Todo: amend というコマンドを用います。

タグ

ハッシュ値は覚えにくいので、tag コマンドで別名をつけておくことができます。

mypc$ git tag ver0.1

このタグを checkout コマンドなどのハッシュ値の代わりに用いることができます。

リモートリポジトリーの作成

ここまでの話だと、1つのコンピュータで作業をしているので、 ファイルを誤って書き換えてしまった、という場合には対処できますが、 ハードディスクがふっ飛んでしまったという場合には対処できません。 サーバーにリポジトリーのクローンをとっておきましょう。

また、サーバーにリポジトリーを置いておくと、 あるコンピュータで作業をしてリポジトリーを更新し、 別のコンピュータに最新版を取り出して作業を再開する、 といったことが容易になるので、その点でも便利です。

リモートリボジトリーの作成(GitHub または Bitbucket)

GitHubBitbucket など、 Git のリモートリポジトリーの Web ベースのホスティングサービスを利用することができます。 また、 GitLab, GitBucket, などの GitHub クローンを研究室や自前のサーバーにインストールすることも可能です。

現時点では GitHub か Bitbucket をお薦めします。

GitHub や Bitbucket 上にリポジトリーを作成する方法やそれをローカルにクローンする方法は、 それぞれの Web ページに行けばわかるので、ここでは説明を省略します。

ベアリポジトリーの作成(stfile)

(複数人でリポジトリーを共有する場合、stfile に置く方法は、 パーミッションの設定が必要になるので面倒です。 Bitbucket や GitHub にベアリポジトリーを作成することをお勧めします。)

git init --bare

ここではサーバー stfile (stfile.eng.kagawa-u.ac.jp) に リモートリポジトリーを作成します。以下の例では、gennai というユーザーが、リポジトリーをホームディレクトリーの下の gitrepos という(すでに作成済みの)ディレクトリーの下に作るものとします。 stfile にログインして、以下のコマンドを実行します。

stfile$ cd ~/gitrepos
stfile$ mkdir myproject.git
stfile$ cd myproject.git
stfile$ git init --bare 

ここで、--bare はベアリポジトリー (つまり作業用ファイルが置かれていない裸のリポジトリー) を作成するオプションです。

ベアリポジトリーには .git という拡張子をつける慣習があるようです。

この時点では、stfile 上のリポジトリーは空です。

ローカル PC でサーバーの登録

リモートリポジトリーを作成したら、 ローカルPC(mypc)の Git Bash または Cygwin に戻って作業します。 myprojectフォルダに移動し、以下のコマンドを実行します。

まず、あとのキー入力を省略するために、 サーバーリポジトリーの URL などを設定ファイルに記録しておきます。

mypc$ git remote add origin gennai@stfile.eng.kagawa-u.ac.jp:gitrepos/myproject.git 
mypc$ git config branch.master.remote origin
mypc$ git config branch.master.merge refs/heads/master

※または、次の書式も使えます。

mypc$ git remote add origin ssh://gennai@stfile.eng.kagawa-u.ac.jp:22/home/st20XX/gennai/gitrepos/myproject.git 

GitHub や Bitbucket にリモートリポジトリーを作成したときは、 サーバーリポジトリーの URL が Web ページのどこかに表示されるはずです。

このあとで、下に述べる pushをすると、リポジトリーがサーバーにも送られます。

ファイルのプッシュ(最初)

stfileにリポジトリーの最初の内容を転送するには push -u します。 (最初にリモートリポジトリーを作成して、clone した場合は push -u をする必要はありません。)

mypc$ git push -u origin master

これで、これまでローカルに作成していたリポジトリーが、 サーバーにも送られました。

リポジトリーのクローン

サーバー (stfile.eng.kagawa-u.ac.jp や Bitbucket)に置いたリモートリポジトリーをさらに別の PC (yourpc) にクローンしましょう。

yourpc$ git clone gennai@stfile.eng.kagawa-u.ac.jp:gitrepos/myproject.git 

これで、yourpcにリポジトリーと作業ファイルがクローンされ、 この PCで作業を再開することができます。

GitHub や Bitbucket にリモートリポジトリーを作成したときは、 クローンするのに必要なコマンドが Web ページのどこかに表示されるはずです。

リモートリポジトリーの日常的使用

ファイルのプルとプッシュ

ローカルにあるファイルが古く、リモートリポジトリーに最新版がある場合、 リモートリポジトリーから最新版を取ってくる必要があります。 例えば、家の PC で作業して push した結果を大学の PC で取出す場合などです。 この操作を pull と言います。

yourpc$ git pull

というコマンドで、 ローカル PC のリポジトリーと作業用ファイルを最新のものにすることができます。

逆に、ローカルリポジトリーで作業をし、最新版を commit した場合、 その変更をリモートリポジトリーに送る必要があります。 これをするのは、先ほどリモートリポジトリーを作成するときに使用した push コマンドです。

yourpc$ git push

これ以降は、mypc でも yourpc でも

anypc$ git push

で、ローカルリポジトリーに commit した変更をサーバーにも転送し、

anypc$ git pull

で、サーバーのリモートリポジトリーにある変更をローカルリポジトリーにマージすることになります。

競合の修正

このように複数の場所で編集を行なう場合、編集を行なう前に必ず pull をしておきます。また編集をし終ったら必ず commit して push します。 (ただし、中途半端な状態—例えばプログラムに明らかなバグがある状態—で push するのは良くないので、後述するブランチを使います。) もし、編集作業後の commit, push を忘れると、 2つの場所にあるファイルのどちらが最新版かわからなくなってしまいます。

例えば thesis.tex というファイルを mypc で編集し、 commit, push を忘れていたとします。 そのあと yourpc で別の編集して commit し、再び mypc に戻って commit, push しようとすると、Git は次のようなエラーを報告し、 サーバーに push できなくなります。

mypc$ git push
cvs commit: Examining .
To gennai@stfile.eng.kagawa-u.ac.jp:gitbase/myproject.git
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to 'gennai@stfile.eng.kagawa-u.ac.jp:gitbase/myproject.git'

このような時は先に pull します。

mypc$ git pull
gennai@stfile.eng.kagawa-u.ac.jp's password: 
Auto-merging thesis.tex
CONFLICT (content): Merge conflict in thesis.tex
Automatic merge failed; fix conflicts and then commit the result.

すると、上のようにリモートリポジトリーと作業ディレクトリーにあるファイルに 矛盾があることを報告してくれます。このとき作業ディレクトリーにある thesis.tex を見ると、食い違いがあった場所は次のように 「<<<<<<<」と「=======」と 「>>>>>>>」に囲まれた形で示されています。

…
<<<<<<< HEAD:thesis.tex
ABCはDEFである。
=======
ZYXはWVUである。
>>>>>>> 4fa914d097bc5f293edb6c9f6c7d8c29403bc6b8:thesis.tex
…

このときは手作業で修正(どちらかを選択するか、マージするか)して、 「<<<<<<<」と「=======」と 「>>>>>>>」を消し、 改めて commit, push する必要があります。

ブランチの使い方

履歴を枝分かれさせることができます。 安定しているバージョンをメンテナンスしつつ、 変更を行なう場合などに使用します。 “枝”のことをブランチと言います。

複数人でプロジェクトを編集するとき、各個人はブランチを作成して、 そのブランチに対してファイルの編集を行います。そして、修正がまとまってから (例えば、ある機能が完成して、デバッグも一通り終えてから) “幹”にマージします。このやり方で、 他の人に中途半端な状態を見せないようにすることができます。

最初にもともとできているブランチには master という名前がついています。

ブランチの確認

次のコマンドで現在のブランチを確認できます。

mypc$ git branch

新しいブランチの作成

mypc$ git checkout -b ブランチ名

これで新しいブランチを作成すると同時にそのブランチに移動します。

ブランチの移動

ブランチを移動するには、以下のコマンドを使います。

mypc$ git checkout ブランチ名

新しいブランチをプッシュ

最初だけは、リモートリポジトリーの名前 (origin) とブランチ名を指定する必要があります。

mypc$ git push origin ブランチ名

これでリモートリポジトリーにも新しいブランチが作成されます。

2回目以降は単に、git pushで構いません。

mypc$ git push

リモートブランチのチェックアウト

pull ではなくて、checkout を使うことに注意してください。

まず fetchコマンドを用いて、リモートリポジトリーの内容をローカルに持って来ます。

yourpc$ git fetch

次に、通常の checkout コマンドで新しく取ってきたブランチに移動します。

yourpc$ git checkout ブランチ名

ブランチのマージ

ブランチでの修正がまとまったら、“幹” にマージします。

merge というコマンドを使用します。以下の例は、master ブランチにマージする場合です。

mypc$ git checkout master
mypc$ git merge ブランチ名

その他

Eclipse からの Git の利用法

Eclipse のプロジェクトを Git リポジトリーに入れるときは、以下のような理由から、 リポジトリーのルートディレクトリーそのものを プロジェクトディレクトリーにするのではなく、 リポジトリーのルートディレクトリーの子ディレクトリーとして プロジェクトディレクトリーを作るほうが良いです。 (つまり、.git というディレクトリーと同じ階層に、 プロジェクトディレクトリーがあり、その下に .project というファイルができる。)

リポジトリーのルートディレクトリーそのものをプロジェクトディレクトリーにしてしまった場合は、 新しくサブディレクトリーとして、プロジェクトディレクトリーを作成し、 git mv コマンドを使って、リポジトリーのルートディレクトリーの直下の .git 以外の各ファイルを新しく作成したサブディレクトリーの下に移動します。

複数のリポジトリーを一つにまとめるには

もともと別々のリポジトリーとして管理していたファイルを一つにまとめたくなるときもあります。 ここでは、あるリポジトリー A のサブディレクトリー dir に、別のリポジトリー B の内容をまるまる持って来ることにします。

(まず、必要ならば、まとめ先のリポジトリー A のディレクトリー構成を変更しておきます。)

次のコマンドでサブディレクトリー subdir に、リポジトリー B の master の内容がコピーされます。

git subtree add --prefix=subdir the_path_or_url_of_B_repository master

このあとで、また必要に応じてディレクトリー構成を整えます。

おわりに

ここで説明した事柄で Git の利用法の 95% は説明できていると思います。しかし、 いざというときにはもっと高度な使い方が必要になります。 こういう使い方を知りたい場合は、以下のリンクや本を参考にしてください。

ToDo

以下の話題については、状況が整いしだい内容を追加する予定です。

日本語でコミットログを入力するときの注意


Koji Kagawa