Git と Mercurial
サマリー
- コンセプト
- Git と Mercurial
- Gitについて
- Mercurialについて
- Assignments
コンセプト
ソフトウェアのバージョンコントロールの歴史はそれなりに長く、ソフトの開発や本の執筆やウェブサイト管理などで重要な役割を担ってきました。 以下は、バージョンコントロールの基本的なコンセプトです。
- ファイル群のversion history(バージョン履歴)を記憶し、必要な時にその履歴に戻ることができます
- diff(差分)を記録し、どのファイルのどの行が変更されたのか知ることができること
- 異なるバージョンのファイルをmarge(マージ)によって新しいバージョンに統合することができます
- branch(ブランチ)によってワーキングコピーを作り、ブランチ下でファイル編集し、編集結果をマージしたり、させなかったりすることができます
- commit(コミット)によって新しいバージョンのスナップショットを記録することができます
- ローカルコンピュータやリモートサーバー上のバージョン履歴群のことをrepository(リポジトリ)と呼びます
- リポジトリからファイルをpull(プル)することができます
- push(プッシュ)によってリポジトリを変更できます
- 複数のユーザーが同じファイルの同じ行で編集をするとmarge conflict(マージコンフリクト)が起きます
- コンフリクトの解消、resolveは以下の方法で実施します。
- a) 一人のユーザーから変更を加えて残りを破棄する
- b) ファイルを手動で編集してコミットする
Git と Mercurial
バージョン管理のソフトはたくさんありますが、一番有名なものはSubversion, Mercurial と Gitです。 それぞれ強みと弱みがありますが、世界中でもっとも使われているのはGitでしょう。 Fab AcademyではMercurialも使われており、両方とも覚えておきたいです。
Git と Mercurial の違い
GitはマクガイバーでMercurialはジェームスボンド
Git は分散管理型のVCS(バージョン管理システム),全てのユーザーはプライベートのローカルリポジトリを持っており、それぞれのユーザーが差分を通常はプルリクエスト経由でメインのリポジトリへマージする。
Mercurial は集中管理型, 全てのユーザーはリポジトリのコピーをローカルコンピュータへpullし、差分を中央リポジトリへpushs changesする。 もしその間に誰かがファイルを編集してしまったら、conflictを解消する必要がある。
どちらがよいでしょう?
参考(English):
Gitについて
ソフトのインストール
Gitのダウンロード OSX, Windows, Linux
ローカルリポジトリの作成
ローカルコンピュータ上でフォルダを作成し、 そのフォルダ内でgit initを実行します。
mkdir testing-git
cd testing-git
git init
このように表示されます。
Initialized empty Git repository in /private/tmp/repo/.git/
ファイルの追加
次にファイルを追加し、コミットする方法です。 READMEファイルを作成し、先ほどのリポジトリフォルダへ入れてから以下のコマンドを実行します。
git add README
git commit -m 'Initial import'
このように表示されます。
[master (root-commit) 1bcaa4d] initial import
1 file changed, 1 insertion(+)
create mode 100644 README
NOTE ローカルリポジトリにコミットされたことによってスナップショットが作られました。
それではREADEMEファイルをまた編集してみて以下のコマンドを実行してみてください。
git status
このように表示されます。
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README
最後にコミットした時からの差分がわかります。 さらにどこが編集されたのか細かく見ることができます。
git diff
差分の詳細です。
diff --git a/README b/README
index 9daeafb..2219bed 100644
--- a/README
+++ b/README
@@ -1 +1,2 @@
-test
+test is a test
+test2
先ほどやったようにgit add と git commitすることで履歴(リポジトリ)に反映させることもできますし、編集を破棄することもできます。破棄するには
git checkout -- README
とすると、最後にコミットしたバージョンにロールバックすることができます。
ブランチ
何かの編集(開発)に長い間取り組む必要があって、その編集履歴をメインのリポジトリに反映させるべきか決めかねていたり、何かの機能を開発中のソフトウェアに追加したいけれどもその機能に確信がない時のことなどを考えてみてください。
こんな時はbranch(ブランチ)を使います。 新しくブランチを追加した時、今まで作業していた元のリポジトリはmasterブランチと呼ばれます。
new_featureというブランチを作成したい時はこのようにします
git branch new_feature
今作業しているブランチを確認したい時は
git branch
このようになります。
git branch
* master
new_feature
masterで作業中なのがわかります。 new_featureに移動します。
git checkout new_feature
こう表示されます。
Switched to branch 'new_feature'
これで、新しいブランチで編集作業ができるようになりました。マスターブランチのファイルに影響がなくコミットができます。 最初に作成したREADMEを編集してコミットしたい場合は、またマスターブランチに戻ります。 ブランチで作業した履歴は、マージコマンドで簡単に取り込むことができます。
git merge new_feature
このように見えます。
Updating 1bcaa4d..27efb70
Fast-forward
README | 3 +++
1 file changed, 3 insertions(+)
これで他のブランチで作業した結果が全てマスターブランチに反映されます。
リモートリポジトリ
Gitの素晴らしいところは、ローカルだけではなくインターネット経由でも管理ができることです。サーバーなしでその機能を使うことができます。 そしてremote repositoriesを使って他のユーザーと共同作業をするときなどに安全にデータを保存することができます。
Gitはどのサーバーにもインストールできますし、多くのユーザーはGitHub を使ってオープンソースのプロジェクトを管理しています。
GitHubでアカウントとリポジトリを作成してみましょう。 ローカルのgitプロジェクトをリポートリポジトリに追加することができます。 リポジトリの名前はいろいろなものがありますが、今回はoriginを使います。
git remote add origin https://github.com/(your account)/repo.git
HTTP, SSH, などを使ってリポジトリを追加することもできます。詳しくはGitHubのヘルプを見てください。GitHub help.
このリモートリポジトリにローカルのプロジェクトブランチをpushします。
git push origin master
ブランチがpushされたあとは、他のユーザーや自分でも、リモートリポジトリからローカルにコピーすることができます。これを**cloning(クローンする)と言います。 自分のコンピュータの違う場所のフォルダの中でクローンしてみましょう。
git clone https://github.com/fibasile/repo.git
ローカルコピーが作成され、編集やコミットなどができるようになります。結果はpushしてリモートリポジトリに反映することもできます。 クローンしたローカルリポジトリの編集をpushしたあと、元のオリジナルのローカルファイルに戻ってpullしてみましょう。
git pull origin master
これでコンピュータ上の2つのローカルリポジトリが同期されました。 同じ方法で違うコンピュータでもローカルリポジトリの同期ができます。
参考(English):
Mercurialについて
ソフトのインストール
Mercurial のダウンロード Windows, OSX, Linux.
設定
Gitではgitコマンドでローカルフォルダ上でファイル操作をしたように、Mercurialではhgコマンド使います。水銀(mercury)の元素記号です。 hgとタイプするとコマンドの一覧を示してくれます。
hg
Mercurial Distributed SCM
basic commands:
add add the specified files on the next commit
annotate show changeset information by line for each file
clone make a copy of an existing repository
commit commit the specified files or all outstanding changes
diff diff repository (or selected files)
export dump the header and diffs for one or more changesets
forget forget the specified files on the next commit
init create a new repository in the given directory
log show revision history of entire repository or files
merge merge working directory with another revision
pull pull changes from the specified source
push push changes to the specified destination
remove remove the specified files on the next commit
serve start stand-alone webserver
status show changed files in the working directory
summary summarize working directory state
update update working directory (or switch revisions)
use "hg help" for the full list of commands or "hg -v" for details
Mercurialリポジトリを作成して初期化してみましょう。
hg init
Gitでやった時と同じようにREADMEファイルを作成して何かテキストを入力します。 ファイルをaddし、commitするのも同じ手順です。
hg add README
hg commit -m 'Initial import' -u fiore
commitにはコメントだけでなくてユーザー名も追加します。デフォルトの設定は hg config –editで行います。
mercurialのログをチェックします。
hg log
このように表示されます。
changeset: 0:a2f0ef1e4c12
tag: tip
user: fiore
date: Wed Jan 14 13:52:23 2015 +0100
summary: Initial import
READMEに何かテキストを追加してみましょう。そしてコミットしてください。 Gitと異なるのは、ここでコミット前にaddする必要がないことです。Mercurialは最後のコミットからの差分を把握しています。
hg commit -m 'Another edit'
ログを再度確認してみましょう:
changeset: 1:6d8acdcc1429
tag: tip
user: fiore
date: Wed Jan 14 13:57:20 2015 +0100
summary: Some text added
changeset: 0:a2f0ef1e4c12
user: fiore
date: Wed Jan 14 13:52:23 2015 +0100
summary: Initial import
では新しいファイルをリポジトリに追加してみましょう。LICENSEファイルを作成します。そしてステータスを確認します。
hg status
? LICENSE
このままの状態でコミットしても何も起きません。
hg commit -m 'another commit'
nothing changed
新しいファイルはバージョン管理下に追加する必要があります。1度追加したあとは、ずっとトラッキングされます。
hg addremove
adding LICENSE
hg commit -m 'another commit'
このコマンドは新しいファイルが追加された場合と、削除された場合のどちらのケースもバージョン管理に反映されます。例えば、最初に作成したREADMEファイルを削除した場合も同じコマンド手順(addremoveとcommit)でリポジトリに反映できます。
rm README
hg addremove
removing README
Mercurialの素晴らしいところは、バージョン履歴に自由に戻ることができるところです。例えば、この状態から最初のコミット時の履歴に戻ってみましょう。
hg update -r0
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
0というのはhg logで確認した最初のchangesetの番号です。 updateにバージョンを指定しない場合は、最新のものに更新されます。
リモートリポジトリ
Gitと同じようにMercurialでもリモートリポジトリを使って他のユーザーと共同作業ができます。
よく使われているオンラインサービスは BitBucketです。アカウントを作ってMercurialのリポジトリを作成できます。リポジトリタイプにMercurialをチェックしてください。
ローカルのリポジトリをリモートリポジトリにpushします。
hg push https://(your account)/(repo name)
これでbitbucket上のリポジトリにローカルプロジェクトが読み込まれましたが、Mercurialはリモートリポジトリのurlを記憶しないため、pushのたびにurlを入力する必要があります。 そこで.hg/hgrcを設定します。
[paths]
default = https://(your account)/(repo name)
Gitと同じようにローカルの別フォルダにcloneすることができます。
cd new_folder
hg clone https://(your account)/(repo name)
LICENSEファイルを編集し、READMEファイルを新しく作成して hg addremove と hg commitを実行しましょう。そしてリモートリポジトリにpushします。
hg addremove
hg commit -m 'Added new README and updated LICENSE'
hg push
今回のローカルリポジトリはhgrcが設定されたリモートリポジトリからのクローンなので、新たに設定する必要はありません。
コンフリクトの解消
これで最初のフォルダにpullすればリポジトリが反映されますが、その前にコンフリクトが起きた時にどうなるか見てみます。 LICENSEファイルを編集してpushしてみます。
hg addremove
hg commit -m 'Removed LICENSE text'
hg push
このような表示になります
pushing to https://fibasile@bitbucket.org/fibasile/testrepo
warning: bitbucket.org certificate with fingerprint 45:ad:ae:1a:cf:0e:73:47:06:07:e0:88:f5:cc:10:e5:fa:1c:f7:99 not verified (check hostfingerprints or web.cacerts config setting)
searching for changes
remote has heads on branch 'default' that are not known locally: 4c3851b23038
abort: push creates new remote head 7f93695a6e1f!
(pull and merge or see "hg help push" for details about pushing new heads)
このような表示が出た場合、MERCURIALが何を言っているのか、どんなトラブルが発生しているのか注意して確認してください.
特に
abort: push creates new remote head 7f93695a6e1f!
というのは新しいブランチheadを作ることを意味しています。 このような他のユーザーが今の変更を全て無視するような結果になりそうなことはやりたくありません。 幸いMercurialがどうやって進めたらいいかヒントをくれています。
(pull and merge or see "hg help push" for details about pushing new heads)
言われた通り実行します:
hg pull
このように表示されます
pulling from https://fibasile@bitbucket.org/fibasile/testrepo
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 2 changes to 2 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
これでマージとコミットができるようになります。 ここで注意しなければならいのは、コミット後もう一度リモートリポジトリに自分がマージしたバージョンをプッシュする必要があることです。
hg merge
hg commit -m 'Merged my changes'
hg push
ほとんどの場合、この方法でファイルを編集した時のコンフリクトは解消できますが、それでもトラブルが発生する場合はツールなどを使って手動でマージする必要があります。 最後にログをチェックします。
changeset: 6:61f4b120ec71
tag: tip
parent: 4:7f93695a6e1f
parent: 5:4c3851b23038
user: fiore
date: Wed Jan 14 14:57:11 2015 +0100
summary: merging my changes
最新のchangesetには2回のpushによって2つのparentsがあることがわかります。
教訓: エラーメッセージには必ず目を通し、mercurialの助言を受けましょう