[Git][イベント] Git道場#1に参加しました と、pullとpull –rebase備忘録 #gitdojo
概要
対象者が
merge / rebaseにちょっと自信がない
conflictが怖い
まさにそんな状況だったので、打破するために参加しました。
心「Git総論、心構え」
Gitにはリモートリポジトリ、ローカルリポジトリがある
- 集中型のリポジトリにはリモートリポジトリとローカルリポジトリの区別がない
- 皆のリポジトリなので履歴参照などはすべてリポジトリを見にいかなければならない
- 分散型では、主な作業はローカルで行い、データを管理できる
- ローカルリポジトリからリモートリポジトリに反映(プッシュ)する事で他人と共有
- ローカルリポジトリは俺のもの、リモートリポジトリは皆のもの
Gitは頑健である
Gitは時間的な変遷を管理する
- 昨日のこの時間何してたかな?
- testブランチを消してもコミットは残っている
- 作業履歴が残っているのでreflogで参照できる
- reflogで救済できる期間は90日以内、またはgit gc が実行されるまで
他(質疑応答の回答など)
- ブランチを削除してもコミットは残っている。git branch -D
- GitHub重い……
- イントラにbareリポジトリ用意して毎朝GitHubから持ってくるなど
技「本日の課題、テクニックの解説」
課題
- 今日はチームで一つのファイルを編集
- pull, rebaseを怖がらずに
- コンフリクトが起こった時の対処法を学ぶ
- pullとの違いを理解する
- ≒mergeとrebaseの違いでいいのかな?
ルール
- 1-10までのNumbersファイルの後ろに記号を追加削除していく
- コミットメッセージだけで語る
- チーム間ではコミットメッセージのみを介して会話する
- 「好きにやっていいので、ぐちゃぐちゃを楽しんでください」
- 今回は@[https://twitter.com/#!/myfinder:title=myfinder]さん、@[https://twitter.com/#!/umiyosh:title=umiyosh]さん、@[https://twitter.com/#!/nysalor:title=nysalor]さんと黙々と。
…みっちり数時間。
- (グラフが)とても…カオスです
実習後
- 再び講義。その後、同じNumbersファイルを(まっさらにしてから)やり直し
- さっきはpullでリポジトリから取得していたと思うけど、今回は必ずpull –rebaseする事
- コミットを直列にならべる事が目的
git pull --rebase
git add
git rebase --continue
- rebaseとは
- (ざっくりと)コミットをかぶせる
- リモートの最新コミットにローカルの共通コミットから先のコミットが被せられる(onto)
- まっすぐになるので誰が何コミットしたかわかりやすい
- コンフリクトした場合、無名ブランチがチェックアウトされた状態になる
- (ざっくりと)コミットをかぶせる
- 一方でmergeは
- コミットを統合する(基本的にマージコミットが生まれる=見た感じ複雑)
- リモートに新しいコミットがあると失敗する
- 変更履歴が残るので、後で調査がしやすい
- コミットを統合する(基本的にマージコミットが生まれる=見た感じ複雑)
- どちらがいいかは状況次第
- 他人がコミットしている事を意識する
- ローカルブランチでは作業履歴を残すためmergeの方がいいかも
アンチパターン?
- git add .
- 全部追加するとかありえない
- statusで確認してね
- 無名ブランチでコミット
- 困った場合は –abortで中断する
- git rebase –skipでスキップする事ができる
- git config user.nameとか設定して
という感じで13:00から18:00までadd,commit,push,pull(pull –rebase), コンフリクト解消を繰り返していました。個人的にはチューターの方にも丁寧に説明していただき、rebaseもかなり腹に落ちた感じで参加してよかった。後はこの感覚があるうちに本で復習してみる。
会場を提供して下さったフューチャーアーキテクトさんとGit道場師範の皆さんありがとうございました。門下生の皆さんお疲れ様でした。(終わった時にはほぼ全員ぐったりしていた)
pull、pull –rebaseまとめ
糞長いので先にまとめ。
pull
以下のふたつのリポジトリがあったとき
A
(FIRST)---(NUMBERADD)
origin/master
B
(FIRST)---(hello world)---(hello git)---(bye svn)
origin/master
Bがpullするとこういう歴史が出来る。
(NUMBERADD)----------------------------(merge)
/ /
(FIRST)---(hello world)---(hello git)---(bye svn)
pull –rebase
同じく。
A
(FIRST)---(NUMBERADD)
origin/master
B
(FIRST)---(hello world)---(hello git)---(bye svn)
origin/master
Bがpull –rebaseするとこういう歴史ができる。
(NUMBERADD)---(hello world merge)
/ no branch
(FIRST)---(hello world)---(hello git)---(bye svn)
(NUMBERADD)---(hello world merge)---(hello git merge)
/ no branch
(FIRST)---(hello world)---(hello git)---(bye svn)
(NUMBERADD)---(hello world merge)---(hello git merge)---(bye svn merge)
/ no branch
(FIRST)---(hello world)---(hello git)---(bye svn)
(NUMBERADD)---(hello world merge)---(hello git merge)---(bye svn merge)
/ master
(FIRST)--
整形して、
(FIRST)---(NUMBERADD)---(hello world merge)---(hello git merge)---(bye svn merge)
master
以下に実際にやってみたログ。
pull
dojo1さんとdojo2さんでdojo.gitリポジトリに書き込んでいく。空のnumファイルをfirst commit後……。
dojo1
dojo1さんが準備。
$ cat num
1
2
3
4
5
$ git coa -m "1から5までnumberふり"
[master 27734d8] 1から5までnumberふり
1 files changed, 5 insertions(+), 0 deletions(-)
グラフはこんな感じ。
$ git g
* 27734d8 2012-04-22 kk_Ataka (HEAD, master) 1から5までnumberふり
* 9f20959 2012-04-22 kk_Ataka (origin/master) first commit
dojo2
dojo2さん。cloneしたときはこんなグラフ。
$ git g
* 9f20959 2012-04-22 kk_Ataka (HEAD, origin/master, origin/HEAD) first commit
ここに27734d8をプルする前にローカルで色々育てる。
$ vim num
$ git coa -m "hello world追加"
$ vim num
$ git coa -m "hello git追加"
$ vim num
$ git coa -m "bye svn追加"
グラフはこう。
$ git g
* 817be9c 2012-04-22 kk_Ataka (HEAD, master) bye svn追加
* 66d89ab 2012-04-22 kk_Ataka hello git追加
* cb71f84 2012-04-22 kk_Ataka hello world追加
* 9f20959 2012-04-22 kk_Ataka (origin/master, origin/HEAD) first commit
この状態でプルすると…
$ git pull
remote: Counting objects: 5, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/kk_Ataka/github/dojo
9f20959..27734d8 master -> origin/master
Auto-merging num
CONFLICT (content): Merge conflict in num
Automatic merge failed; fix conflicts and then commit the result.
[22:54:45 kk_Ataka@www15203u (master *+|MERGING<>)~/github/dojo2]
$ git g
* 817be9c 2012-04-22 kk_Ataka (HEAD, dojo2/master, master) bye svn追加
* 66d89ab 2012-04-22 kk_Ataka hello git追加
* cb71f84 2012-04-22 kk_Ataka hello world追加
| * 27734d8 2012-04-22 kk_Ataka (origin/master, origin/HEAD) 1から5までnumberふり
|/
* 9f20959 2012-04-22 kk_Ataka first commit
first commit以降のブランチがdojo1さんが編集したものと自分が育てたものに分岐。これを解消してやり、コミット。
git coa -m "コンフリクトを解消し、メッセージにnumberをふった"
[master d21349d] コンフリクトを解消し、メッセージにnumberをふった
[22:57:18 kk_Ataka@www15203u (master>)~/github/dojo2]
$ git g
* d21349d 2012-04-22 kk_Ataka (HEAD, master) コンフリクトを解消し、メッセージにnumberをふ
|\
* | 817be9c 2012-04-22 kk_Ataka (dojo2/master) bye svn追加
* | 66d89ab 2012-04-22 kk_Ataka hello git追加
* | cb71f84 2012-04-22 kk_Ataka hello world追加
| * 27734d8 2012-04-22 kk_Ataka (origin/master, origin/HEAD) 1から5までnumberふり
|/
* 9f20959 2012-04-22 kk_Ataka first commit
dojo1に戻り
dojo1に戻りプルして一行追加しコミット&プッシュ。
$ git pull
remote: Counting objects: 16, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 12 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (12/12), done.
From /home/kk_Ataka/github/./dojo
27734d8..d21349d master -> origin/master
Updating 27734d8..d21349d
Fast-forward
num | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
$ git g
* d21349d 2012-04-22 kk_Ataka (HEAD, origin/master, master) コンフリクトを解消し、メッセ
|\
* | 817be9c 2012-04-22 kk_Ataka bye svn追加
* | 66d89ab 2012-04-22 kk_Ataka hello git追加
* | cb71f84 2012-04-22 kk_Ataka hello world追加
| * 27734d8 2012-04-22 kk_Ataka (dojo1/master) 1から5までnumberふり
|/
* 9f20959 2012-04-22 kk_Ataka first commit
$ vim num
$ git coa -m "number6を追加"
[master eeeab6f] number6を追加
1 files changed, 1 insertions(+), 0 deletions(-)
$ git push
Counting objects: 5, done.
Writing objects: 100% (3/3), 294 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /home/kk_Ataka/github/./dojo.git/
d21349d..eeeab6f master -> master
同じ頃dojo2では
その隙にdojo2は少しローカルで育て中。(ただし、今度はコンフリクトさせないように)
$ vi num
$ git coa -m "bye svnは削除"
そしてさっきのdojo1の更新をプル。
$ git pull
remote: Counting objects: 5, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/kk_Ataka/github/dojo
d21349d..eeeab6f master -> origin/master
Auto-merging num
Merge made by recursive.
num | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
[23:06:42 kk_Ataka@www15203u (master>)~/github/dojo2]
$ git g
* 5ba127c 2012-04-22 kk_Ataka (HEAD, master) Merge branch 'master' of /home/kk_Ataka/gith
|\
* | 252d4b5 2012-04-22 kk_Ataka bye svnは削除
| * eeeab6f 2012-04-22 kk_Ataka (origin/master, origin/HEAD) number6を追加
|/
* d21349d 2012-04-22 kk_Ataka コンフリクトを解消し、メッセージにnumberをふった
|\
* | 817be9c 2012-04-22 kk_Ataka (dojo2/master) bye svn追加
* | 66d89ab 2012-04-22 kk_Ataka hello git追加
* | cb71f84 2012-04-22 kk_Ataka hello world追加
| * 27734d8 2012-04-22 kk_Ataka 1から5までnumberふり
|/
* 9f20959 2012-04-22 kk_Ataka first commit
こうなる。なので基本的にプルはマージの履歴が残る。
pull –rebase
pull –rebaseではどうか。下記の状態まで戻る。
dojo1
$ git g
* 49622c6 2012-04-22 kk_Ataka (HEAD, origin/master, master) 1から5までnumberふり
* ec12cb5 2012-04-22 kk_Ataka first commit
dojo2
$ git g
* 3a940bc 2012-04-22 kk_Ataka (HEAD, master) bye svn追加
* 763cbaa 2012-04-22 kk_Ataka hello git追加
* d6c6c98 2012-04-22 kk_Ataka hello world追加
* ec12cb5 2012-04-22 kk_Ataka (origin/master, origin/HEAD) first commit
ここでpull –rebaseを使う。
$ git pull --rebase
remote: Counting objects: 5, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/kk_Ataka/github/dojo
ec12cb5..49622c6 master -> origin/master
First, rewinding head to replay your work on top of it...
Applying: hello world追加
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging num
CONFLICT (content): Merge conflict in num
Failed to merge in the changes.
Patch failed at 0001 hello world追加
When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".
盛大にコンフリクトする。改めて見るとrebase –continue, –skip, –abortを使いなさいって書いてあるな。
で、今のrebaseが始まったとき、ブランチはどこにいるのかというと……。
$ git br
* (no branch) 49622c6 1から5までnumberふり
master 3a940bc [ahead 3, behind 1] bye svn追加
ここ。無名ブランチ。この496…はどこかというと……。
$ git g
* 3a940bc 2012-04-22 kk_Ataka (master) bye svn追加
* 763cbaa 2012-04-22 kk_Ataka hello git追加
* d6c6c98 2012-04-22 kk_Ataka hello world追加
| * 49622c6 2012-04-22 kk_Ataka (HEAD, origin/master, origin/HEAD) 1から5までnumberふり
|/
* ec12cb5 2012-04-22 kk_Ataka first commit
dojo1さんがプッシュしていた所。なにはともあれまず、リポジトリにプッシュされていたものを優先する。このdojo1さんの変更に対して、d6c6c98、763cbaa、3a940bcとひとつずつrebaseしていく。問題を解決したらrebase –continue。無名ブランチにいるのでコミットしちゃダメ。
$ vim num
競合解消…
$ git add num
$ git rebase --continue
Applying: hello world追加
Applying: hello git追加
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging num
CONFLICT (content): Merge conflict in num
Failed to merge in the changes.
Patch failed at 0002 hello git追加
ひとつ解消したらふたつ目でまたコンフリクトした。今どこにいるかというと……。
$ git br
* (no branch) 781c723 hello world追加
master 3a940bc [ahead 3, behind 1] bye svn追加
$ git g
* 781c723 2012-04-22 kk_Ataka (HEAD) hello world追加
| * 3a940bc 2012-04-22 kk_Ataka (master) bye svn追加
| * 763cbaa 2012-04-22 kk_Ataka hello git追加
| * d6c6c98 2012-04-22 kk_Ataka hello world追加
* | 49622c6 2012-04-22 kk_Ataka (origin/master, origin/HEAD) 1から5までnumberふり
|/
* ec12cb5 2012-04-22 kk_Ataka first commit
コンフリクトを解消しつつ無名ブランチで突き進んでいる。
$ vim num
競合解消…
$ git add num
$ git rebase --continue
Applying: hello git追加
Applying: bye svn追加
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging num
CONFLICT (content): Merge conflict in num
Failed to merge in the changes.
Patch failed at 0003 bye svn追加
どんどん無名ブランチを進めていく。
$ git br
* (no branch) 8fb0d5e hello git追加
master 3a940bc [ahead 3, behind 1] bye svn追加
$ git g
* 8fb0d5e 2012-04-22 kk_Ataka (HEAD) hello git追加
* 781c723 2012-04-22 kk_Ataka hello world追加
| * 3a940bc 2012-04-22 kk_Ataka (master) bye svn追加
| * 763cbaa 2012-04-22 kk_Ataka hello git追加
| * d6c6c98 2012-04-22 kk_Ataka hello world追加
* | 49622c6 2012-04-22 kk_Ataka (origin/master, origin/HEAD) 1から5までnumberふり
|/
* ec12cb5 2012-04-22 kk_Ataka first commit
解消。
$ vim num
競合解消…
$ git add num
$ git rebase --continue
Applying: bye svn追加
これで全てのコミットの変更がdojo1さんの変更の上に適用された。で、今どこにいるかというと。
$ git br
* master 96897da [ahead 3] bye svn追加
$ git g
* 96897da 2012-04-22 kk_Ataka (HEAD, master) bye svn追加
* 8fb0d5e 2012-04-22 kk_Ataka hello git追加
* 781c723 2012-04-22 kk_Ataka hello world追加
* 49622c6 2012-04-22 kk_Ataka (origin/master, origin/HEAD) 1から5までnumberふり
* ec12cb5 2012-04-22 kk_Ataka first commit
無名ブランチからmasterブランチに。自分で作っていたコミットはなくなりあたらしくdojo1さんが作ったコミットの先に移動している。(SHA1が違う)