Git でローカルリポジトリを作成してリポジトリを理解する

今回は、ローカルリポジトリを作成するまでを実施し、何が起きているか理解します。

git クライアントは、mac に入れた git コマンドです。

この記事の例を試すリモートリポジトリがなければ、「Doecker で GitLab コンテナを作る」を参考にテスト用の GitLab を用意するとよいです。

私はテスト用の GitLab で次の準備がしてある状態です。

  • グループ"mygrp"
  • 開発ユーザ"monkey"と"dog"で、mygrp へ権限付与
  • プロジェクト"projectx"へリポジトリ作成しプロテクト解除

この状態から説明していきます。

GitLab に作成したリモートリポジトリから、それと連携するローカルリポジトリを作成します。
下記の2通りありますが、"git clone"を使わないほうが勉強になるかと思います。

  • “git clone"で一括作成
  • “git branch"などで順次作成

git clone でローカルリポジトリを一括で作成する

git clone で、リモートリポジトリからローカルリポジトリを一括作成します。
git clone でいろんなことが裏で実施されます。主に下記の画像のようなことが起きています。

git cloneの状態

git clone してみる

まずは git clone して、どんな状態になるか理解します。

下記のように、git clone すると、プロジェクト名のディレクトリ"projectx"ができ、そこにリモートリポジトリの master ブランチの内容が取得できている状態になります。

$ git clone http://gitlab.monkey.local/mygrp/projectx.git

どんな状態になっているか調べる

ディレクトリへ入って、リモートリポジトリの状態を確認して理解していきます。

$ cd projectx

“git remote"で、出来上がった projectx に設定されているリモートリポジトリを確認できます。
“-v"で詳細です。

$ git remote -v
origin  http://gitlab.monkey.local/mygrp/projectx.git (fetch)
origin  http://gitlab.monkey.local/mygrp/projectx.git (push)

“origin"という名前で、"http://gitlab.monkey.local/mygrp/projectx.git"のサーバにあるリポジトリが設定されています
“origin"は、git clone が設定するデフォルトの名前です。
git pull などのコマンドでリモート名を省略すると、"origin"を使うなどデフォルトの名前として git で使われているものです。

origin はリモートリポジトリ(サーバのリポジトリ)のエイリアス と理解できていればよいです。

“git branch"で、ローカルのリポジトリにあるブランチを確認できます。"-a"はリモートとローカル両方です。
“-r"はリモートで、指定しない場合はローカルのみです。

$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

“master"が ローカルブランチ で、"remotes/xxx"が リモートブランチ です。

まず、 リモートブランチ は、"リモート追跡ブランチ"と呼ばれ、リモートリポジトリの状態を追跡するためのブランチです。
例えば、この"remotes/origin/master"を fetch すれば、サーバの master ブランチの最新の情報をとってこ来れます。

“remotes/origin/master"は、"origin(リモートリポジトリのエイリアス)"の master ブランチのことを示しています。
リモートリポジトリに master 以外のブランチがあれば、それらも表示されます。

注意としては、あくまでも clone したときの origin にあったブランチが表示されるだけです。
つまり、ローカルリポジトリにあるリモートブランチをリストアップしているだけで、サーバの最新のブランチ一覧を表示しているわけではありません。

clone 後に追加されたブランチを、ローカルリポジトリに追加したい場合は、"git fetch origin"とリモートブランチ"origin"を fetch する必要があります。
(ブランチ名がわかっているならgit fetch origin <branch-name>

次に、ローカルブランチ は、作業用に作成されているローカルブランチで、ローカルブランチ作成時はリモートブランチのどれかを指しています。
作業開始時には、リモートブランチとローカルブランチは同一です。
ローカルで commit 等をすると、ローカルブランチが先に進み、また、誰かがリモートブランチの示しているサーバのブランチを更新して、それを fetch すれば、リモートブランチは別のパスを進みます。

ローカルブランチがどのリモートブランチを指しているか(指していたか)を確認するには、"-vv"を指定します。

[~/tmp/clone/projectx] $ git branch -vv
* master 1100259 [origin/master] 管理者でREADME.mdを追加。

ローカルブランチ"master"は、リモートブランチ"origin/master"を指していることがわかります。

最後に、"remotes/origin/HEAD -> origin/master"ですが、これはリモートリポジトリの HEAD で、"git push"等でブランチ名を省略した場合に、この HEAD のブランチが使用されます。
“git remote set-head"で変更できます。

次の概念は 作業ブランチ(ローカルの HEAD) です。
先程の下記ブランチ一覧で"*"がついているのが作業ブランチです。
よく言う HEAD のことです。

$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

この場合、ローカルブランチ"master"を HEAD が指しており、このブランチで作業中ということです。
“git checkout"で作業ブランチ(HEAD)を切り替えることができます。

先程のリモートブランチでも HEAD が出てきましたが、それとは別ものです。

  • ローカルブランチの HEAD は作業中のブランチのことで、git checkout <local-branch>で切り替える。
  • リモートブランチの HEAD は push や pull のリモート操作のときのデフォルトのブランチのことで、"git remote set-head"で切り替える。

と私は理解してますが、明確に整理されているのを見たことがないので、間違っているかもしれません。
そもそも、リモートの HEAD は理解しなくていいんですが、省略してしまうといつの間にか使っていることになります。

“git branch"などで順次作成してみる

下記の図の git clone と同じことを git remote add, fetch, branch, checkout というように、1つずつ細かいステップで作っていきます。

git cloneの状態

git init (事前準備)

まずは、空のローカルリポジトリを作成します。

[~/tmp]$ mkdir monkey/projectx
[~/tmp/monkey/projectx]$ cd monkey/projectx
[~/tmp/monkey/projectx]$ git init

開発ユーザ"monkey"の設定を、初期化したローカルのリポジトリに反映します。
–local にしています。これはローカルリポジトリのディレクトリのみに反映します。
–global とするとログインユーザに反映してしまうので注意してください。

[~/tmp/monkey/projectx] $ git config --local user.name "monkey"
[~/tmp/monkey/projectx] $ git config --local user.email "monkey@monkey.local"

ここまでで、空のワーキングツリー(ワーキングディレクトリ)と空のローカルリポジトリができました。

git initの状態

git remote add (リモートリポジトリを追加)

次は、このローカルリポジトリに、リモートリポジトリを設定します。

[~/tmp/monkey/projectx] $ git remote add origin http://gitlab.monkey.local/mygrp/projectx.git

リモートリポジトリの設定内容を確認してみます。

[~/tmp/monkey/projectx] $ git remote -v
origin  http://gitlab.monkey.local/mygrp/projectx.git (fetch)
origin  http://gitlab.monkey.local/mygrp/projectx.git (push)

ここまでで、ローカルリポジトリにリモートリポジトリの設定ができました。

git remote addの状態

git fetch (リモートリポジトリをローカルへ反映)

上記の remote では、リモートブランチ"projectx の master"を origin で登録しただけです。
まだローカルリポジトリには、何も持ってきていません。
設定しただけです。リモートブランチをローカルブランチに持ってくるのが fetch です。

まずは、fetch する前にローカルリポジトリのブランチを確認してみましょう。

[~/tmp/monkey/projectx] $ git branch -a

結果は何も表示されません。’-a’はローカル、リモートの両方のブランチを表示するオプションです。
リモートブランチもありません。

では、fetch してみましょう。省略しているので、"git remote add"で登録した"origin"を fetch します。

[~/tmp/monkey/projectx] $ git fetch
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From http://gitlab.monkey.local/mygrp/projectx
 * [new branch]      master     -> origin/master

[~/tmp/monkey/projectx] $ git branch -a
  remotes/origin/master

リモートの"projectx の master"ブランチが fetch できました。

“git branch -a"は、GitLab 上にある git server を見に行っていないことがわかりましたか?
fetch して初めて一覧にでてきます。
つまり"git branch -a"はローカルリポジトリにある、リモートブランチの情報なのです。

また、"git fetch"と入力しました。
本当は、git fetch <remote> です。
<remote> を省略すると"origin"なので、正しくはというか、下記のように解釈されています。

[~/tmp/monkey/projectx] $ git fetch origin

ここまでで、ローカルリポジトリにリモートリポジトリの最新化ができました。

git fetchの状態

git branch (ローカルリポジトリを作る)

ローカルリポジトリ"master"を、リモートリポジトリ"origin/master"を上位に作ります。

git branch <local-name> <remote-name> で、下記のように作れます。

[~/tmp/monkey/projectx] $ git branch master origin/master
Branch 'master' set up to track remote branch 'master' from 'origin'.

出来上がったブランチ(ローカル/リモート)を確認しましょう。

[~/tmp/monkey/projectx] $ git branch -a
* master
  remotes/origin/master

[~/tmp/monkey/projectx] $ git branch -vv
* master 1100259 [origin/master] 管理者でREADME.mdを追加。

“master"ができ、ローカルの HEAD も"master"になっています。
HEAD がマスターになるのは、今までローカルブランチがなく、HEAD がなかったので、1つ目のローカルブランチが出来たためです。
通常は次の"git checkout"をしないと HEAD は移動しません。

ここまでで、ローカルリポジトリにローカルブランチができました。

git branchの状態

git checkout (作業ブランチを変える)

あとは、作成したローカルブランチを作業ブランチに変更するだけです。
作業ブランチが変更されれば、ワーキングツリーにそのスナップショットが反映されます。

作業ブランチを切り替えるのは"git checkout"でできます。

[~/tmp/monkey/projectx] $ git checkout master
Already on 'master'
Your branch is up to date with 'origin/master'.

これで、ワーキングツリーにリポジトリのファイルが複製されます。
GitLab で作成した"README.md"が作成されています。

[~/tmp/monkey/projectx] $ ls
README.md

[~/tmp/monkey/projectx] $ cat README.md
これはgitクライアントをテストするためのプロジェクトです。

ここまでで、ほぼ git clone で裏で動いていた処理を実行し終えました。

git checkoutの状態

git clone との差

まだ、git clone との差があります。
リモートブランチの HEAD がない状態です。

push などでブランチを省略しなければ必要ない設定ですが、下記のように"git remote set-head"を実行すれば設定できます。

[~/tmp/monkey/projectx] $ git branch -a
* master
  remotes/origin/master

[~/tmp/monkey/projectx] $ git remote set-head origin master

[~/tmp/monkey/projectx] $ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

まとめ

長くはなりましたが、これでローカルにリポジトリを作って、作業ブランチが準備できました。

Git

Posted by crz33