Git道場#1に参加しました と、pullとpull --rebase備忘録 #gitdojo

Tags: [ Git ] [ イベント ] Published: 2012/04/22

概要

対象者が

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ファイルの後ろに記号を追加削除していく
  • コミットメッセージだけで語る
  • チーム間ではコミットメッセージのみを介して会話する
  • 「好きにやっていいので、ぐちゃぐちゃを楽しんでください」
  • 今回は@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が違う)


Author: kk_Ataka / Powered by Jekyll on GitHub Pages