HOW TO USE GIT BISECT TO PINPOINT EMACS BUGS -*- outline -*- This documents explains how to use git bisect to find the commit that introduced an Emacs bug. Bisecting works best if the bug is easy and relatively quick to reproduce in a clean ‘emacs -Q’ instance. For general information about bisecting, use ‘M-x man git-bisect’. This document contains quick-start instructions and Emacs-specific tips. * Bisecting Emacs bugs First, find a recipe that reproduces the bug in emacs -Q. Then use this recipe to locate a revision in which the bug doesn't happen. If it's a new bug, a not-too-recent revision could do; otherwise, checking for the bug previous releases of Emacs works well. Then, run the following command to start bisecting git bisect start is usually HEAD in practice. Git will then check out revisions between these two bounds,; at each step, you need to run ‘git bisect good’ or ‘git bisect bad’ to inform git of the status of the current revision: ‘bad’ if it has the bug; good if it doesn't. If Emacs' build is broken in the current revision, use ‘git bisect skip’ to move to a neighboring revision. ** Automating ‘git bisect’ You can also write ‘git bisect run ’ to automate the process. ‘’ should build Emacs, run your bug reproduction test, and return 0 if the current revision is good, and 1 otherwise. Returning 125 is equivalent to doing ‘git bisect skip’. Concretely, ‘’ usually looks like this: #!/usr/bin/env bash # Remove leftovers from previous runs git clean -xfd > /dev/null # Build Emacs and skip commit if build fails (./autogen.sh && ./configure --cache-file=/tmp/emacs.config.cache && make -j4) || exit 125 # Reproduce the bug, writing output somewhere src/emacs -Q -l "../reproduce-the-bug.el" || exit 125 # Remove leftovers again git clean -xfd > /dev/null # Analyze output and produce exit code cmp ../reference-output current-output Some caveats: - This script cleans Emacs' source directory with ‘git clean -xfd’, so make sure your uncommitted changes are saved somewhere else. - You should produce the ‘../reproduce-your-bug.el’ script on your own (it should check if the bug exists, and save a different output to a file named ‘current-output’ based on the result of that check), as well as a file ‘../reference-output’ containing the expected output in the good case. ** Using ‘git bisect’ to find display-related bugs Most bugs that manifest graphically can be checked for by programmatically inspecting text properties, but some are only apparent through visual inspection. Since building Emacs takes a long time, it can be a pain to debug these manually. Fortunately, it's relatively easy to bisect such bugs automatically. Use the following template for ‘../reproduce-the-bug.el’: (defun take-screenshot-and-exit (fname x y w h) "Save a screenshot of Emacs as FNAME, then exit. X and Y are the coordinates of the top-left point of the area of interest. W, and H are its dimensions." (let ((window-id (frame-parameter nil 'outer-window-id))) (call-process "xwd" nil nil nil "-silent" "-id" window-id "-out" fname)) (call-process "mogrify" nil nil nil fname "-crop" (format "%dx%d+%d+%d" w h x y)) (kill-emacs)) (defun main () ;; Reproduce your bug here … ;; Force a redisplay (redisplay t) ;; Insert rough X, Y, W, H values below (run-with-timer 0 nil #'take-screenshot-and-exit "screenshot.xwd" … … … …)) (main) This script makes a screenshot of Emacs after reproducing your bug (if ‘xwd’ isn't available, you can use ImageMagick's ‘import’ tool, passing it a ‘-window’ argument where ‘xwd’ wants ‘id’). Cropping the image is useful to weed out unrelated display changes; try to include only a small portion of the screen containing your bug. Then to produce the right exit code use ImageMagick's ‘identify’ tool: cmp <(identify -quiet -format "%#" "../screenshot.xwd") <(identify -quiet -format "%#" "../good.xwd") ‘good.xwd’ should be the image produced by your script in the good state.