はじめてUNIXで仕事をする人が読む本 の備忘録 09 バージョン管理システム

はじめてUNIX で仕事をする人が読む本 の備忘録 09

お世話になった本

この連載ブログを書くにあたり、お世話になった本がこちら。LPICと被っているところもありますが、実務での使い方なんかも扱っており、良書だと思います。

第9章 バージョン管理システム

バージョン管理システムとは

名前の通り、ファイルのバージョンを管理してくれるありがたい存在。

機能としては

  • 「何の」修正を行ったのかわかる
  • 「誰が」修正を行ったのかわかる
  • 「いつ」修正を行ったのかわかる
  • 「なぜ」修正を行ったのかわかる
  • ファイルを過去の状態に戻せる

バージョン管理システムの種類

代表的なのだけ

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

Git だけ見ていく。(一部省略するかも)

Git の利用方法

初期設定

Git のWebページでアカウントを作る。そのアカウントのuser name / user email が覚えておく。

$ git config --global user.name "Lecuture Staff"
$ git config --global user.email lec-staff@example.co.jp

とかね。
保存先は、.gitconfigです。

リポジトリの作成

変更履歴を記録する領域のことをリポジトリと呼ぶ。
リポジトリを作成するには、git initを使う。

$ cd project/sample_project/
$ ls -a
.  ..  sample.pl
$ git init
Initialized empty Git repository in /home/taka/project/sample_project/.git/
$ ls -a
.  ..  .git  sample.pl
$ 

この時点で~/project/sample_project/リポジトリの作業コピーとして扱われる。しかし、自動的にリポジトリに追加されるわけでは無い。

$ git add .

カレントディレクトリ配下の変更のあったファイルをコミットするリストに追加(登録)する。

そして、コミット

$ git add .
$ git commit -m "first commit"
[master (root-commit) 9e21337] first commit
 1 file changed, 4 insertions(+)
 create mode 100755 sample.pl

# 確認するなら以下の通り
$ git log
commit 9e213378f45f636300a7f4ac53b9a599ad275a00
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:29:50 2017 -0500

    first commit

ファイルの編集

ざっくりと、こんな感じ

$ ls -a
.  ..  .git  sample.pl  # 現在のファイルの確認
$ vim sample.pl  # ファイルの編集
$ vim foo.sh  #ファイルの作成と編集
$ git add .  # Git に変更のあったファイルを登録
$ git status  # 現在のステータスを確認。new file とmodified があるのがわかる。
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   foo.sh
#   modified:   sample.pl
#
$ git commit -m "2nd commit"  # コミット
[master 46e533d] 2nd commit
 2 files changed, 4 insertions(+)
 create mode 100644 foo.sh
$ git commit -m "2nd commit"
[master 46e533d] 2nd commit
 2 files changed, 4 insertions(+)
 create mode 100644 foo.sh
[taka@ip-172-31-22-211 sample_project]$ git log -p
commit 46e533d1468c15de15f13b1052b6abe388c4f5a9
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:37:06 2017 -0500

    2nd commit

diff --git a/foo.sh b/foo.sh
new file mode 100644
index 0000000..e65e27d
--- /dev/null
+++ b/foo.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+echo "foo"
diff --git a/sample.pl b/sample.pl
index 9059403..477f4d0 100755
--- a/sample.pl
+++ b/sample.pl
@@ -1,4 +1,5 @@
 #!/usr/bin/perl
 
 print "Hello, World!\n";
+print "Hello, World2!\n";
 

commit 9e213378f45f636300a7f4ac53b9a599ad275a00
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:29:50 2017 -0500

    first commit

diff --git a/sample.pl b/sample.pl
new file mode 100755
index 0000000..9059403
--- /dev/null
+++ b/sample.pl
@@ -0,0 +1,4 @@
+#!/usr/bin/perl
+
+print "Hello, World!\n";
+
$ git status     <============ もう一度確認
# On branch master
nothing to commit, working directory clean  <===== きれいになった。
# 本当はここでgit push origin master とかするんですけどね。

変更の取り消し

git resetを使う。
git reset --head で全ての変更をキャンセル出来る。

$ vim bar.sh
$ cat bar.sh 
#!/bin/bash

$DATE=date
echo $DATE
$ git add .
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   bar.sh
#
$ git reset  <====== これ
$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   bar.sh
nothing added to commit but untracked files present (use "git add" to track)

ファイルの削除

git rmこれは、Git の作業コピーとインデックスから削除するコマンド。
なので、これを実施した後はgit commitが必要。

履歴の確認

git logで履歴の確認が出来る。

 git log
commit 46e533d1468c15de15f13b1052b6abe388c4f5a9
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:37:06 2017 -0500

    2nd commit

commit 9e213378f45f636300a7f4ac53b9a599ad275a00
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:29:50 2017 -0500

    first commit

ちなみに、46e533d1468c15de15f13b1052b6abe388c4f5a9これは、リビジョン識別しといい、Gitは格納しているファイル群をこれで管理している。

ブランチの作成

git branchで現在存在するブランチと、現在利用しているブランチを確認できる。
git branch <branch name> ブランチを作成する。
git checkout <branch name> でブランチを移動する。
ブランチを移動するときは、事前にコミットなどをして、変更を確定させておく必要がある。
また、
git checkout -b <branch name> == git branch <branch name> && git checkout <branch name> である。

$ git branch   # ブランチの存在の確認と、現在のブランチの確認。
* master
$ git branch 1st_branch  # ブランチの作成
$ git checkout 1st_branch  # ブランチの移動
Switched to branch '1st_branch'
$ git branch  # ブランチが作成され、移動している
* 1st_branch
  master
$ git checkout master  # 一度ブランチをマスターに戻してみた
Switched to branch 'master'

$ git checkout -b 2nd_branch  # ブランチの作成と移動を一緒にしている
Switched to a new branch '2nd_branch'
$ git branch  # これでブランチを作成して移動していることが確認できる
  1st_branch
* 2nd_branch
  master

マージ

分岐させたブランチは、統合して両方の変更を含んだものを作成できる。これが、マージである。
頭のいい人はここで気づくかもしれないが、条件を満たせば、衝突が起きる。これが英語そのままConflictである。そのときは、VimEmacsその他で修正する必要がある。

例として、masterブランチと1st_branchで変更を加えて、masterブランチにマージしてみようと思う。

$ git branch
  1st_branch
  2nd_branch
* master
$ vim foo.sh 
$ cat foo.sh 
#!/bin/sh

echo "foo"
echo $HOME

$ chmod u+x foo.sh 
$ ls -l
合計 8
-rwxrw-r--. 1 taka taka 34  2月 24 21:31 foo.sh
-rwxrw-r--. 1 taka taka 69  2月 23 18:36 sample.pl
$ git commit -a -m "modify foo.sh"  <======== git add . + git commit -m である。
[master b03be3f] modify foo.sh
 1 file changed, 2 insertions(+)
 mode change 100644 => 100755 foo.sh
$ 
$ git log
commit b03be3f65437753f4ea30d395e3a8104a88280d9
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Fri Feb 24 21:33:46 2017 -0500

    modify foo.sh

##################
# 1st_branch にて作業
##################
$ git branch
  1st_branch
  2nd_branch
* master
$ git checkout 1st_branch
Switched to branch '1st_branch'  <==== スイッチした
$ git branch
* 1st_branch
  2nd_branch
  master
$ ls -l  <======================= 現在のファイルを確認
合計 8
-rw-rw-r--. 1 taka taka 22  2月 24 21:43 foo.sh
-rwxrw-r--. 1 taka taka 69  2月 23 18:36 sample.pl
$ vim bar.sh  <================== bar.sh を作成
$ cat bar.sh  <================== 中身を確認
#!/bin/bash
echo $PATH
echo $HOME
echo `date +%Y%m%d`

$ chmod u+x bar.sh  <============ 実行権を付与
$ ls -l  <====================== ファイルを確認
合計 12
-rwxrw-r--. 1 taka taka 55  2月 24 21:45 bar.sh
-rw-rw-r--. 1 taka taka 22  2月 24 21:43 foo.sh
-rwxrw-r--. 1 taka taka 69  2月 23 18:36 sample.pl
$ git commit -a -m "create: bar.sh"  <=========== コミット
# On branch 1st_branch
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   bar.sh
nothing added to commit but untracked files present (use "git add" to track)
$ git status <============================= 一応確認
# On branch 1st_branch <=================== 1st_branch
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   bar.sh
nothing added to commit but untracked files present (use "git add" to track)

###################
# master ブランチに移動して、1st_branchをマージ
###################
$ git branch
* 1st_branch
  2nd_branch
  master
$ git checkout master
Switched to branch 'master'
$ git branch  <======================== master ブランチになった
  1st_branch
  2nd_branch
* master

$ git merge 1st_branch -m "marge to master form 1st_branch"   <== マージメッセージ付きマージ
Already up-to-date.

$ git status  <======================== ステータスを見てみよう
# On branch master  <================== master ブランチのステータスを見ている。1st_branch で作成した bar.sh がある
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   bar.sh
nothing added to commit but untracked files present (use "git add" to track)

$ ls -l
合計 12
-rwxrw-r--. 1 taka taka 55  2月 24 21:45 bar.sh  <====== あるぞ!
-rwxrwxr-x. 1 taka taka 34  2月 26 01:04 foo.sh
-rwxrw-r--. 1 taka taka 69  2月 23 18:36 sample.pl

$ git log
commit b03be3f65437753f4ea30d395e3a8104a88280d9
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Fri Feb 24 21:33:46 2017 -0500

    modify foo.sh

commit 46e533d1468c15de15f13b1052b6abe388c4f5a9
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:37:06 2017 -0500

    2nd commit

commit 9e213378f45f636300a7f4ac53b9a599ad275a00
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:29:50 2017 -0500

    first commit
$

リポジトリの複製

git clone これで、リポジトリそのものを複製できます。

$ git clone sample_project sample_project2
Cloning into 'sample_project2'...
done.
$ ls -l
合計 0
drwxrwxr-x. 3 taka taka 63  2月 26 01:04 sample_project
drwxrwxr-x. 3 taka taka 49  2月 26 01:44 sample_project2 <== コピーできたと思うけど、何かおかしい。。。

変更の受け取り

git pull で、clone 元のリポジトリに変更が合った場合、その変更を受け取ることが出来る。

# 事前にclone 元のsample_project 内で変更を入れておいた。
$ vim foo2
$ chmod u+x foo2 
$ ll
合計 16
-rwxrw-r--. 1 taka taka 55  2月 24 21:45 bar.sh
-rwxrwxr-x. 1 taka taka 34  2月 26 01:04 foo.sh
-rwxrw-r--. 1 taka taka 29  2月 26 02:06 foo2
-rwxrw-r--. 1 taka taka 69  2月 23 18:36 sample.pl
$ git add .
$ git status
$ git commit -m "Update"
[master 5d410b7] Update
 2 files changed, 9 insertions(+)
 create mode 100755 bar.sh
 create mode 100755 foo2
$ ls
bar.sh  foo.sh  foo2  sample.pl

###
# ここから、git pullします。
### 
$ cd ../
$ cd sample_project2
$ ls
foo.sh  sample.pl
$ git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From /home/taka/project/sample_project
   b03be3f..5d410b7  master     -> origin/master
Updating b03be3f..5d410b7
Fast-forward
 bar.sh | 5 +++++
 foo2   | 4 ++++
 2 files changed, 9 insertions(+)
 create mode 100755 bar.sh
 create mode 100755 foo2
$ ls
bar.sh  foo.sh  foo2  sample.pl

## 同期された!

共有リポジトリの作成

複数人で共有して変更できるリポジトリを作るときに使う。
git init --bare --shared=true で「作業コピーを持たない」、「グループから書き込み可能な」リポジトリが出来る。

しかし、個人的にはWebでリポジトリを作ってGit Clone をすることが多いので、パス。

一度、コマンドで実施してみよう。

$ mkdir sample_shared_project.git
$ cd sample_shared_project.git/
$ git init --bare --shared=true
Initialized empty shared Git repository in /home/taka/project/sample_shared_project.git/
$ ls -la
合計 12
drwxrwsr-x. 7 taka taka 119  2月 26 02:16 .
drwxrwxr-x. 5 taka taka  80  2月 26 02:16 ..
-rw-rw-r--. 1 taka taka  23  2月 26 02:16 HEAD
drwxrwsr-x. 2 taka taka   6  2月 26 02:16 branches
-rw-rw-r--. 1 taka taka 126  2月 26 02:16 config
-rw-rw-r--. 1 taka taka  73  2月 26 02:16 description
drwxrwsr-x. 2 taka taka 242  2月 26 02:16 hooks
drwxrwsr-x. 2 taka taka  21  2月 26 02:16 info
drwxrwsr-x. 4 taka taka  30  2月 26 02:16 objects
drwxrwsr-x. 4 taka taka  31  2月 26 02:16 refs

$ git remote add origin https://github.com/shimesaba-type0/sample_shared_project.git
$ git push origin master
Username for 'https://github.com': shimesaba-type0
Password for 'https://shimesaba-type0@github.com': 
remote: Repository not found.
fatal: repository 'https://github.com/shimesaba-type0/sample_shared_project.git/' not found

not found はわかるけど、remote にadd しようとしてこうなるのはなぜなのだろうか。

相変わらず、手元で初期化して、GitHub にプッシュする方法がわからない。


煮え切らないところでは有りますが、第9章 バージョン管理システムは以上です。
次は、第10章 ソースコードからのドキュメントの作成です。