天天看點

Git源碼調試

前言

Git作為目前最流行的代碼版本管理工具,是DevOps工具鍊中的核心工具之一。DevOps工程師是Git的重度使用者,難免在使用中會碰到一些從文檔層面不易了解或解決的問題,需要從源碼層面進行分析。本小文旨在了解Git源碼基礎架構,能快速定位需要分析的代碼子產品,并通過IDE進行調試分析。

Git代碼結構

common main

git源碼中包含好多個git相關程式,他們的啟動過程是一緻的,可以複用一套代碼。git為此設計了一個 common main結構,原文說明如下:

* There are certain house-keeping tasks that need to be performed at
   the very beginning of any Git program, and programs that are not
   built-in commands had to do them exactly the same way as "git"
   potty does.  It was easy to make mistakes in one-off standalone
   programs (like test helpers).  A common "main()" function that
   calls cmd_main() of individual program has been introduced to
   make it harder to make mistakes.           

具體的實作是:

1、在common-main.c中定義通用的main函數,裡面調用 cmd_main

2、各個git程式在編譯時連結上面這個編譯出來的cmd-main.o

3、各個git程式定義各自的cmd_main

builtin commands

使用過git的同學都知道,git有很多子指令,譬如 checkout, add, commit, status, push等等。執行 git xxx 和執行 git-xxx 的效果是一樣的。

這些子指令在git源碼裡叫builtin,我們來看看 builtin 是怎麼實作的。

首先看編譯過程,從頂層的Makefile看到如下生成語句:

$(BUILT_INS): git$X
        $(QUIET_BUILT_IN)$(RM) $@ && \
        ln $< $@ 2>/dev/null || \
        ln -s $< $@ 2>/dev/null || \
        cp $< $@           

builtin是git的連結或是拷貝而來的,實際是一個東西。

在代碼層面,git.c 維護一個builtin的清單,

static struct cmd_struct commands[] = {
    { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
    { "am", cmd_am, RUN_SETUP | NEED_WORK_TREE },
    { "annotate", cmd_annotate, RUN_SETUP },
    { "apply", cmd_apply, RUN_SETUP_GENTLY },
    { "archive", cmd_archive },
    { "bisect--helper", cmd_bisect__helper, RUN_SETUP },
    { "blame", cmd_blame, RUN_SETUP },
    { "branch", cmd_branch, RUN_SETUP },
    { "bundle", cmd_bundle, RUN_SETUP_GENTLY },
    { "cat-file", cmd_cat_file, RUN_SETUP },
        ... ...
}           

cmd_struct的第一個字段是子指令的名稱,第二個字段是具體執行函數。get_builtin 函數根據名稱找到結構,然後run_builtin執行結構裡的指令。

所有的builtin的源碼都在builtin子目錄下,譬如builtin/add.c 對應 git add 子指令,裡面定義cmd_add函數執行具體的操作

git代碼調試

調試的前提是能編譯通過,是以需要先安裝依賴的包:

$ sudo apt-get install libssl-dev zlib1g-dev libcurl4-openssl-dev

還有個小細節,git的源碼預設是按-O2編譯的,會導緻在Eclipse調試的時候檢視變量值顯示 optimized out, 很不友善,是以需要更改編譯選項。

編譯過程是通過Makefile組織的,我們需要修改Makefile。Makefile裡有引入configure生成的configure.mak.autogen, 裡面也有編譯選項,是以需要同時改configure和Makefile

$ edit configure and Makefile , from -O2 to -O0

$ ./configure

$ make clean

$ make all