SlideShare a Scribd company logo
こわくない



Presented by Kota Saito @ksaito
こんな人が対象者
一応ブラン チ作ってコミットしてるけど
実は、マー ジとかよくわかってない……

   エラーが出た時に対処できない……

 rebase しちゃダ
             メって何でな   の?
Git よくわかんない!

  怖い!!
\怖くないよ/
#1 コミットとブランチ

#2 二種類のマージ

#3 リベースの功罪
コミットとブランチ
そもそも、コミットって
なんだっけ……?
コミットに入ってる情報
 リビジョン (SHA-1 ハッシュ)
 例: 23cdd334e6e251336ca7dd34e0f6e3ea08b5d0db

 Author (コミットを作成した人)
 例: オープンソースプロジェクトにパッチを送った人

 Committer (コミットを適用した人)
 例: 受け取ったパッチを取り込んだ人

 ファイルのスナップショット (tree)
 コミットで変更されたファイルを含むツリー(説明は省略)

 1つ前のコミットのリビジョン
 例: 4717e3cf182610e9e82940ac45abb0d422a76d77
コミットに入ってる情報
 リビジョン (SHA-1 ハッシュ)
 例: 23cdd334e6e251336ca7dd34e0f6e3ea08b5d0db

 Author (コミットを作成した人)
 例: オープンソースプロジェクトにパッチを送った人

 Committer (コミットを適用した人)
                  これ重要!!
 例: 受け取ったパッチを取り込んだ人

 ファイルのスナップショット (tree)
 コミットで変更されたファイルを含むツリー(説明は省略)

 1つ前のコミットのリビジョン
 例: 4717e3cf182610e9e82940ac45abb0d422a76d77
コミット   A   があれば
コミット   A   があれば


その前の   B   をたどれる
A

B

C
こわくない Git
最新のコミット




    たどれる!!



最古のコミット
この概念=
コミットグラフ


 \テストに出るぞ/
で、ブランチって
なんだっけ……?
new
      例えば master に
      コミットが4回されたあとの
      こんなコミットグラフ


old
new   =   master   イマココ!!




old
new

      さらに master にもう1回
      コミットがされると…



old
new!   =   master   イマココ!!




old
つまり

      =

ブランチは最新コミットの別名!!
ブランチ名の代わりに
リビジョンを指定したり
git checkout -b foo master


                     =
git checkout -b foo 4717e3cf1826
リビジョンの代わりに
ブランチ名を指定したり
 git show 4717e3cf1826
           =
 git show master
できる!!
あれ? 枝分かれする
ブランチの話は?


てか、masterって
ブランチだったのか
git branch topic master
git branch    topic   master



master   から   topic   を作る
例えば master に
new   コミットが3回されたあとの
      こんなコミットグラフ


old
new   =   master   イマココ!!




old
git branch      topic   master

             してみると……

new      =   master




old
!?
new   =   master   =   topic




old
つまり

   =     =

   ブランチを作る=
コミットのさらなる別名を作る
枝分かれしてなくね?
スルーですか?
この状態から            topic     に
      コミットしてみると……

new    =   master   =     topic




old
new!       =        topic   伸びた!!

       =   master




old
master       にコミットしてみると…

new!                =       topic


               =   master




old
new!   =   master


           =        topic



                    枝分かれ!!


old
Point
初めてコミットした時点で
枝分かれになります。
コミットとブランチ
・コミットには「1つ前のコミット」が
 含まれるので、最古までたどっていける
 → コミットグラフ

・ブランチは、そのブランチでの
 最新のコミットの別名に過ぎない

・枝分かれは、それぞれのブランチで
 コミットされて初めて発生する
二種類のマージ
Question
gitのマージには
 2種類ある事
知ってましたか?
Fast-Forward
       and
Non Fast-Forward
Fast-Forward = 早送り
?
例えばこんなコミットグラフ

    =        topic




=   master
topic ブランチに
3回コミットした

    3   =        topic

 2

    1

=       master
git merge topic

    3   =        topic

2

    1
                         マージ!!
=       master
git merge topic

    3   =        topic

2

    1
                         マージ!!
                         グラフはどうなる?
=       master
3   =   topic   =   master

2

1


                    !?
3   =        topic

2

    1

=       master
                         ←これが
3   =   topic   =   master

2       ここに↑
1       移動しただけ
Why?
topic    =   master   +   1   +   2   +   3




master
topic    =       master   +   1   +   2   +   3

                                  マージ!!
master   +   1    +   2   +   3   =       ?
topic    =       master   +   1   +   2   +   3




master   +   1    +   2   +   3   =       topic
topic   =   master     +   1   +   2   +   3




マージ後の                master    =       topic
中の人「どうせ同じ内容になるなら
いちいちマージしなくてよくね?」
中の人「マージ後に topic と同じ内容になるなら
  topic のところまで進めちゃおうぜww」


         3   =        topic   =   master

      2

         1                    進める

     =       master
これが Fast-Forward
Fast-Forward

マージのかわりに早送り。
\ドヤァ…/
Non Fast-Forward
さっきのコミットグラフから
    にコミットすると…
master



    =        topic




=   master
=   master


    =        topic


               枝分かれ!!
マージ後の   master   ≠   topic
中の人「早送りできない><」
中の人「ちゃんとマージするかー」
git merge topic
=       master


    3   =        topic

    2

    1
                         マージ!!
〜中の人計算中〜

「えーと master の内容と
 topic のコミットを比較して…」
         「衝突してたら教えてあげなきゃ…」
master   +   1   +   2   +   3




中の人「全部まぜちゃえー」
master   +   1   +   2   +   3   =   M




中の人「マージ結果ができたよ!」
=       master


    3   =        topic

    2
                         M
    1
                    中の人「そぉい!!」
M   =       master           <スポッ




        3   =        topic

        2

        1
M   =       master           ←マージの結果
                              作られたコミット


        3   =        topic

        2

        1
M   =       master           ←マージの結果
                              作られたコミット
                       マージコミット
        3   =        topic

        2

        1

                     \テストに出るぞ/
Non Fast-Forward
Non Fast-Forward

早送りじゃないマージ。
\ドヤヤヤァ…/
ちなみに
git merge topic
Fast-Forward                      Non Fast-Forward

早送りできればする、無理なら普通のマージ


git merge --no-ff topic
               Non Fast-Forward

常に普通のマージ


git merge --ff-only topic
        Fast-Forward

常に早送りする(できなければエラーとする)
ところが
議論がある
常に git merge --no-ff すべきだ!


 訳: 早送りマージすんな!
\えっ/
Why?
3   =   topic   =   master

2

1
        早送りした後の状態から
             を消すと…
          topic
3   =   master

2

1
                 ん?
3   =   master

2

1
                 あれ?
=   master




     直接コミットしたのと
     変わらない!!
\    の霊圧が消えた…!?/
  topic


  =   master
Fast-Forward の弊害①

「ブランチをマージした」という事実が
 歴史(コミットグラフ)に残らない
=   master




     おっと、間違って
     マージしちゃった (>ω・)
=   master




     えーと、マージを
     元に戻すにはっと…
git revert <commit>
<commit> (リビジョン) のコミットを
取り消すためのコミットを作る


git reset --hard <commit>
<commit> (リビジョン) 時点の状態まで
完全に巻き戻す
=   master




    おkおk
    コミットを指定すればいいのか
=   master




    で、どれが topic の
    コミットだっけ……
Fast-Forward の弊害②

  「ブランチのマージ」を
    取り消しづらい
Point
マージの種類を意識して
マージしましょう!
二種類のマージ
・Fast-Forward = 早送り
 ・コミットグラフ的に結果が同じなら
  同じコミットまで進めてしまうこと
 ・「マージした」という記録が残らない
 ・マージを取り消しづらい

・Non Fast-Forward = 普通のマージ
 ・Git ががんばって計算するマージ
リベースの功罪
git 初心者が陥りがちな罠

    第1位
     (個人的に)
リベーーーーーース

git rebase
ブランチ を master に追従するときに
使ってま す!! マージはなんか怖いし…


   rebase すると、コミットログが
   キレイになって見やすいよね!!


 merge よりも
           rebase の方が
 マージコミット
           もなくて楽でし
                      ょ?
Question
そもそも rebase が
 なにをするのか
理解していますか?
2   =       master


1

        2   =        topic


        1
                              topic
                      この状態から     で
                      git rebase master すると…
topic

   2      2
   1      1

まず、コミットの変更内容を
それぞれパッチにする
2   =       master     =     topic


1                             移動
        2   =        topic


        1        次に topic を master と
                 同じコミットに移動させる
                 (元々の topic ブランチでの
                  変更は含まなくなる)
ここまで来たら、作っておいた
    パッチを1つずつ順に適用して
    コミットしていく


2   =   master   =    topic


1

                       1  2
                     (  と  は省略)
差分を適用してコミット              1



2   =   master   =   topic


1
A   ←    1 から作られたコミット

2   =   master   =   topic


1
A   =    topic


2   =   master


1
2


    A   =    topic


2   =   master


1
B   ←    2 から作られたコミット

    A   =    topic


2   =   master


1
B   =    topic


    A

2   =   master


1
重要
   2        B

   1
       ≠    A

rebase で作られたコミットは
元のコミットと同じ内容だけど
別のコミットになります!!
重要
   2        B

   1
       ≠    A
                本当?
rebase で作られたコミットは
元のコミットと同じ内容だけど
別のコミットになります!!
コミットに入ってる情報
 リビジョン (SHA-1 ハッシュ)
 例: 23cdd334e6e251336ca7dd34e0f6e3ea08b5d0db

 Author (コミットを作成した人)
 例: オープンソースプロジェクトにパッチを送った人

 Committer (コミットを適用した人)
 例: 受け取ったパッチを取り込んだ人

 ファイルのスナップショット (tree)
 コミットで変更されたファイルを含むツリー(説明は省略)

 1つ前のコミットのリビジョン
 例: 4717e3cf182610e9e82940ac45abb0d422a76d77
コミットに入ってる情報
 リビジョン (SHA-1 ハッシュ)
 例: 23cdd334e6e251336ca7dd34e0f6e3ea08b5d0db

 Author (コミットを作成した人)
 例: オープンソースプロジェクトにパッチを送った人

 Committer (コミットを適用した人)
 例: 受け取ったパッチを取り込んだ人

 ファイルのスナップショット (tree)
 コミットで変更されたファイルを含むツリー(説明は省略)

 1つ前のコミットのリビジョン
 例: 4717e3cf182610e9e82940ac45abb0d422a76d77
2    B

   1    A

        2


1つ前のコミットが違う!!
2      B

  1      A

         2

1つ前のコミットが変わると
 リビジョンも変わります
  (だから別物になる)
Point
rebaseで作られるコミットは
 元のコミットとは別物
別物でも、同じ変更が
されるから問題ない気が
git push origin topic
git push origin           topic



  topic   を origin (サーバー) に同期
local              origin

2   =   topic

                push
1
local       origin

2   =   topic   2   =   topic

1               1
local        origin
3   =    topic


2       commit   2   =   topic

1                1
local              origin
3   =   topic

                push
2                      2   =   topic

1                      1
origin「お、pushがきたぞ?
どれどれ、内容を見てみよう」
origin「新しいコミットは1つだけか」


          3



「さて、こいつの前のコミットは…」
3

         2

origin「お、2番なら知ってるぞ!」
local       origin
3   =   topic


2               2   =   topic

1               1
local       origin
3   =   topic   3   =    topic


2               2       よし、2番の
                        後ろに追加
1               1
local       origin
3   =   topic   3   =   topic


2               2

1               1
push after rebase
local       origin

2   =   topic   2   =   topic

1               1

0               0
local        origin

B   =    topic   2   =   topic

A       rebase   1

0                0
local              origin

B   =   topic          2   =   topic

                push
A                      1

0                      0
origin「お、pushがきたぞ?
どれどれ、内容を見てみよう」
origin「新しいコミットは2つか」

         B

         A


「さて、こいつの前のコミットは…」
B

       A

       0

origin「あれ? 0番か…」
B      2

     A      1

     0      0

origin「もう0番には次のコミットが
あるし、1とAはリビジョンも違う!!」
local       origin
                      ダメダメ!!
                    受け付けないよ!!
B   =   topic   2   =   topic

A               1

0               0
Point
push されているブランチを
   rebase すると
  push できなくなる
Point

よって、共有のブランチでは
rebase してはいけない !!
push -f ダメ! 絶対!!

  push -f で強制的に上書き push できますが
他の人が pull する時にマージする必要があったり
コミットログがおかしな事になるのでやめましょう
ブ ランチを master に追従するときに
使ってます !! マージはなんか怖いし…
\怖くないよ/
こわくない Git
M   git merge master
M
M   git merge master



M
M



M
M       git merge topic


    M



    M
M


    M

          と  で衝突する修正を

    M   しない限り、マージ時には
        一切コンフリクトしません!
Point

git のマージは
相当かしこい
rebase すると、コミットログが
キレイになって見やすいよね!!
M


    M


        この一連の流れを
    M   もし rebase でやっていると
確かに一直線でキレイ
お気づきだろうか…
ヒソヒソ…
(なあ、もしかして
 俺たち忘れられてないか?)
        M   M   M
マージの記録は残らない
えっ

M   M    M
Point
rebase でコミットグラフは
 一直線にキレイになるが
その陰で失われる情報がある
Point
  そもそも git で
入り組んだグラフになっても
そんなに気にすることはない
merge よりも
          rebase の方が
マージコミット
          もなくて楽でし
                     ょ?
ここから git rebase master すると…



                    ←a.txtの1行目を修正

a.txtの1行目を修正→
                    ←a.txtの1行目を修正
コミットがそれぞれパッチになって…



                2

a.txtの1行目を修正→
                1
1つ目のパッチを適用


     a.txtの1行目を修正するパッチ1つ目↓

                         1
a.txtの1行目を修正→
コンフリクト!


     a.txtの1行目を修正するパッチ1つ目↓

                         1
a.txtの1行目を修正→
コンフリクトを解消



                ←a.txtの1行目を修正

a.txtの1行目を修正→
2つ目のパッチを適用

     a.txtの1行目を修正するパッチ2つ目↓

                         2

                   ←a.txtの1行目を修正

a.txtの1行目を修正→
コンフリクト!


     a.txtの1行目を修正するパッチ2つ目↓

                          2

                    ←a.txtの1行目を修正

a.txtの1行目を修正→
コンフリクトを解消



                ←a.txtの1行目を修正


                ←a.txtの1行目を修正

a.txtの1行目を修正→
Point
   rebase だと
コミットそれぞれについて
コンフリクトの解消が必要
ちなみに git merge master だと…




                    ←a.txtの1行目を修正

a.txtの1行目を修正→
                    ←a.txtの1行目を修正
コンフリクトを解消


                M


                    ←a.txtの1行目を修正

a.txtの1行目を修正→
                    ←a.txtの1行目を修正
Point
   merge だと
コミットがいくつあろうと
コンフリクト解消は1回だけ
Point
   したがって
rebase よりもむしろ
merge の方が楽です
リベースの功罪
           Good
・コミットグラフがキレイになる
 → マージ後のログがキレイになるので
   master にマージする直前にやるのは
   OK とする事がある
 → GitHub などのオープンソースプロジェクトに
   プルリクエストを送る場合は
   rebase してから送るのがマナーとされている
リベースの功罪
          Bad
・push されたブランチをリベースすると
 push できなくなる

・「マージした」という事実は失われる

・マージに比べるとコンフリクト解消が面倒
すこしは git の
 理解の手助けに
なれたでしょうか?
\怖くないよ/
\ズッ友だょ……!!/
Have a Nice Git!
References
Pro Git book
http://git-scm.com/book/ja/

git merge or rebase, ff or no-ff - Togetter
http://togetter.com/li/407277

A successful Git branching model
http://nvie.com/posts/a-successful-git-
branching-model/

More Related Content

PDF
見やすいプレゼン資料の作り方 - リニューアル増量版
PDF
いつやるの?Git入門 v1.1.0
PDF
いつやるの?Git入門
PDF
『バックドア基準の入門』@統数研研究集会
PDF
SSII2019企画: 点群深層学習の研究動向
PDF
カネとAgile(大企業新規事業編) #rsgt2021
PDF
深層学習の不確実性 - Uncertainty in Deep Neural Networks -
見やすいプレゼン資料の作り方 - リニューアル増量版
いつやるの?Git入門 v1.1.0
いつやるの?Git入門
『バックドア基準の入門』@統数研研究集会
SSII2019企画: 点群深層学習の研究動向
カネとAgile(大企業新規事業編) #rsgt2021
深層学習の不確実性 - Uncertainty in Deep Neural Networks -

What's hot (20)

PPTX
世界一わかりやすいClean Architecture
PDF
テスト文字列に「うんこ」と入れるな
PDF
GoによるWebアプリ開発のキホン
PDF
Docker Compose 徹底解説
PPTX
SPAセキュリティ入門~PHP Conference Japan 2021
PPTX
DXとかDevOpsとかのなんかいい感じのやつ 富士通TechLive
PDF
BuildKitの概要と最近の機能
PDF
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
PDF
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
PPTX
関数型・オブジェクト指向 宗教戦争に疲れたなたに送るGo言語入門
PDF
PostgreSQLアンチパターン
PDF
例外設計における大罪
PPTX
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
PDF
コンテナの作り方「Dockerは裏方で何をしているのか?」
PDF
目grep入門 +解説
PDF
オブジェクト指向プログラミングのためのモデリング入門
PDF
イミュータブルデータモデル(入門編)
PDF
Dockerfile を書くためのベストプラクティス解説編
PDF
Dockerからcontainerdへの移行
PDF
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
世界一わかりやすいClean Architecture
テスト文字列に「うんこ」と入れるな
GoによるWebアプリ開発のキホン
Docker Compose 徹底解説
SPAセキュリティ入門~PHP Conference Japan 2021
DXとかDevOpsとかのなんかいい感じのやつ 富士通TechLive
BuildKitの概要と最近の機能
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
関数型・オブジェクト指向 宗教戦争に疲れたなたに送るGo言語入門
PostgreSQLアンチパターン
例外設計における大罪
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
コンテナの作り方「Dockerは裏方で何をしているのか?」
目grep入門 +解説
オブジェクト指向プログラミングのためのモデリング入門
イミュータブルデータモデル(入門編)
Dockerfile を書くためのベストプラクティス解説編
Dockerからcontainerdへの移行
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
Ad

Viewers also liked (20)

PDF
デザイナのためのGit入門
PDF
はじめようGit
PDF
はじめてのGit forデザイナー&コーダー
PDF
Gitのよく使うコマンド
PDF
15分でわかるGit入門
PDF
Java初心者がJava8のラムダ式をやってみた
PDF
社内Java8勉強会 ラムダ式とストリームAPI
PDF
Lombok ハンズオン
KEY
一人でもはじめるGitでバージョン管理
PDF
やりなおせる Git 入門
PDF
もしWordPressユーザーがGitを使ったら 〜WordPressテーマを共同編集しよう〜
PDF
Gitはじめの一歩
PDF
ノンプログラマでも今日から使える「Git」でバージョン管理
PDF
今年の卒論はGithubで決まり!
KEY
バージョン管理のワークフロー
PPT
Git紹介
PDF
インフラエンジニアのこれまでとこれから
PPTX
AbemaTV モバイルアプリの開発体制と開発プロセスの話
PDF
ドキュメンテーションを加速するストレスフリーの作図ツール『blockdiag』 jus2011年6月勉強会
PDF
Git 入門
デザイナのためのGit入門
はじめようGit
はじめてのGit forデザイナー&コーダー
Gitのよく使うコマンド
15分でわかるGit入門
Java初心者がJava8のラムダ式をやってみた
社内Java8勉強会 ラムダ式とストリームAPI
Lombok ハンズオン
一人でもはじめるGitでバージョン管理
やりなおせる Git 入門
もしWordPressユーザーがGitを使ったら 〜WordPressテーマを共同編集しよう〜
Gitはじめの一歩
ノンプログラマでも今日から使える「Git」でバージョン管理
今年の卒論はGithubで決まり!
バージョン管理のワークフロー
Git紹介
インフラエンジニアのこれまでとこれから
AbemaTV モバイルアプリの開発体制と開発プロセスの話
ドキュメンテーションを加速するストレスフリーの作図ツール『blockdiag』 jus2011年6月勉強会
Git 入門
Ad

こわくない Git