🙄

git branch -dとgit branch -Dの内部処理に関して

に公開

Git を使用する開発者なら誰でも、不要になったブランチを削除する場面になったことはあるんじゃないでしょうか?
Git では、ブランチを削除するための二つの主要コマンド、git branch -dgit branch -D が用意されています。この記事では、これら二つのコマンドの違いと内部処理について詳しく解説します。

基本的な違い

コマンド 説明 安全性
git branch -d 安全なブランチ削除(小文字の d) 高い
git branch -D 強制的なブランチ削除(大文字の D) 低い

git branch -d(安全な削除)

動作原理

git branch -d コマンドは「安全な削除」を実行します。このコマンドは、削除対象のブランチの変更内容が他のブランチ(通常はメインブランチ)に既にマージされていることを確認してから削除を実行します。

内部処理の流れ

  1. 削除対象ブランチが指すコミットハッシュを特定
  2. そのコミットが現在のブランチ(または指定されたブランチ)の履歴に含まれているか確認
  3. すべての変更がマージされていることが確認できた場合、ブランチの参照を安全に削除

使用例

git branch -d feature/login-page

git branch -D(強制削除)

動作原理

git branch -D コマンドは「強制削除」を実行します。このコマンドはブランチの状態に関わらず、指定されたブランチを無条件で削除します。マージされていない変更があっても、警告なしで削除されるため注意が必要です。

内部処理の流れ

  1. マージ状態のチェックをスキップ
  2. ブランチの参照を直接削除
  3. 関連するリフログ(reflog)エントリも削除される

使用例

git branch -D experimental-feature

技術的な内部処理の詳細

Git の内部では、両方のコマンドは以下のような処理を行っています:

  1. .git/refs/heads/<branch_name> に保存されているブランチ参照ファイルを操作
  2. -d オプションの場合:
    • git rev-list コマンドを内部的に使用して、削除対象ブランチのコミットが現在のブランチに含まれているか確認
    • 具体的には git rev-list <current_branch>..<branch_to_delete> のようなコマンドで差分を確認
  3. 削除が許可される場合:
    • 参照ファイルを削除(rm .git/refs/heads/<branch_name>
    • 必要に応じて .git/packed-refs ファイル内の関連エントリも更新

使い分けのガイドライン

git branch -d を使うべき場合

  • 開発が完了し、変更がメインブランチにマージされたフィーチャーブランチを削除する場合
  • 通常の開発ワークフローの一部としてブランチを整理する場合
  • チーム開発環境で、重要な変更を誤って失わないようにしたい場合

git branch -D を使うべき場合

  • 実験的な変更を含むブランチで、その変更を永久に破棄したい場合
  • マージする予定のない一時的なブランチを削除する場合
  • ブランチの変更内容を意図的に捨てたい場合

注意点と回復方法

git branch -D を使用すると、マージされていない変更が完全に失われるリスクがあります。
ただし、Git は削除されたブランチのコミットを一定期間(通常は30日)保持し、復旧できる可能性があります。

ブランチを誤って削除した場合の回復方法:

  1. git reflog を使用して削除されたブランチの最後のコミットハッシュを見つける
  2. 新しいブランチを作成して回復:
    git checkout -b recovered-branch <commit-hash>
    

まとめ

  • git branch -d:安全に使えるブランチ削除コマンド。マージ済みのブランチのみ削除可能
  • git branch -D:強制的にブランチを削除するコマンド。マージ状態に関わらず削除実行
  • 通常の開発では -d オプションを使用し、実験的な変更を破棄する場合にのみ -D オプションを使用するのが推奨される方法

Discussion