by shigemk2

当面は技術的なことしか書かない

Git Internals

社内勉強会のメモ。

コミットとブランチ編

親コミットと子コミット

新しくブランチを作ると同じコミットを参照している

.git/HEAD で今どこのブランチを参照しているかがわかる

.git/refs/head/ブランチ名 ブランチの最新コミットを参照している

USER@USER-THINK ~/projects/sandbox
$ git branch --verbose --all
* master                  ca38ca1 [ahead 1] Child commit.
  remotes/origin/HEAD     -> origin/master
  remotes/origin/master   4fb4c83 Merge pull request #1 from shigemk2/shigemk2
  remotes/origin/shigemk2 6d60fab Add hoge

USER@USER-THINK ~/projects/sandbox
$ git branch newbranch

USER@USER-THINK ~/projects/sandbox
$ git branch --verbose --all
* master                  ca38ca1 [ahead 1] Child commit.
  newbranch               ca38ca1 Child commit.
  remotes/origin/HEAD     -> origin/master
  remotes/origin/master   4fb4c83 Merge pull request #1 from shigemk2/shigemk2
  remotes/origin/shigemk2 6d60fab Add hoge

USER@USER-THINK ~/projects/sandbox
$ ll .git/refs/heads/
total 2
-rw-r--r-- 1 USER Administrators 41 Sep 12 15:12 master
-rw-r--r-- 1 USER Administrators 41 Sep 12 15:16 newbranch

USER@USER-THINK ~/projects/sandbox
$ cat .git/refs/heads/master  .git/refs/heads/newbranch
ca38ca1d067a3df13ea6b9b0d8b1d14001f26a83
ca38ca1d067a3df13ea6b9b0d8b1d14001f26a83
USER@USER-THINK ~/projects/sandbox
$ cat .git/refs/heads/master  .git/refs/heads/newbranch
6023fdaafc7a8536cdf71ea0f04544841a29f37c
386b95eb316c5f53f32e4f862268304dbba91696

USER@USER-THINK ~/projects/sandbox
$ git log --oneline
386b95e Commit on newbranch.
ca38ca1 Child commit.
4fb4c83 Merge pull request #1 from shigemk2/shigemk2
6d60fab Add hoge
2998c7d Create test2.txt
bf250f8 Create test.txt
c7fcaac Initial commit

USER@USER-THINK ~/projects/sandbox
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)

USER@USER-THINK ~/projects/sandbox
$ git log --oneline
6023fda Second Child commit.
ca38ca1 Child commit.
4fb4c83 Merge pull request #1 from shigemk2/shigemk2
6d60fab Add hoge
2998c7d Create test2.txt
bf250f8 Create test.txt
c7fcaac Initial commit

git checkout

HEADが参照しているブランチを変えられる

git checkoutで最新コミットを変更する

USER@USER-THINK ~/projects/sandbox
$ git checkout ca38ca1
Note: checking out 'ca38ca1'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at ca38ca1... Child commit.
USER@USER-THINK ~/projects/sandbox
$ cat .git/HEAD
ca38ca1d067a3df13ea6b9b0d8b1d14001f26a83
$ cat .git/refs/heads/master  .git/refs/heads/test
6023fdaafc7a8536cdf71ea0f04544841a29f37c
ca38ca1d067a3df13ea6b9b0d8b1d14001f26a83

USER@USER-THINK ~/projects/sandbox
$ git reset --hard master
HEAD is now at 6023fda Second Child commit.

USER@USER-THINK ~/projects/sandbox
$ cat .git/refs/heads/master  .git/refs/heads/test
6023fdaafc7a8536cdf71ea0f04544841a29f37c
6023fdaafc7a8536cdf71ea0f04544841a29f37c

コミットがmasterまで巻き戻っている

git merge

merge

一番怖いコマンド rebase

  • リポジトリを整理
  • ブランチを消すと、.git/refs/heads/からブランチ名のファイルが消える

rebaseすると…

USER@USER-THINK ~/projects/sandbox
$ git log --oneline
22b45ea test2 commit 2
baabcb1 test2 commit 1
731f9a5 Merge
386b95e Commit on newbranch.
6023fda Second Child commit.
ca38ca1 Child commit.
4fb4c83 Merge pull request #1 from shigemk2/shigemk2
6d60fab Add hoge
2998c7d Create test2.txt
bf250f8 Create test.txt
c7fcaac Initial commit

USER@USER-THINK ~/projects/sandbox
$ cat .git/refs/heads/test2
22b45eaabcd90a8bc8b394794198b781744ab7a2

USER@USER-THINK ~/projects/sandbox
$ git branch
  master
* test2

USER@USER-THINK ~/projects/sandbox
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: test2 commit 1
Applying: test2 commit 2

USER@USER-THINK ~/projects/sandbox
$ ls -1
LICENSE
README
README.md
hoge.txt
master-test-file
test.txt
test2-test-file
test2.txt

USER@USER-THINK ~/projects/sandbox
$ git log --oneline
1e45241 test2 commit 2
556ecc5 test2 commit 1
d1a0c5c master commit 2
d9f34cd master commit 1
731f9a5 Merge
386b95e Commit on newbranch.
6023fda Second Child commit.
ca38ca1 Child commit.
4fb4c83 Merge pull request #1 from shigemk2/shigemk2
6d60fab Add hoge
2998c7d Create test2.txt
bf250f8 Create test.txt
c7fcaac Initial commit

USER@USER-THINK ~/projects/sandbox
$ cat .git/refs/heads/test2
1e45241864e4be33a3f1d109f4c2bb6c0dca19ad

対象となるコミットハッシュが書き換えられる。また、heads/test2も書き換えられる コミットログのラインが一本になる。

2つのブランチが分岐された時点から、現在のブランチを切り離して、もうひとつのブランチの最新のコミットに移動させる 履歴はきれいになるけど、コンフリクトが起こるときは起こる

レビュー

  • git branch 新しいブランチを作る
  • git checkout HEADが参照しているブランチを変更する
  • git reset 現在のブランチが参照しているコミットを変更
  • git rebase ブランチごとを移住

そのキーとなるのは .git/HEAD