Gitのブランチについて調べた話

Gitでブランチを使った開発を始めた。

このブログサイトの草稿を書くのにブランチ使えそうな気がした。

草稿ごとにブランチ切って、完成したブランチ(草稿)をマージする的な。

というわけでGitのブランチについて調べてみた。

ちなみにGitについては「add、commit、push…」をひたすら唱えてるだけのレベル。

ブランチ含むgitのシステムについて調べた

  • git pull と git pull –rebase の違いって?図を交えて説明します! | KRAY Inc
  • Gitのfetch、merge、rebase、pullあたりについて説明してるブログだけど、図がすごい分かりやすかった
  • リモートリポジトリとローカルリポジトリがある
  • ローカルリポジトリにはローカルブランチとリモート追跡ブランチがある
  • ローカルブランチはそのまんま、ローカルに作成したブランチ
  • ローカルブランチはgit checkout <branch name>で切り替え、git checkout -b <branch name>で新規作成して切り替え
  • git branchでローカルブランチの一覧、git branch --remote(git branch -r)でリモートリポジトリの一覧が見れる
  • 見れば分かるとおりリモートリポジトリのブランチは頭にorigin/がついてる
  • ローカルブランチの中にHEAD(ローカルブランチの履歴の先頭)、インデックス(コミットするファイルを登録する場所)、ワーキングツリー(編集してるファイル)がある
  • リモート追跡ブランチはリモートリポジトリから取得した任意のブランチの情報を保存してる
  • リモート追跡ブランチはリモートリポジトリの情報を保持している
  • つまり、データ(?)の流れは以下のようになる
    • fetch -> リモートリポジトリ =====> リモート追跡ブランチ (ローカルで現在いるブランチのリモートリポジトリの情報を取得)
    • merge, rebase -> リモート追跡ブランチ =====> ローカルブランチ
    • push -> ローカルブランチ =====> リモートリポジトリ
  • git fetchはリモートリポジトリのメタ情報を取ってくるだけ
  • git merge <branch name>は現在のブランチに指定したブランチをくっつける
  • ここで指定ブランチで編集したファイルを現在のブランチでも編集してるとコンフリクトするっぽい
  • あとブランチ切ったあと、元のブランチが全く変更されていない状態で作ったブランチをマージするのをFast-Forwardというらしい
  • Fast-Forwardはブランチ切らないでコミット積み上げてプッシュしたのと結果的には同じ
  • まあ履歴を分けたいときはもとのブランチが編集されてなくても下のNon Fast-Forwardを使うらしい
  • あとGitはFast-ForwardとNon Fast-Forwardを自動で判断するので、その場合はgit merge -no-ff <branch name>とする必要がある
  • 対してブランチ切ったあと元のブランチにも変更があって、その状態でマージするのをNon Fast-Forwardというらしい
  • 上記のコンフリクトはこっちの場合に起こるものっぽい
  • ブランチはもとのブランチのある時の履歴から発生してるけど、git rebase <branch name>はその発生元を切り替えるらしい
  • そのときに積み上げたコミットは全て別のものになるらしい
  • あと何をもって「別のもの」としてるかというと、コミットにはそれぞれコミットIDなるものが付与されているらしい
  • rebaseするとブランチの根本のコミットが変わるので、必然的に全てのコミットのIDが変わると
  • というわけでrebaseは嫌われてるみたい。コミットIDでリンクとか張ってると、全部無駄になるからね
  • 最後にgit push origin <branch name>でリモートリポジトリにローカルリポジトリの変更を反映させる

実際にブランチを切って作業してみた

  • この記事自体が初めてブランチ切って作業したもの
$ git checkout master

$ git checkout -b <branch name>

$ git push origin <branch name>

# ~ファイル編集~

$ git add -A

$ git commit -m "message"

# ~1つないし複数のcommit~

$ git push origin <branch name>

# ~1つないし複数のpush~

$ git checkout master

# --no-ffを付けないとFast-forwardになってマージコミットがされない
# git merge <branch name>
$ git merge --no-ff <branch name>

$ git push origin master

# リモートのmerge済みブランチを削除
$ git push -d origin <branch name>

# ローカルのmerge済みブランチを削除
$ git branch -D <branch name>
  • まずはgit checkout <branch name>でブランチを切るもととなるブランチに移動
  • そしてgit checkout -b <branch name>でブランチを作成してそこに入る
  • ここで取り敢えずgit push origin <branch name>としておくと、今しがた作成したローカルブランチをリモートにも反映させられるらしい
  • あとoriginはリモートリポジトリのこと指してるっぽい
  • 次に作成したブランチで色々と作業する
  • ちなみにチェックアウトすると作業してるファイルもブランチごとに切り替わるけど、コミットしてない状態だとブランチだけ切り替わって、ワーキングツリーは切り替わらないので注意
  • あと作業途中だけどコミットするほどじゃない状態でブランチ切り替えたくなったり、別のブランチで作業始めちゃったってときはstashが使える
  • Gitでbranchを変えるときに、ファイルの変更はどう扱えばいいのか? - QA@IT
  • 簡単に言うとgit stash saveでstashにしまって、git stash popで取り出すだけ
  • 切ったブランチの作業が全て終わったら、元になるブランチにチェックアウトしてgit merge <branch name>でマージ
  • 元のブランチにマージしたブランチは削除しとくのがいいらしい