勉強日記

チラ裏

Version Control with Git ch7 Branches

shop.oreilly.com


Branches

  • Gitのブランチが使われるワケ
    • 軽量でシンプル
    • 最高級のマージサポート
  • 本章の内容
    • ブランチの...
      • 選択
      • 作成
      • 閲覧
      • 削除
    • ベストプラクティス

Reasons for Using Branches

  • ブランチは種々の理由で切られる
    • 技術的
    • 哲学的
    • 管理者的
    • 社会的
    • 古いバージョンを取っておく
      • v1.1リリース後もv1.0を取っておく、等
    • 開発フェーズごとに切る
      • プロトタイプ
      • ベータ
      • 安定
      • エッジ(信頼性のリスクがまだ高いやつ)
    • タスクごとに切る
        • 機能追加
        • 複雑な不具合の調査
      • 概念的に別々のタスクを別々のブランチで作業し、マージを容易にする
    • コントリビュータごとに切る
  • これらを トピックブランチ 、あるいは 開発ブランチ と呼ぶ
    • 「トピック」の意味するところは、各ブランチが目的をもつということ
  • 他に 追跡ブランチ もある
    • 12章にて

コラム: Branch or Tag?

  • 似ている。置換可能なことも
  • 相違点
    • タグ
      • 静的
      • 一度付けたらずっとそのコミットを指す
        • 標識のような感じ
    • ブランチ
      • 動的
      • 開発用
        • コミットするたびにHEADが動く
  • タグを使用するかブランチを使用するかはプロジェクトのポリシーによるが、つけようとしている名前が静的か動的かは意識すべき
  • タグとブランチには同じ名前を付けられる
    • 付けた場合、完全名で区別する必要あり
      • refs/tags/ref
      • refs/heads/ref
    • 特段の理由がない限り、やめたほうがいい

Branch Names

  • ブランチ名は基本的に任意
    • masterブランチも、git init時に自動的に作られる以外に特別な意味はない
      • リネームしたり消したりしても良い
        • そのまま残しておくのがベストプラクティスではある
  • unixのパスのように、/区切りで構造化できる
    • globが使える

Dos and Don'ts in Branchs Names

  • ブランチ名は/で終われない
  • ブランチ名は-で始まれない
  • /区切りの個々の部位は.で始まれない
    • feature/.newは不可
  • ..は不可
    • 【補】rangeと衝突するからかな?
  • 含んではならないもの
    • ホワイトスペース類
    • Gitにとって特別な意味のある文字
      • ~
        • 【補】n個上の親
      • ^
        • 【補】親のうちn番目
      • :
        • 【補】git show branch:pathpathのファイル内容表示
      • ?
        • 【補】glob
      • *
        • 【補】glob
      • [
      • ASCII制御文字
        • 0x1F以下
        • 0x7F (DEL)
  • git check-ref-format低レベルコマンドでバリデートできる
git check-ref-format --branch feature/.new
fatal: 'feature/.new' is not a valid branch name

Using Branches

  • アクティブブランチ/カレントブランチ
    • どのファイルをチェックアウトするか
    • gitコマンドの暗黙のオペランドとなる
      • git merge のmerge先とか
  • ブランチ名は、そのブランチの最新のコミットを指す
    • tip または headと呼ばれる
    • DAG上でそこに到達可能な全コミットの歴史が含まれる
    • コミットするたびに動くということ
      • 特定のコミットを静的に指したければタグを使う

Creating Branches

  • カレントブランチのHEADからprs/pr-1138ブランチを生やす
git checkout rel-2.3 # カレントブランチをv2.3リリースに
git branch prs/pr-1138
  • 文法
git branch branch [starting-commit]
  • [starting-commit]省略時はカレントブランチ(のHEAD)から生やす
  • リリースv2.3のbugfixブランチならこう
git branch prs/pr-1138 rel-2.3
  • git branchコマンド自体は、新しいブランチ名を導入するだけ
    • 作業ディレクトリに変更を加えない
    • ブランチのコンテキストは変わらない
      • checkoutはしないということ
    • コミットを作成しない
  • [starting-commit]はSHA1値でもよい

Listing Branch Names

  • トピックブランチのみ
git branch
  hoge
* master
  • リモート追跡ブランチ
git branch -r
  origin/HEAD -> origin/master
  origin/master
  • 両方
git branch -a
  hoge
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

Viewing Branches

  • こういう歴史において...
776b2c7 * hoge add hoge2
f9a9164 *   master Merge branch 'piyo'
        |\  
2bf157b | * piyo add piyo
f95731e * | add hoge
        |/  
b52f5cf * initial commit
git checkout hoge
git show-branch
* [hoge] add hoge2
 ! [master] Merge branch 'piyo'
  ! [piyo] add piyo
---
*   [hoge] add hoge2
--  [master] Merge branch 'piyo'
*++ [piyo] add piyo
  • 上半分: ブランチ一覧
    • 凡例
      • * カレントブランチ
      • ! カレントブランチでない
    • カラム位置が下半分のマトリックスに対応
  • 下半分: HEADコミット一覧
    • 凡例
      • +, *
        • カラム位置に対応するブランチの歴史に含まれるコミット
        • *はカレントブランチを示す
      • -
        • マージコミット
      • なし
        • カラム位置に対応するブランチの歴史には含まれないコミット
        • 例: 776b2c7 add hoge2 はmasterブランチ、piyoブランチの歴史には含まれない
  • git branch同様、-r, -aオプションを利用可能
  • おおむね時間逆順
    • 【補】正確にはDAGのトポロジカルソート
  • デフォルトで、マトリックスの各カラム1回ずつ出現するまで探索する
  • 表示数を増やすには--more=numオプションを使用する
git show-branch --more=2
* [hoge] add hoge2
 ! [master] Merge branch 'piyo'
  ! [piyo] add piyo
---
*   [hoge] add hoge2
--  [master] Merge branch 'piyo'
*++ [piyo] add piyo
*+  [master^] add hoge
*++ [master~2] initial commit
  • ブランチ絞れる
git show-branch --more=2 hoge master
* [hoge] add hoge2
 ! [master] Merge branch 'piyo'
--
*  [hoge] add hoge2
-- [master] Merge branch 'piyo'
*+ [master^2] add piyo
*+ [master^] add hoge
  • glob利用可能
git branch -m piyo feature/piyo
git branch -m hoge feature/hoge

git show-branch  feature/*
! [feature/hoge] add hoge2
 ! [feature/piyo] add piyo
--
+  [feature/hoge] add hoge2
++ [feature/piyo] add piyo

Checking out Branches

git checkout ref
  • 作業ディレクトリに変更を加える
  • 未コミットのデータが失われないような安全装置はある

A Basic Example of Checking out a Branch

  • 即座に終了しても別に失敗してないから安心して

Checking out When You Have Uncommited Changes

  • 未コミットのデータが失われないような安全装置がある

ケース1: 現在のコミットで未追跡のファイルが、checkout先のコミットで追跡済の場合

git checkout feature/piyo
echo "hoge2" >> hoge2 # 未追跡のhoge2ファイル作成
git status
On branch feature/piyo
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    hoge2

nothing added to commit but untracked files present (use "git add" to track)
  • hoge2ファイルを追跡済のhogeブランチをcheckoutしようとする
git show feature/hoge:hoge2
hogehoge
  • 未追跡のhoge2ファイルが上書きされてしまうのでエラー
git checkout feature/hoge
error: The following untracked working tree files would be overwritten by checkout:
    hoge2
Please move or remove them before you switch branches.
Aborting
  • git追跡下においても、未commitだとダメ
git add hoge2 # 追跡
git checkout feature/hoge
error: Your local changes to the following files would be overwritten by checkout:
    hoge2
Please commit your changes or stash them before you switch branches.
Aborting
  • git stashでindexを退避すればcheckout可能
git stash
git checkout feature/hoge
git stash pop
Saved working directory and index state WIP on feature/piyo: 2bf157b add piyo

Switched to branch 'feature/hoge'

Auto-merging hoge2
On branch feature/hoge
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   hoge2

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (842e81245ee2b751af069e2de44222eed99b05f7)
  • -fオプションで未追跡のhoge2を捨てることもできる
git checkout -f feature/hoge

【補】ケース2: 現在のコミットで追跡済のファイルが、checkout先のコミットにない場合

git checkout hoge
echo "hoge" >> hoge # 追跡済のhogeファイルに変更を加える
git show feature/piyo:hoge
  • checkout先のコミットにhogeファイルはない
fatal: Path 'hoge' does not exist in 'feature/piyo'
  • checkout先にはhogeファイルがないため、gitはhogeファイルを削除しようとする
  • 未コミットの変更が失われてしまうため、エラー
git checkout feature/piyo
error: Your local changes to the following files would be overwritten by checkout:
    hoge
Please commit your changes or stash them before you switch branches.
Aborting

Merging Changes into a Different Branch

git checkout feature/piyo
echo hoge2 > hoge2
git add hoge2
git status
On branch feature/piyo
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   hoge2
  • hoge2ファイルのあるfeature/hogeブランチをcheckout
git show feature/hoge:hoge2
hogehoge
  • 未コミットの変更が失われるためエラー
git checkout feature/hoge
error: Your local changes to the following files would be overwritten by checkout:
    hoge2
Please commit your changes or stash them before you switch branches.
Aborting
  • -mオプションをつける
git checkout -m feature/hoge
M    hoge2
Switched to branch 'feature/hoge'
  • status確認
git status
On branch feature/hoge
Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

    both added:      hoge2

no changes added to commit (use "git add" and/or "git commit -a")
  • コンフリクトの解決が必要
cat hoge2
<<<<<<< feature/hoge
hogehoge
=======
hoge2
>>>>>>> local
  • 作業ブランチを作ったのに間違ってmasterで作業してしまった場合などに有効
    • 【所感】こういうときはいつもgit stashしていた

Creating and Checking out a New Branch

git checkout -b new-branch [start-point]
  • 下と同義
git branch new-branch [start-point]
git checkout new-branch

Detached HEAD Branches

  • branchのHEAD以外のコミットをチェックアウト
    • タグ等も該当
git checkout master^
Note: checking out 'master^'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at f95731e add hoge
git branch
* (HEAD detached at f95731e)
  feature/hoge
  feature/piyo
  master
  • bisect中のヤツとかもこの類
* (no branch, bisect started on master)
  feature/hoge
  feature/piyo
  master
  • git branchまたはgit checkout -bでnamed branchを作れる

Deleting Branches

git branch -d target-branch
  • カレントブランチは削除不可
  • カレントブランチの歴史に含まれないコミットを含むブランチを削除不可
  • 例: こういう歴史において
7b598af * feature/hoge2 add hogehoge
f07d76c * feature/hoge modified hoge2
776b2c7 * add hoge2
f9a9164 *   master Merge branch 'piyo'
        |\  
2bf157b | * feature/piyo add piyo
f95731e * | add hoge
        |/  
b52f5cf * initial commit
  • master(f9a9164)はfeature/hoge(f07d76c)を含まないので、masterにいるときはfeature/hogeを削除できない
git checkout master
git branch -d feature/hoge
error: The branch 'feature/hoge' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature/hoge'.
  • feature/hoge2(7b598af)はfeature/hoge(f07d76c)を含むので、feature/hoge2にいるときはfeature/hogeを削除できる
git checkout feature/hoge2
git branch -d feature/hoge
Deleted branch feature/hoge (was f07d76c).
  • コミットを含むかどうかはgit show-branchコマンドで確認できる
git show-branch
* [feature/hoge] modified hoge2
 ! [feature/hoge2] add hogehoge
  ! [feature/piyo] add piyo
   ! [master] Merge branch 'piyo'
----
 +   [feature/hoge2] add hogehoge
*+   [feature/hoge] modified hoge2
*+   [feature/hoge^] add hoge2
-- - [master] Merge branch 'piyo'
*+++ [feature/piyo] add piyo
  • feature/hoge, feature/hoge^はmasterブランチに含まれていない
    • ↓抜粋
   ! [master] Merge branch 'piyo'
----
*+   [feature/hoge] modified hoge2
*+   [feature/hoge^] add hoge2
  • git branch -Dで無視して削除できる
  • ブランチ名の作成、変更、操作、マージ、削除等の歴史の記録はない
  • ブランチのコミットの歴史は別
    • DAGという形で残る
    • DAG上で、ブランチ名やタグから到達不可能なコミットはいずれ削除される

英語

  • reconcile
    • 調和させる
  • disparate
    • 完全に異なる
  • first-rate
    • 最上級の
  • shrub
    • 低木
  • smattering
    • 聞きかじりの
  • bleeding-edge technology
    • 信頼性のリスクが高く、活用するために高い費用が掛かるような技術
  • stake
      • stakeholder: 地面に杭を打ち込んで権利を主張する者の意
  • a multitude of
    • 多数の
  • plumbing
    • 低レベルの、くらいの意味で使われている
      • 高レベルコマンドからつなぎ合わせて利用されるやつ
  • devote
    • ゆだねる
  • be alarmed at
    • ...に不安を感じる
  • instantaneously
    • 即座に
  • catch-22
    • 逃れようのない状態
  • advisable
    • 賢明である