1. ホーム
  2. ギット

[解決済み】git diffの出力を読むには?

2022-03-29 13:35:51

質問

のマニュアルページは git-diff はかなり長く、初心者には必要ないと思われるケースも多く説明されています。例えば

git diff origin/master

解決方法は?

git の履歴から高度な diff を取得する例を見てみましょう ( git.gitレポジトリのコミット1088261f ):

diff --git a/builtin-http-fetch.c b/http-fetch.c
similarity index 95%
rename from builtin-http-fetch.c
rename to http-fetch.c
index f3e63d7..e8f44ba 100644
--- a/builtin-http-fetch.c
+++ b/http-fetch.c
@@ -1,8 +1,9 @@
 #include "cache.h"
 #include "walker.h"
 
-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
+int main(int argc, const char **argv)
 {
+       const char *prefix;
        struct walker *walker;
        int commits_on_stdin = 0;
        int commits;
@@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix)
        int get_verbosely = 0;
        int get_recover = 0;
 
+       prefix = setup_git_directory();
+
        git_config(git_default_config, NULL);
 
        while (arg < argc && argv[arg][0] == '-') {

このパッチを一行ずつ解析してみましょう。

  • 最初の行

    diff --git a/builtin-http-fetch.c b/http-fetch.c
    
    は "git diff" という形式のヘッダです。 diff --git a/file1 b/file2 . その a/b/ のファイル名は、(今回のように)リネームやコピーを伴わない限り、同じになります。 そのため --git は、diffが"git"形式であることを意味します。

  • 次に、1つまたは複数の拡張ヘッダー行です。 最初の3つの

    類似性指数 95
    builtin-http-fetch.c からリネーム。
    http-fetch.cにリネーム
    
    からファイル名が変更されたことを教えてくれます。 builtin-http-fetch.c から http-fetch.c と、この2つのファイルが95%同一であること(このリネームを検出するために使用されました)。

    拡張されたdiffのヘッダーの最後の行、それは
    インデックス f3e63d7..e8f44ba 100644
    
    は、指定されたファイルのモードについて教えてくれます ( 100644 また、preimage (変更前のバージョン) と postimage (変更後のバージョン) の短縮されたハッシュ値も表示します。) この行は git am --3way は、パッチが適用できない場合に、3 者間マージを試みるためのものです。

  • 次に2行のUnified diffヘッダーです。

    --- a/builtin-http-fetch.c
    +++ b/http-fetch.c
    
    と比較すると diff -U の結果では、ソース(前画像)とデスティネーション(後画像)ファイル名の後に、from-file-modification-time と to-file-modification-time がない。 ファイルが作成された場合、ソースは /dev/null ファイルが削除された場合、ターゲットは /dev/null .

    を設定した場合 diff.mnemonicPrefix コンフィギュレーション変数を true に設定し、その代わりに a/b/ のプレフィックスを使用すると、この2行のヘッダーの代わりに c/ , i/ , w/o/ を接頭辞として、それぞれ比較するものに対して使用します。 git-config(1)

  • 次に、1つまたは複数の相違点の塊が来ます。各塊は、ファイルが異なる1つの領域を示しています。 統一されたフォーマットのハンクは、次のような行で始まります。

    @@ -1,8 +1,9 @@
    
    または
    @@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, ...)
    
    という形式になっています。 @@ from-file-range to-file-range @@ [header] . from-file-rangeは次のような形式です。 -<start line>,<number of lines> であり、to-file-rangeは +<start line>,<number of lines> . start-line と number-of-lines は、それぞれ preimage と postimage における hunk の位置と長さを表しています。 number-of-lines が表示されない場合は、1であることを意味する。

オプションのヘッダーは、各変更が発生するC関数を示し、それがCファイルである場合(例えば -p オプション)、または他の種類のファイルについては、もしあれば同等のものを使用します。

  • 次に、ファイルが異なる部分の説明です。 両ファイルに共通する行は、スペース文字で始まります。実際に2つのファイルで異なっている行は、左の印字欄に次のいずれかの指示文字があります。

  • '+' -- 最初のファイルのここに1行が追加されました。

  • '-' -- 最初のファイルから1行削除されました。



だから、例えば、最初のチャンク

     #include "cache.h"
     #include "walker.h"
     
    -int cmd_http_fetch(int argc, const char **argv, const char *prefix)
    +int main(int argc, const char **argv)
     {
    +       const char *prefix;
            struct walker *walker;
            int commits_on_stdin = 0;
            int commits;

というのは cmd_http_fetch に置き換えられました。 main と、その const char *prefix; という行が追加されました。

つまり、変更前の 'builtin-http-fetch.c' ファイルの該当箇所は、以下のようなものでした。

    #include "cache.h"
    #include "walker.h"
    
    int cmd_http_fetch(int argc, const char **argv, const char *prefix)
    {
           struct walker *walker;
           int commits_on_stdin = 0;
           int commits;

変更後の 'http-fetch.c' ファイルは、次のようになります。

    #include "cache.h"
    #include "walker.h"
     
    int main(int argc, const char **argv)
    {
           const char *prefix;
           struct walker *walker;
           int commits_on_stdin = 0;
           int commits;

  • があるかもしれません。
    \ ファイル末尾に改行がない
    
    
    の行が存在します(例diffにはありません)。

として ドナル・フェローズ氏のコメント diff を読む練習は、実際の例で、自分が何を変更したのかがわかっている状態で行うのが一番です。

参考文献