How to debug git with visual studio code on a mac
I needed to figure out how to debug the git
binary to figure out exactly what it was doing, and I thought I'd share the setup because it took me a little while to get going.
Prerequisites
- install visual studio code
- install the microsoft C/C++ extension
- you will need to have
lldb
, the llvm debugger available on your system.- To see if you have
lldb
available, runwhich lldb
; as long as it prints a path and notlldb not found
, you're good to go - The most common way to get it installed is to install
Xcode
from the app store or theXcode Command Line Tools
which can be installed withxcode-select --install
- You may also install it with homebrew by doing
brew install llvm
. Be aware though that brew will not link it by default, so you'll have to figure out how to tell vs code to use it
- To see if you have
Building git
- Clone the git repository:
git clone https://github.com/git/git
- Change into the cloned directory:
cd git
- Set some build variables by creating a file called
config.mak
. It should have exactly these contents:DEVELOPER=1 CFLAGS+= -O0
- A command you might use to make this file:
printf 'DEVELOPER=1\nCFLAGS+= -O0' > config.mak
- see the Makefile for more info on what
DEVELOPER
does - the
CFLAGS
variable provides a flag to the C compiler to build a binary with no compiler optimizations; traditionallyO3
means "the most optimizations" andO0
means "no optimizations"- clang documentation on optimization options
- A command you might use to make this file:
make -j4
- The
-j
argument to make tells it how much parallelism it can use. It speeds up the build by increasing parallelism; you can use more if you have more CPUs, or less if you have fewer. The build doesn't take very long though so it's not a big deal.
- The
- When this completes successfully, you should have a bunch of new binaries in your git directory, such as
git
,git-add
,git-am
, etc
Debugging git
-
make a
.vscode
directory:mkdir .vscode
-
open the git directory with visual studio code:
code .
-
create a file in the
.vscode
directory calledlaunch.json
that tells vs code how to startgit
for debugging. Its contents should be:{ "configurations": [ { "name": "debug git", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/git", "args": ["status"], "cwd": "${workspaceFolder}", "externalConsole": false, "MIMode": "lldb" } ] }
- Note that we're passing
status
as an argument; the first command we're going to debug isgit status
. To debug other commands, you'll want to change theargs
option - See the documentation for information on these configuration options and what additional flags are available
- Note that we're passing
-
Open the
builtins/commit.c
file in the editor -
Set a breakpoint on the first line inside the
cmd_status
function; in my current version of git, that's located at line 1504- To set a breakpoint, click on the left gutter, just to the left of the line numbers; you should see a red dot appear. Once a breakpoint is set, the debugger will stop when it reaches that location, allowing you to control execution of the program
- here is VS Code's documentation on how to set breakpoints
- Annoyingly, setting a breakpoint at the function name doesn't seem to work for me, so I have to set a breakpoint inside the function or else the program doesn't break
- If you really want to do this, in the command palette there's an action called
Add Function Breakpoint
, which created a function breakpoint that I could typecmd_status
into, and that did break on the function invocation
- If you really want to do this, in the command palette there's an action called
- The
builtins
directory contains most of the high-level git UI code - git subcommands will have a function name
cmd_<command name>
; check outcmd_log
orcmd_commit
for other examples
- To set a breakpoint, click on the left gutter, just to the left of the line numbers; you should see a red dot appear. Once a breakpoint is set, the debugger will stop when it reaches that location, allowing you to control execution of the program
-
Switch to the
Run and Debug
tab of VS code -
click on
start debugging
, the green arrow located at the top left of the window, or press F5 to do the same thing.- alternatively, open your command palette with
โงโP
, typeDebug
, and selectDebug: Select and Start Debugging
, then selectdebug git
- alternatively, open your command palette with
If all goes well, you should now be controlling the execution of git inside VS code! Go ahead and dig in to try and understand what's going on.
I might write more about what it is that's going on in there, but I'm not sure - let me know if you would like to understand some part of it better.