taisablog

taisa's engineer blog

Git

Gitのソースコードをデバッグする

投稿日:November 30, 2016 更新日:


これまでGitの内側の仕組みなどをチェックしてきて、最近ようやくソースコードをデバッグしてみても処理が追えそうというところまできたので記事にまとめておきます。ただ色々試しながらやった結果なので、もっとよいやり方はあるかもしれません。

emacsとgdbをインストール

今回OSはCentOSを使っていきます。

sudo yum install emacs
sudo yum install gdb

gitのソースコードをクローンする

今回はGitHubにあるソースコードを利用します。

git clone https://github.com/git/git.git
cd git
# バージョンを指定してチェックアウトしておきます。
git chekcout -b v2.6.0-rc1

ソースコードをコンパイルする

まず必要なライブラリをインストールしてからコンパイルします。

yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
make

emacsを起動してデバッグをする

環境が整ったので、ここからgdbを起動しgitコマンドのデバッグをしていきます。gdbはそのまま起動しても使えますが、emacsからの方がデバッグしやすいのでemacsからgdbを起動します。

# emacsを起動する
emacs -nw
# gdbを起動する
M-x
gdb
gdb --annotate=3 git
# main関数で止まるようにブレークポイントを指定します
(gdb) b main
# 実行
(gdb) r
20150915005627

デバッガが起動しました。画面上側がコマンドラインで、下側がソースになっています。

# ステップ実行(next)
(gdb) n
# 変数の内容をチェック
(gdb) print argc
$1 = 1
# ステップイン(step)
(gdb) s
# 最後まで実行(continue)
(gdb) c

gitコマンドを実行した場合、676行目までいき usage と The most commonly used git commands が表示されて終了します。

    /* The user didn't specify a command; give them help */
    commit_pager_choice();
    printf("usage: %s\n\n", git_usage_string);
    list_common_cmds_help();
    printf("\n%s\n", _(git_more_info_string));
=>  exit(1);

まとめ

普段開発ではIntelliJを利用しているのでCLionでもできないかと色々試してみましたが、そもそもMacでコンパイルを通すこともできず断念しました。ただおかげでLinux環境でもなんとかやっていけそうなので、このままコードリーディングを進めてみようと思います。

参考

-Git
-

執筆者:

関連記事

Gitの参照 – HEADとheadsとtagsとremotes

Gitの参照についてまとめました。また別記事にてGitの内側について記載しています。 配管(Plumbing)と磁器(Porcelain)Git オブジェクト Gitの内側についておさらい 「git init」すると「.git」ディレクトリができるがその中についてがテーマ普段は使わない配管コマンドと呼ばれる下位レベルのコマンドがある4つのオブジェクトがある blobオブジェクト(ファイルに相当) treeオブジェクト(ディレクトリに相当) commitオブジェクト(commit情報を保持) tagオブジェクト(Tagを保持) Gitの参照って? ここで取り上げるGitの参照は「HEAD」ファイルと「.git/refs」配下のことを示します。「git init」した直後「HEAD」ファイルは「refs/heads/master」を参照し(初期化直後はなにも存在しない)、「.git/refs」配下には、headsとtagsディレクトリがあります。ブランチにcommitするとheads配下にブランチ名のファイルができ、HEADファイルはheads配下のブランチ名を参照します。 # masterにcommit後 # HEADファイル ref: refs/heads/master # refs配下の構造 └── refs ├── heads │   └── master └── tags Gitの参照の種類 Gitの参照の種類は次の通りです。 heads:作業中ブランチのcommitを参照tags:commitをわかりやすくする為の名前付け用remotes:リモートブランチのcommitを参照HEAD:作業中のブランチに対するシンボリック参照。HEADは基本的にheadsを参照しているので、他の参照と区別する為シンボリック参照と呼ばれます 動作確認の為の事前準備 次のような3つのcommitがあるリポジトリを用意しremoteへpushしておきます。 % git log –pretty=oneline master 1f36229bc26825222b191dcd63929392d9d8e2fd third commit 543ee947f5a865e1a998f793120667c3bf89fc80 second commit 23391397b4316d334e9293c4f7d1d601c1f24c4c first commit % git remote add origin git@github.com:taisa007/internal-git.git 次からはこのリポジトリを利用します。クローンする場合はこちらを利用してください。 構成 構成は次の通りです。「.git/refs」ディレクトリ配下にそれぞれheads, remotes, tagsというディレクトリが作られています。 % tree .git └── refs ├── heads │   └── master ├── remotes │   └── origin │   └── master └── tags Gitの参照の解説 「refs」配下にあるファイルはそれぞれ最後のcommitをファイルに記録しています。例えば現在masterは「third commit」にいますが「git log –pretty=oneline master」とすると次のようなcommit履歴が確認できます。 % git log –pretty=oneline master 1f36229bc26825222b191dcd63929392d9d8e2fd third commit 543ee947f5a865e1a998f793120667c3bf89fc80 second commit 23391397b4316d334e9293c4f7d1d601c1f24c4c first commit …

Git 2.9でdiffがちょっとかしこくなった

ちょっと前にはなるがGit 2.9がリリースされてdiffがちょっとかしこくなった。 リリースノート Git 2.9 Release Notes 記事 Git 2.9 has been releasedGit2.9のキレイなdiffを出すためのconfig diffをいままでよりいい感じにする git diffに「–compaction-heuristic」オプションを追加するかgit configに「diff.compactionHeuristic true」を設定することで、これまでdiffがコンフリクト起こして正しく出せてなかったケースをカバーするようになった。今回のリリースではオプションつけるか設定変更する必要があるけど後々デフォルトになる予定とのこと。ちなみにほんとかな?と記事のソースで新旧バージョンで比較してみたところしっかり解消されてました。はいすいません。オプションつける場合 git diff –compaction-heuristic コンフィグに設定する場合 git config –global diff.compactionHeuristic true ハイライトもこれまでよりいい感じにできる diff-highlightでは同行の文字変更を見やすくするというものだけどこれ自体は以前からあった。ではどこが変わったかというと、これまでごく一部でハイライトできなかったけどそれ解消したよってことだと思う。でこっちも設定変える必要あるよとのこと。設定がなければ追加 git config –global pager.log ‘diff-highlight | less’ git config –global pager.show ‘diff-highlight | less’ git config –global pager.diff ‘diff-highlight | less’ 今回のリリースで追加された新しい設定 git config interactive.diffFilter diff-highlight ということで今回のリリースによって.gitconfigに設定が追加された。 [diff] compactionHeuristic = true [interactive] diffFilter = diff-highlight