This post is a collection of git tips and tricks that have improved my life while working on all kind of codebases, from small libraries to huge monorepos hosting the services of a whole org. Some tips are Emacs-specific, others will take the shape of simple git oneliners that I use daily. This is a 'live' article and it will keep evolving as I collect more tips.

Emacs: Reviewing PRs

Reviewing code occupies a good chunk of the average day of most developers, or at least those of us that are still pursuing the "individual contributor" career path. I know, poor lost souls. In the age of AI, we still care about such a legacy craft! But somebody has to keep writing the code that LLMs can later learn from and cannibalize..

While reviewing code in Github/Codeberg/etc is to some degree unescapable (even if just for the few seconds needed to write the infamous LGTM ), I have developed the habit to pull important changes locally and look at them from my editor. There's something that happens in my brain when I review code from the same place where I author it, which doesn't happen when I look at a diff online. Changes that look innocuous when seen in the diff view of Github tend to acquire a more 'concrete' meaning once I start playing with them in my editor and treating them as code that I wrote myself, doing the usual jump to definition, find references, et cetera. I tend to become more critical not just about surface level details, but how things fit in with the existing code.

One tool that I found particular useful for this task is git-timemachine: https://codeberg.org/pidu/git-timemachine.
With a few simple shortcuts it allows you to move up and down between different revisions of a file.

The way I use it in Doom is the following:

  • Select a buffer by moving to it (the usual SPACE + w + [one of: j,k,l,h] )
  • SPACE + g + t (git-timemachine-toggle): enable git-timemachine mode on a buffer
    • Once this mode is active, it will show the short info of the last commit at the top of the buffer
  • CTRL + k (git-timemachine-show-previous-revision): move backwards in the git history of this file
  • CTRL + j (git-timemachine-show-next-revision): move forward in the git history of this file

Being able to quickly see the file changing under your fingers definitely helps get a sense of the scope of the changes, sometimes much more than just reading a static diff.

If you just want to quickly see the last commits that touched a file, you can use magit-log-buffer-file (bound to SPACE + g + L by default in Doom).

From there you can move up and down to select a commit, then press 'Enter' and magit will open another buffer to show you the related diff. This is the equivalent of doing something like git log --oneline -- <my-file>, but it's easier to quickly flip through different commits. Sadly the rendered diff doesn't have syntax highlighting, so I use this less often than git-timemachine.

Another quick tool is magit-diff-range, which lets you enter a revision to diff against (e.g. HEAD~5).

You can also use vc-annotate to display the edit history of the current file in the active buffer. Then you can move back and forth (vc-annotate-prev-revision and vc-annotate-next-revision, bound to CTRL+k and CTRL+j). Like the magit commands, this one also doesn't have any syntax highlighting (and feels a bit clunkier).

Command Line: Look at the changes brought by a specific commit

If you need to see which files were touched by a commit, you can just run the following command:

git diff-tree --no-commit-id --name-only -r <your-commit-hash>

If a commit touches multiple files, you can narrow the diff to a single file by passing the file path after the --:

git show <your-commit-hash> -- ./path/to/the/file.rs

If you want to check quickly when a file was last modified, you can run the following:

git log -1 --format='%ad' --  ./path/to/the/file.rs

Note that the -1 tells git to filter out just the last commit (works for any number, e.g.: -5). I learned this quite late in my git life, and it's much better than trying to pipe the output of git log into head -n 1 or things like that.

Sending patches

In my career I was surprised by how few people actually know how to quickly send a diff to somebody by Slack/Email/etc. so that they can apply it. You don't need to create an ad-hoc Github gist or anything like that, and it can be a very effective way to bounce around a more concrete idea of how something should be done. This is actually how the Linux kernel still reviews patches, as far as I know.

To export a diff (aka patch), you can just run something like git diff <your-commit-hash> > my.patch and then give the my.patch file to whoever you want. On their side, they will just need to run git apply my.patch in order to apply the changes. If the changes don't apply cleanly then probably you're on different commits or you have different uncommitted changes, etc.

If you're using Slack (or even Github), they both support the diff language, so I'd recommend using it to get better syntax highlighting (red for removals, green for additions). Just write the diff inside the code block as usual, e.g.:
```diff
paste your diff here
```

Sometimes precious newline characters can be lost when sending diffs. It can be quite frustrating. I recommend to use a clipboard manager like wl-copy (or pbcopy on macOS) to quickly copy the diff instead of using the mouse or some other program that might inadvertently chomp precious characters..