.git/configを覗いてみる話

今日は、リポジトリを構成する”.git/config”を覗いてみようと思います。

という訳で、今回のフォルダ構成はこんな感じです。

Project
├── Repo
└── Work

まずは、リモートリポジトリの初期化。
$ cd Project/Repo
$ git init --bare

次に、ローカルリポジトリを初期化します。
$ cd Project/Work
$ git init

そして、ローカルリポジトリにある、”.git/config”を覗いてみます。
$ cat .git/config

[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
	precomposeunicode = false

自分の環境だと、git initした直後の”.git/config”はこうでした。
次に、リモートリポジトリを追加してみます。
$ git remote add origin ../Repo

さて、”.git/config”はどうなったでしょう。

[core]
	(さっきと同じ)
[remote "origin"]
	url = ../Repo
	fetch = +refs/heads/*:refs/remotes/origin/*

リモートリポジトリの情報が追加されました。
Windows環境だと、urlが絶対パスで記述されている場合があるので、
Dropboxの中に入れて、MacとWindowの両方で作業する場合は、
この値を相対パスに書き直すと、エラーを解消できる場合があります。

次に、適当なファイルを追加してプッシュしてみます。
$ echo foo >> readme.txt
$ git add readme.txt
$ git commit -m"初回コミット"
$ git push origin master

次に、git pushだけでもコミットできるように設定します。
$ git branch -u origin/master
Branch master set up to track remote branch master from origin.

さて、もう一度”.git/config”を覗いてみましょう。

[core]
	(さっきと同じ)
[remote "origin"]
	(さっきと同じ)
[branch "master"]
	remote = origin
	merge = refs/heads/master

今度は、masterブランチの情報が追加されました。
この設定により、作業中のブランチがmasterの場合は、
git pushだけでプッシュが行えるようになりました。

もしくは、プッシュするときに-uをつけても、同様の設定が行われます。
$ git push -u origin master

-u--set-upstreamのショートオプションなので、
upstreamが何かは別として、upstreamの設定が行われるという意味です。
そして、”.git/config”に追加された情報がupstreamを意味しているとすれば、
upstreamとは、git pushを実行したときのプッシュ先の情報と解釈できます。(*1)

では、いくつか実験してみたいと思います。
ローカルブランチを切り替えて、プッシュしてみましょう。
$ git checkout -b topic
Switched to a new branch 'topic'
$ echo bar >> readme.txt
$ cat readme.txt
foo
bar
$ git commit -a -m "barを追加"

そして、以下の方法でプッシュしてみます。
$ git push
fatal: The current branch topic has no upstream branch.
To push the current branch and set the remote as upstream, use

git push --set-upstream origin topic

これは、topicブランチにおける、
git pushのプッシュ先情報、つまりupsteramが設定されていないという意味です。

なので、試しにメッセージの通りコマンドを実行してみます。
$ git push --set-upstream origin topic

これで、upstreamが設定されると同時に、
リモートリポジトリにtopicブランチをプッシュしてくれます。
なので、このコマンドを実行した際に表示されるメッセージの最後に、
以下のように、リモートリポジトリにtopicブランチを追加した旨が表示されます。

Branch topic set up to track remote branch topic from origin.

では、もう一度”.git/config”を覗いてみましょう。

[core]
	(さっきと同じ)
[remote "origin"]
	(さっきと同じ)
[branch "master"]
	remote = origin
	merge = refs/heads/master
[branch "topic"]
	remote = origin
	merge = refs/heads/topic

さて、masterブランチとtopicブランチでmergeの値が異なりますね。
以下のコマンドで、リモートリポジトリにあるブランチを見てみましょう。
$ git branch -r
origin/master
origin/topic

先ほどのプッシュで、リモートリポジトリにもtopicブランチができたようです。
自分が作業する場合は、リモートリポジトリにブランチを増やしたりせず、
ローカルリポジトリでブランチを作って、マージを済ませてしまうのですが、
バックアップの対象がリモートリポジトリだけの場合は、
ブランチのバックアップを取るためにも、このように作業をする場合があります。

次に、materブランチにtopicブランチで行った変更を反映させてみます。
もちろん、以下の方法でも行うことができます。
$ cat readme.txt
foo
$ git merge topic
Updating 699b0f1..07d8768
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
$ cat readme.txt
foo
bar

いわゆる、ローカル・マージです。
このままプッシュすれば、リモートリポジトリのmasterブランチも更新されます。

次に、ローカルリポジトリにtopicブランチがない状態からマージしてみます。

まずは、先ほどのマージを取り消します。
$ git reset --hard HEAD^
HEAD^は最新から1つ手前を意味します。
HEAD^^のように^を2つ付けると最新から2つ手前を意味します。
そして、--hardはファイルの内容も戻すことを意味します。
もし、今回のような目的ではなく単にコミットをやり直したい場合は、
--softを使うことでファイルの内容を維持したままコミットを取り消すことが出来ます。

そして、ローカルリポジトリのtopicブランチを削除します。
$ git branch -D topic

では、マージを始めましょう。
まずは、リモートリポジトリにあるtopicブランチを取得します。
$ git checkout -b topic origin/topic

これで、ローカルリポジトリにtopicブランチができました。
これだと、ローカル・マージができますね。
$ git checkout master
$ git merge topic

さっきと同じですね。
次に不要なブランチを削除します。
まずは、ローカルリポジトリのtopicブランチから。
$ git branch -d topic

次に、リモートリポジトリをtopicブランチ。
$ git push origin :topic
To ../Repo
- [deleted] topic

削除なのにプッシュ???こちらがヒントです。
$ git push <remote name> <local branch>:<remote branch>

最後に、topicブランチが削除されたことを確認しましょう。
$ git branch
* master
$ git branch -r
origin/master

これで作業は完了です。
お疲れさまでした。

おしまい。

(*1) その他の用途(git pull)でも使われますが、そのうち説明します。。。

Leave a Comment