Git と Visual Studio 2017 その 4 : ブランチ

前回の記事ではコミットのリセットについて紹介しました。今回の記事ではブランチを見ていきます。

ブランチ : Git

ブランチは、現在のコードには手を加えることなく変更をする際に切る(作成する)もので、レポジトリの完全なコピーを持つイメージでした。コピーであれば何をしても安心ですよね。しかしプロジェクトの規模が大きい場合、レポジトリ全体をコピーするのは無理があり、この点 Git はうまく処理します。ではどのように動作するか見ていきましょう。

1. ブランチを切る前に現在の .git ディレクトリのプロパティより、サイズおよびファイル/フォルダ数を確認。

image

2. ‘git branch dev’ を実行して dev ブランチを作成。

image

3. 再度 .git ディレクトリのプロパティを確認。ファイル数が 2 つ増加。これらのファイルは .git\refs\heads および .git\logs\refs\heads ディレクトリに dev ファイルが作成されたため。

image

4. 作成されたファイルを type で表示。

image

5. 一方 .git\refs\heads\master を見た場合も同じ SHA1 ハッシュ値を持っている。つまりブランチを作成した際、Git はレポジトリーをコピーすることはなく、新しいブランチ名と同じファイルが作成しコミットのハッシュ値をコピーするだけのため、高速に完了する模様。

image

6. 現在 master ブランチにいるため、‘git checkout dev’ で dev ブランチに移動(チェックアウト)。HEAD を確認するとポイントしている先が dev ファイルになっているため、ブランチの移動は HEAD の書き換と同等。

image

ブランチにコミット

Dev ブランチを切ったので、早速コミットして何が起きるか見てみましょう

1. ’git branch’ を実行して dev ブランチにいることを確認。

image

2. “Class4.cs” ファイルをソリューションに追加してコミット。Class4.cs は新規追加で追跡対象となっていないため、’git commit –a’ ではコミット対象とならない。個別に追加してからコミットを実行。また Visual Studio ですべてのファイルを保存し忘れると、プロジェクトファイルの変更が認識されないため注意。プロジェクトファイルは既に追跡対象となっているため、明示的に add せず、commit –a でコミット対象となる。

image

3. ‘git log --oneline --graph’ を実行して履歴を表示。HEAD は dev ブランチをポイントしており、これまでの履歴の最後に新しいコミットが追加されている。

image

4. master ブランチに切り替えて履歴を再度確認。今度は dev ブランチの最後のコミットが表示されていない。

image

ブランチの削除

このタイミングでブランチを削除するとどうなるか、やってみましょう。

1. ‘git branch -d dev’ を実行してブランチを削除。しかし Git はまだ変更がマージされていないと警告を表示して削除を阻止。理由はこのままブランチを削除すると変更内容が失われるため。

image

2. 次は ‘git branch -D dev’ を実行。この場合強制的にブランチが削除さえるが、dev ブランチが最後にポイントしていたコミット ID を表示。

image

3. エクスプローラーで見ると、確かに dev ファイルが無い。つまり最後の変更である Class4.cs ファイルも削除された?

image

4. 前回の記事で説明した通り、Git は既定で 90 日間は Git オブジェクトを削除しないため、実際には消えていない。復旧する方法は色々あるが、今回の場合 ‘git reset --hard c79adb2’ を行うと復旧される。‘git log --oneline’ で結果を確認。今回は dev ブランチだけで変更があったため、競合なく復元できたが、この辺りは今後の記事で説明。

image

Git オブジェクトとしてのコミットは存在しているため、reset コマンドで master がポイントするコミットを変更できました。またこのコミットオブジェクトが保持する親コミットの ID は 3fd99cb であったため、履歴的にも矛盾がありません。Git オブジェクトには何も変更がなく、refs\heads\master の値が書き換わっただけです。

ブランチ : VS

次に Visual Studio 2017 でのブランチを見ていきます。

1. ステータスバーにある Git 情報を確認。左がレポジトリ名、右が現在のブランチ名。

image

2. master をクリックして ”新しいブランチ” をクリック。ブランチメニューに遷移。

image

3. ブランチ名を指定。ひとつ下のドロップダウンでは作成したブランチがポイントしたいブランチを指定。今回は master しかないため既定のまま。”ブランチのチェックアウト” チェックボックスを付けると、ブランチの作成時にチェックアウトも実施される。Git も ‘git checkout –b dev’ で同じことが可能。

image

4. ブランチが作成されると GUI で確認できる。太字になっているブランチが現在チェックアウトされているブランチ。任意のブランチを右クリックしてチェックアウトすることができるが、個人的にはステータスバーを使うほうが現在のブランチを確認することも、替える事も便利。

image image

5. dev ブランチにいることを確認して、Class5.cs ファイルを追加。右クリックメニューよりコミットを選択。

6. コミットコメントを入力して、”すべてをコミット” をクリック。この時点で保存していないファイルがあると保存のダイアログが表示される。とても便利。

image image

7. アクション | 履歴の表示よりローカル履歴を確認。dev ラベルが最新のコミットを、master ラベルが直前のコミットをポイントしていることを確認。

image

8. 次は削除を検証。master ブランチに切り替え。

image

9. dev ブランチを右クリックして削除。Git でも表示されたように、マージされていない旨が表示される。ここで OK をクリックすると -D オプションと同じ効果。

image image

Visual Studio でもほぼ同じ操作が可能ですが、削除されたブランチに紐づくコミットを VS からは復旧できませんでした。

ブランチの復旧

最後にブランチの復旧について見ていきます。

1. 検証のため、dev ブランチを作成し、Class 5.cs、Class6.cs をそれぞれコミット。

image

2. この時点で再度 dev ブランチを削除。

image

3. ‘git reset --hard 5df97d2’ を実行すると情報は復旧されるものの、master ブランチに復旧されるため先ほどと履歴が異なる。

image

4. 一旦 dev ブランチを削除した状況に戻すため、‘git reset --hard c79adb2’ を実行。

5. ここで ‘git checkout 5df97d2’ を実行し、コミット 5df97d2 の状態に遷移。Git が “detached HEAD” という警告を出すが、これは HEAD がどのブランチもポイントしていない状態の事であり問題なし。

image

6. ‘git branch’ を実行すると master 以外に Head detached ととして 5df97d2 が表示。HEAD の中身もブランチをポイントせず、直接コミットをポイント。

image image

7. ‘git checkout -b dev’ を実行。現在のコミットをポイントする新しい dev ブランチを作成。’git branch’ を実行すると Detached Head はなくなり、dev ブランチが存在。履歴もブランチ削除以前に復旧。

image

まとめ

見てきた通り、Visual Studio 2017 のブランチサポートは Git の機能全てをカバーしませんが、重要な機能はサポートしています。またブランチを間違えて消した場合も、Git の動作としてあくまでコミットをポイントするためのラベルであることを理解していると、慌てることなく復旧が行えます。次回はマージを見ていきます。次の記事へ

中村 憲一郎