Git道場#1に参加しました と、pullとpull --rebase備忘録 #gitdojo
心「Git総論、心構え」
- @iwamatsuさんの講義
Gitは頑健である
Gitは時間的な変遷を管理する
- 昨日のこの時間何してたかな?
- testブランチを消してもコミットは残っている
- 作業履歴が残っているのでreflogで参照できる
- reflogで救済できる期間は90日以内、またはgit gc が実行されるまで
他(質疑応答の回答など)
- ブランチを削除してもコミットは残っている。git branch -D
- GitHub重い……
- イントラにbareリポジトリ用意して毎朝GitHubから持ってくるなど
技「本日の課題、テクニックの解説」
- @conceal_rsさんの講義
課題
- 今日はチームで一つのファイルを編集
- pull, rebaseを怖がらずに
- コンフリクトが起こった時の対処法を学ぶ
- pullとの違いを理解する
- ≒mergeとrebaseの違いでいいのかな?
ルール
- 1-10までのNumbersファイルの後ろに記号を追加削除していく
- コミットメッセージだけで語る
- チーム間ではコミットメッセージのみを介して会話する
- 「好きにやっていいので、ぐちゃぐちゃを楽しんでください」
- 今回は@myfinderさん、@umiyoshさん、@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が違う)