Share via


Git 履歴の簡略化について

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Git 履歴の簡略化は、混乱を招く厄介なものになる可能性があります。 99% の場合は、それが存在することすら気がつかないでしょうが、時として Git の暗い片隅から飛び出して噛み付くでしょう。 この記事では、履歴の簡略化とは何か、およびファイル履歴を参照するときにそれがどのように混乱を引き起こす可能性があるかついて見ていきます。

では、一般的なシナリオから始めましょう。

  1. ファイルに変更をプッシュし、変更を main にマージします。
  2. 一部の同僚も、ブランチを main にマージします。
  3. しばらくして戻ると、変更が見つからないことに気付きます。
  4. 原因を探すためにファイルの履歴を参照すると、変更は一覧にすら表示されていません。

Git コミット履歴はツリーです。 場合によっては、時系列の履歴は実際のファイル ツリー履歴と同じではありません。 この状況は、マージ コミットによってファイルが元の状態に戻されるときに最も多く発生します。 その場合、技術的にはファイルは変更されていないため、既定の履歴ビューでは、"すべての変更が実際に表示されるわけではありません"。 このシナリオでは、Git で履歴を簡略化できることが認識され、探している可能性が最も高い "変更" が、ログから削除されます。

このことを経験したことがない限り、変更はいったいどこへ行ったのか疑問に思い、不満に思うかもしれません。

履歴の簡略化: 既定でオン

既定では、ファイルに対して log コマンドを実行すると (git log file.txt) 自動的に履歴が簡略化され、おそらく一部のコミットが出力から非表示になります。 詳細については、git log の man ページを参照してください。

混乱に輪を掛けるのは、履歴の簡略化は git log を実行するだけでは "行われない" ということです。これは、すべての変更を参照しているとき、簡略化するものがないためです。

履歴の簡略化を無効にするには、コマンド ライン スイッチ --full-history を使用する必要があります。

履歴の簡略化の例

簡略化のしくみをより深く理解するために、履歴の簡略化の独自の例を作成します。 まず、作成する履歴の図を見てみましょう。

Git ブランチ

ご覧のとおり、次の手順を実行します。

  1. ファイルを作成します。
  2. ブランチ (動物) で、そのファイルに行を追加します。
  3. 別のブランチ (フルーツ) で、そのファイルに別の行を追加します。
  4. "動物" ブランチを元の main にマージします。
  5. "フルーツ" を元の main にマージし、フルーツ ブランチからファイルのコピー全体を選択します。
  6. ファイルの履歴を確認します。

Git は自動的に履歴を簡略化します。 ここでは手順 5 が重要です。 "動物" ブランチの変更はすべて無視しました。 Git では、手順 1 と手順 5 の間でファイルが基本的に "変更されていない" ことが認識されたため、"2 つの履歴エントリ" のみが表示されます。

最初にファイルを作成し、それをリポジトリに追加します。

> cd sample
> git init
> echo "some content" > test.txt
> git add test.txt
> git commit -m "Initial commit"

次に、動物ブランチで、"donkeys" というテキストをファイルに追加することにしました。

> git checkout -b animals
> echo "donkeys" >> test.txt
> git commit -am "We have added an animal"

実験中に、ファイルに代わりにフルーツを入れることがおそらく必要になると判断されたため、別のブランチを作成し、ファイルの末尾に "bananas" というテキストを追加します。

> git checkout main -b fruit
> echo "bananas" >> test.txt
> git commit -am "We have added a fruit"

変更に満足したため、動物ブランチを元の main にマージすることにしました。

> git checkout main
> git merge animals

次に、test.txt ファイルのログ見てみましょう。

> git log test.txt
    
    commit 6b33d99b996c430a60c9552b79245d1aa8320339
        Date:   Mon Feb 15 10:45:33 2016 -0500

        We have added an animal

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

ここまでは問題ありません。 ログ出力に異常は見あたりません。 次に、考えを変えて、フルーツ ブランチをマージすることにしたとします。

>git merge fruit
    
    Auto-merging test.txt
    CONFLICT (content): Merge conflict in test.txt
    Automatic merge failed; fix conflicts and then commit the result.

これはマージの競合です。 しばらく検討した後、フルーツ ブランチから "test.txt ファイル全体" を使用することにしました。 通常は、何らかのテキスト エディターまたはマージ ツールを使用しますが、わずか 2 行であるためファイル全体を作り直します。

> echo "some content" > test.txt
> echo "bananas" >> test.txt
> git commit -am "Fixed merge conflict"

ここで、test.txt ファイルの履歴を見てみましょう。

> git log test.txt
    
    commit fdd4dfd816c4efebc5bdb240f49e934e299db581
        Date:   Mon Feb 15 10:51:06 2016 -0500

        We have added a fruit

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

確かに、ログには最初の実験からの変更が表示されておらず、マージも表示されていません。 それらはまだ存在しているのでしょうか。 Git では変更が完全に除去されたのでしょうか。

> git log --full-history test.txt

ご覧のように、full-history フラグがない場合はログが簡略化されていましたが、Git ではすべての変更が保持されています。

> commit 5d0bb77a24e265dc154654fb3b5be331b53bf977
    Merge: 6b33d99 fdd4dfd
        Date:   Mon Feb 15 10:59:34 2016 -0500

        Fixed merge conflict

    commit fdd4dfd816c4efebc5bdb240f49e934e299db581
        Date:   Mon Feb 15 10:51:06 2016 -0500

        We have added a fruit

    commit 6b33d99b996c430a60c9552b79245d1aa8320339
        Date:   Mon Feb 15 10:45:33 2016 -0500

        We have added an animal

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

Git 履歴の簡略化のまとめ

履歴の簡略化の問題点は、ほとんどの場合、それに気付かないということです。 しかし、マージの競合に問題が発生し、何が起こったかを知りたい場合、Git ログ履歴を見て変更がどこに行ったのか疑問に思うかもしれません。

これで、パニックになる代わりに、次のことが理解できます。

  • 既定では、ファイルの履歴の簡略化が有効になっています
  • --full-history フラグでは、より包括的なファイル履歴が提供されます

アップデート: この記事の執筆後、Azure DevOps Services では多くの素晴らしい履歴表示オプションが Web 上で紹介されています。 つまり、コマンド ラインをログに記録したくない場合は、履歴を表示する必要があるファイルをエクスプローラーでプルアップするだけで、単純または単純でない履歴ビューを指定できる次の履歴フィルターが表示されます。

Git フィルター

(c) 2016 Microsoft Corporation. All rights reserved. このドキュメントは、"現状のまま" 提供されます。URL およびその他のインターネット Web サイトの参照を含む、このドキュメントの情報および見解は、予告なしに変更することがあります。 このドキュメントの使用上のリスクは、すべてユーザーが負うものとします。

このドキュメントは、Microsoft 製品の知的財産権に関する法的な権利をお客様に許諾するものではありません。 内部での参照を目的とする場合、このドキュメントをコピーして使用できます。