Git初心者のメモ その5：共有リポジトリ

Gitに関する記事

* 前の記事：[Git初心者のメモ その4：ブランチを使ってみる](http://qiita.com/y_ito/items/6bc6549eafe231cce16d)
* 次の記事：[Git初心者のメモ その6：リモートからブランチを持ってくる](https://qiita.com/y_ito/items/ac6d5a9d05e27c039b2b)

<br>

---
GitHubやGitLabを使わなくても、共有フォルダに共有リポジトリを作ってpushを受け付けるようにすれば複数人で共同作業できる。
試しに共有リポジトリを作ってpushしたりpullしてみたりしたけど、正直言って `git branch -r` や `git remote show` で表示されているのは何？「リモート追跡リポジトリ」って何？って感じで概念が理解できていない。


#共有リポジトリを作る

共有リポジトリは以下のコマンドで作成する。引数で指定したディレクトリが作成され、中にリポジトリのファイルが作られる。
ディレクトリ名はサフィックスに ".git" を付けて ○○○○○.git のような名前を付けるのが通例らしい。

`git init --bare --shared ＜ディレクトリのパス＞`

実際にbareな（ワークツリーを持たない）共有リポジトリを作ってみる。
とりあえず、共有リポジトリ（リモートのリポジトリ、pushを受ける方）もローカルのリポジトリ（pushする方）も同じPCのストレージ上でやってみた。リポジトリを作っただけなので当然履歴もブランチもない。

```shell-session:共有リポジトリ
y_ito@note MINGW64 /c/work/pub_rep
$ git init --bare --shared uchinaaguchi.git
Initialized empty shared Git repository in C:/work/pub_rep/uchinaaguchi.git/

y_ito@note MINGW64 /c/work/pub_rep
$ ls -a
./  ../  uchinaaguchi.git/

y_ito@note MINGW64 /c/work/pub_rep
$ cd uchinaaguchi.git/

y_ito@note MINGW64 /c/work/pub_rep/uchinaaguchi.git (BARE:master)
$ ls -a
./  ../  config  description  HEAD  hooks/  info/  objects/  refs/

y_ito@note MINGW64 /c/work/pub_rep/uchinaaguchi.git (BARE:master)
$ git branch -a

y_ito@note MINGW64 /c/work/pub_rep/uchinaaguchi.git (BARE:master)
$
```

bareではないリポジトリにpushしようとしてもエラーになる。bareではないリポジトリでもpushを受け付けるように設定することはできるが、危険だからやめた方がいいらしい（参考ページ4）。

別なリポジトリを作って、そこから先のbareリポジトリにpushしてみようと思う。
まずリポジトリ（以降、「作業用リポジトリ1」と呼称）を作成しファイル1個をコミットする。

```shell-session:作業リポジトリ用1
y_ito@note MINGW64 /c/work/lo_rep_1
$ git init
Initialized empty Git repository in C:/work/lo_rep_1/.git/

<<<ここでファイル作成>>>
y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git add uchinaaguchi.txt

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git commit -m "first commit"
[master (root-commit) d55d6a3] first commit
 1 file changed, 2 insertions(+)
 create mode 100644 uchinaaguchi.txt

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git branch -a
* master

```

作業用リポジトリ1にリモートリポジトリを追加する。
だけど `git branch -r` で何も表示されないなあ。
→かなり後に追記：それはそうだ。`git branch -r` は「リモート追跡ブランチ」を表示するもので、まだリモート追跡ブランチはないから。


```shell-session:作業用リポジトリ1
y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git remote add origin file:///c/work/pub_rep/uchinaaguchi.git

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git branch -a
* master

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git branch -r

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git remote -v
origin  file:///c/work/pub_rep/uchinaaguchi.git (fetch)
origin  file:///c/work/pub_rep/uchinaaguchi.git (push)

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git remote show origin
* remote origin
  Fetch URL: file:///c/work/pub_rep/uchinaaguchi.git
  Push  URL: file:///c/work/pub_rep/uchinaaguchi.git
  HEAD branch: (unknown)

```

とりあえず`push`してみる。

```shell-session:作業用リポジトリ1
y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git push
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin master


```

失敗した。引数は省略できないのか？ちゃんと引数を指定したら出来た。
push後は `git remote -r` でリモート追跡ブランチが表示されるようになった。
また、`git remote show origin` の表示内容も変わっている "HEAD branch:" が変わっていて、さらにその下に4行追加されている。

```shell-session:作業用リポジトリ1
y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git push origin master
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 276 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To file:///c/work/pub_rep/uchinaaguchi.git
 * [new branch]      master -> master

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git branch -a
* master
  remotes/origin/master

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git branch -r
  origin/master

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git remote show origin
* remote origin
  Fetch URL: file:///c/work/pub_rep/uchinaaguchi.git
  Push  URL: file:///c/work/pub_rep/uchinaaguchi.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local ref configured for 'git push':
    master pushes to master (up to date)

```

共有リポジトリを確認するとpushした内容が反映している。

```shell-session:共有リポジトリ
y_ito@note MINGW64 /c/work/pub_rep/uchinaaguchi.git (BARE:master)
$ git log --oneline --name-only
d55d6a3 first commit
uchinaaguchi.txt

y_ito@note MINGW64 /c/work/pub_rep/uchinaaguchi.git (BARE:master)
$ git show HEAD:uchinaaguchi.txt
うちなーぐち,標準語
はいさい,こんにちは

y_ito@note MINGW64 /c/work/pub_rep/uchinaaguchi.git (BARE:master)
$ git branch -a
* master

```

今度は `git clone` をしてみる。
作成されるフォルダが "uchinaaguchi.git" ではなく "uchinaaguchi" となる。リモートリポジトリには ".git" を付ける、ローカルリポジトリには ".git" を付けないというのが慣習なのだろうか。
このcloneにより作られたリポジトリを以後「作業用リポジトリ2」と呼称する。

```shell-session:作業用リポジトリ2
y_ito@note MINGW64 /c/work/lo_rep_2
$ git clone file:///c/work/pub_rep/uchinaaguchi.git
Cloning into 'uchinaaguchi'...
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

y_ito@note MINGW64 /c/work/lo_rep_2
$ ls -a
./  ../  uchinaaguchi/

y_ito@note MINGW64 /c/work/lo_rep_2
$ cd uchinaaguchi/

y_ito@note MINGW64 /c/work/lo_rep_2/uchinaaguchi (master)
$ ls -a
./  ../  .git/  uchinaaguchi.txt

y_ito@note MINGW64 /c/work/lo_rep_2/uchinaaguchi (master)
$ git log --oneline --name-only
d55d6a3 first commit
uchinaaguchi.txt

```

ブランチを表示すると、作業用リポジトリ1にはなかった `origin/HEAD -> origin/master` という謎のリモート追跡ブランチが。なんだこれ。

```shell-session:作業用リポジトリ2
y_ito@note MINGW64 /c/work/lo_rep_2/uchinaaguchi (master)
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

y_ito@note MINGW64 /c/work/lo_rep_2/uchinaaguchi (master)
$ git branch -r
  origin/HEAD -> origin/master
  origin/master

y_ito@note MINGW64 /c/work/lo_rep_2/uchinaaguchi (master)
$ git remote -v
origin  file:///c/work/pub_rep/uchinaaguchi.git (fetch)
origin  file:///c/work/pub_rep/uchinaaguchi.git (push)

y_ito@note MINGW64 /c/work/lo_rep_2/uchinaaguchi (master)
$ git remote show origin
* remote origin
  Fetch URL: file:///c/work/pub_rep/uchinaaguchi.git
  Push  URL: file:///c/work/pub_rep/uchinaaguchi.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

```

作業用リポジトリ2でファイルを更新してpushする。作業用リポジトリ1と異なり、push時に origin master とかって引数は不要。なんでだろう？

```shell-session:作業用リポジトリ2
<<<ファイルを編集>>>

y_ito@note MINGW64 /c/work/lo_rep_2/uchinaaguchi (master)
$ git diff
diff --git a/uchinaaguchi.txt b/uchinaaguchi.txt
index 51e1d28..ff32cff 100644
--- a/uchinaaguchi.txt
+++ b/uchinaaguchi.txt
@@ -1,2 +1,3 @@
 うちなーぐち,標準語
 はいさい,こんにちは
+めんそーれ,いらっしゃいませ^M

y_ito@note MINGW64 /c/work/lo_rep_2/uchinaaguchi (master)
$ git commit -a -m "「めんそーれ」を追加した。"
[master 3dfee49] 「めんそーれ」を追加した。
 1 file changed, 1 insertion(+)

y_ito@note MINGW64 /c/work/lo_rep_2/uchinaaguchi (master)
$ git log --oneline
3dfee49 「めんそーれ」を追加した。
d55d6a3 first commit

y_ito@note MINGW64 /c/work/lo_rep_2/uchinaaguchi (master)
$ git push
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 381 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To file:///c/work/pub_rep/uchinaaguchi.git
   d55d6a3..3dfee49  master -> master

```

共有リポジトリに変更内容が行ってるのを確認する。

```shell-session:共有リポジトリ
y_ito@note MINGW64 /c/work/pub_rep/uchinaaguchi.git (BARE:master)
$ git log --oneline
3dfee49 「めんそーれ」を追加した。
d55d6a3 first commit

y_ito@note MINGW64 /c/work/pub_rep/uchinaaguchi.git (BARE:master)
$ git show HEAD:uchinaaguchi.txt
うちなーぐち,標準語
はいさい,こんにちは
めんそーれ,いらっしゃいませ

```

作業用リポジトリ1でpullしてみる。pullの時と同様に引数をが必要だった。

```shell-session:作業リポジトリ用1
y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git pull
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 file:///c/work/pub_rep/uchinaaguchi
   d55d6a3..3dfee49  master     -> origin/master
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> master


y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git pull origin master
From file:///c/work/pub_rep/uchinaaguchi
 * branch            master     -> FETCH_HEAD
Updating d55d6a3..3dfee49
Fast-forward
 uchinaaguchi.txt | 1 +
 1 file changed, 1 insertion(+)

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ git log --oneline
3dfee49 「めんそーれ」を追加した。
d55d6a3 first commit

y_ito@note MINGW64 /c/work/lo_rep_1 (master)
$ cat uchinaaguchi.txt
うちなーぐち,標準語
はいさい,こんにちは
めんそーれ,いらっしゃいませ

```

これで3つのリポジトリが同じ内容になった。



#参考ページ

1.[Githubを使わずにチームでGitを共有する方法 - Qiita](http://qiita.com/shuntaro_tamura/items/d04fb892c9a6b7e1ab42)
2.[gitのローカル用の共有リポジトリ（？）を作る方法 - bi_naの日記](http://d.hatena.ne.jp/bi_na/20120206/1328502980)
3.[Gitリモートリポジトリの作り方 - Qiita](http://qiita.com/nekogeruge_987/items/326ba157d5552f0076be)
4.[git config --add receive.denyCurrentBranch ignoreはどう危険なのかAdd Star](http://d.hatena.ne.jp/nishiohirokazu/20120416/1334548800)

<!--
[[git]ローカルからpushした時に自動的に追跡ブランチにする - dackdive's blog](http://dackdive.hateblo.jp/entry/2014/09/10/121945)
[Gitでリモートブランチの追跡ブランチをローカルに作成する - Qiita](http://qiita.com/Vermee81/items/0026fd512e5379b46422)
[Git - リモートでの作業](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%81%A7%E3%81%AE%E4%BD%9C%E6%A5%AD)
-->