Git


1 Overview

🎯 git/cfg.personal.conf
[user]
	name = Linus Arver
	email = linus@ucla.edu
[clone]
	defaultRemoteName = u
[color]
	branch = auto
	diff = auto
	status = auto
[color "diff"]
	meta = yellow bold
	commit = blue bold reverse
[color "status"]
	untracked = yellow bold
[commit]
	cleanup = scissors
[core]
	editor = ~/syscfg/script/emacsclient-tty.sh
	excludesFile = ~/.gitignore
	hooksPath = ~/syscfg/script/git/hooks
[diff]
	algorithm = histogram
	colorMoved = default
	colorMovedWS = allow-indentation-change
	context = 5
	tool = difftastic
[difftool]
	prompt = false
[difftool "difftastic"]
	cmd = difft "$LOCAL" "$REMOTE"
[gui]
	spellingdictionary = none
[init]
	defaultBranch = main
[merge]
	conflictStyle = zdiff3
[pager]
	difftool = true
[push]
	default = simple
	autoSetupRemote = true
[rebase]
	updateRefs = true
[rerere]
	enabled = true
[sendemail]
	aliasesFile = ~/.git-sendemail-aliases
	aliasFileType = mailrc
	chainReplyTo = false
	sendmailCmd = "gmi send --quiet -t -C ~/mail/linusarver@gmail.com"
	suppressCc = self
[tag]
	sort = taggerdate
[tig]
	vertical-split = false
Makefile-git
git:
	ln -fs ${C}/git/cfg.personal.conf ${H}/.gitconfig
	ln -fs ${C}/git/sendemail-aliases ${H}/.git-sendemail-aliases

2 Email

🎯 git/sendemail-aliases
alias git git@vger.kernel.org

3 Diffs

By default running git diff gives you paged output, and sometimes it can be tricky to remember whether the diff was of the worktree or the index (what's been staged, if you passed the -c flag).

It would be nice if you could put a vertical label showing "worktree" or "index" to tell you which diff you were looking at. Below is a Rust program which does this (it uses the label "CHANGED" and "STAGED" instead of "worktree" or "index").

🎯 gd/src/main.rs
use clap::{Arg, ArgAction, Command};
use colored::*;
use std::borrow::Cow;
use std::process::Command as SCommand;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let cmd = clap::Command::new("gd")
        .version("v0.0")
        .propagate_version(true)
        .subcommand_required(true)
        .arg_required_else_help(true)
        .subcommand(
            Command::new("diff")
                .about("Show git unstaged and staged diffs.")
                .arg(
                    Arg::new("width")
                        .long("width")
                        .value_name("NUM")
                        .default_value("80")
                        .help("With of the terminal screen; used for coloring in missing trailing whitespace for better legibility. Default 80.")
                        .takes_value(true)
                        .required(false),
                )
                .arg(
                    Arg::new("staged")
                        .long("staged")
                        .help("Whether to get staged diff.")
                        .action(ArgAction::SetTrue),
                ),
        );
    let matches = cmd.get_matches();
    match matches.subcommand_name() {
        Some("diff") => {
            if let Some(m) = matches.subcommand_matches("diff") {
                let width = m
                    .get_one::<String>("width")
                    .unwrap()
                    .parse::<usize>()
                    .unwrap();
                let staged = m.get_one::<bool>("staged").unwrap();
                let diff = if *staged {
                    SCommand::new("git")
                        .args(["diff", "--staged"])
                        .output()
                        .expect("git command failed to start")
                } else {
                    SCommand::new("git")
                        .args(["diff"])
                        .output()
                        .expect("git command failed to start")
                };

                colored::control::set_override(true);
                show_diff(
                    &diff.stdout,
                    &width,
                    if *staged {
                        " STAGED ---------------------- "
                    } else {
                        " CHANGED --------------------- "
                    },
                    *staged,
                );
            }
        }
        _ => unreachable!("clap should ensure we don't get here"),
    }
    Ok(())
}

fn show_diff(output: &Vec<u8>, width: &usize, vlabel: &str, staged: bool) -> () {
    // We convert tabs into 4 spaces. This should ideally only
    // affect leading indentation, but we are too lazy to fix this
    // because 99.999% of the time literal tabs are only found in
    // the leading indentation anyway.
    let diff_output = String::from_utf8_lossy(output).replace("\t", "    ");

    // Split output lines, then for each line: (1) prepend the
    // vertical label char and (2) depending on leading +/- char
    // colorize the text fg and bg.

    let divider = " ".on_truecolor(0, 0, 0);

    let mut i = 0;
    for line in diff_output.lines() {
        let mut words_iter = line.split_ascii_whitespace();
        let (eline, escaped) = escape(line);

        let cline = if line.len() > 0 {
            if line.chars().nth(0).unwrap().is_ascii_whitespace() {
                format!(" {}", eline).normal()
            } else {
                match words_iter.next() {
                    Some("diff") => format!(" {}", eline)
                        .bold()
                        .truecolor(255, 255, 0)
                        .on_truecolor(85, 85, 51),
                    Some("index") => format!(" {}", eline)
                        .bold()
                        .truecolor(255, 255, 0)
                        .on_truecolor(85, 85, 51),
                    Some("---") => format!(" {}", eline)
                        .bold()
                        .truecolor(255, 255, 0)
                        .on_truecolor(85, 85, 51),
                    Some("+++") => format!(" {}", eline)
                        .bold()
                        .truecolor(255, 255, 0)
                        .on_truecolor(85, 85, 51),

                    // This is not identical to git-diff (the latter does
                    // not colorize the entire line), but this is close
                    // enough.
                    Some("@@") => format!(" {}", eline).cyan(),

                    // It could be that the word looks like "+foo" if "foo" is at the
                    // beginning of the eline. In this case we have to check for the
                    // first letter.
                    Some(w) => match &w[0..1] {
                        "+" => format!(" {}", eline)
                            .truecolor(204, 255, 204)
                            .on_truecolor(51, 85, 51)
                            .bold(),
                        "-" => format!(" {}", eline)
                            .truecolor(255, 204, 204)
                            .on_truecolor(85, 51, 51)
                            .bold(),
                        _ => format!(" {}", eline).normal(),
                    },

                    None => format!(" {}", eline).normal(),
                }
            }
        } else {
            "".normal()
        };

        // vlabel_part is surrounded with 3 spaces, for a total of 4 chars. We
        // also have to bump the width because each escaped character fools
        // println!() into thinking that the string is 1 char larger than it
        // really is.
        let rwidth = width - 4 + escaped;
        let vlabel_part = match &vlabel[i..i + 1] {
            " " => {
                if staged {
                    "   ".truecolor(255, 0, 255).on_truecolor(81, 51, 81)
                } else {
                    "   ".truecolor(0, 255, 255).on_truecolor(51, 81, 81)
                }
            }
            "-" => {
                if staged {
                    " \u{2503} ".truecolor(255, 0, 255).on_truecolor(81, 51, 81)
                } else {
                    " \u{2503} ".truecolor(0, 255, 255).on_truecolor(51, 81, 81)
                }
            }
            c => {
                if staged {
                    format!(" {} ", c)
                        .truecolor(255, 0, 255)
                        .on_truecolor(81, 51, 81)
                } else {
                    format!(" {} ", c)
                        .truecolor(0, 255, 255)
                        .on_truecolor(51, 81, 81)
                }
            }
        };
        println!("{}{}{:rwidth$}", vlabel_part, divider, cline);
        i = (i + 1) % vlabel.len();
    }
}

// Escapes a string to be fed into println!(). E.g., "foo\bar" becomes
// "foo\\bar".
//
// Adapted from
// https://github.com/njaard/sonnerie/blob/e6b82eed3d5ba53c2e667172985df9a967056b5d/escape_string/src/lib.rs#L166.
fn escape<'a>(text: &'a str) -> (Cow<'a, str>, usize) {
    let bytes = text.as_bytes();

    let mut owned = None;
    let mut escaped = 0;

    for pos in 0..bytes.len() {
        let special = match bytes[pos] {
            b'%' => Some(b'%'),
            b'\\' => Some(b'\\'),
            _ => None,
        };
        if let Some(s) = special {
            if owned.is_none() {
                owned = Some(bytes[0..pos].to_owned());
            }
            owned.as_mut().unwrap().push(s);
            owned.as_mut().unwrap().push(s);
            escaped = escaped + 1;
        } else if let Some(owned) = owned.as_mut() {
            owned.push(bytes[pos]);
        }
    }

    if let Some(owned) = owned {
        (
            unsafe { Cow::Owned(String::from_utf8_unchecked(owned)) },
            escaped,
        )
    } else {
        (
            unsafe { Cow::Borrowed(std::str::from_utf8_unchecked(bytes)) },
            escaped,
        )
    }
}

3.1 Build system

🎯 gd/Makefile
all:
	cargo install --profile release --path .
build:
	cargo build
test:
	cargo test
🎯 gd/Cargo.toml
[package]
name = "gd"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
clap = { version = "3.1.0", features = ["cargo"]}
colored = "2"
🎯 Cargo.toml
[workspace]
members = [
    "gd"
]

resolver = "2"

[profile.release]
# Strip all symbols.
strip = true
# Bring in other optimizations to reduce binary size.
debug = false
opt-level = 'z'
codegen-units = 1
lto = true
panic = 'abort'

4 tig

🎯 tig/.tigrc
# Appearance.
color cursor 16 green bold
color title-blur 16 blue bold
color title-focus 16 blue bold

set blame-view = date:relative-compact author:abbreviated,maxwidth=5 id:width=8,color line-number:yes,interval=1 text
set main-view  = date:relative-compact author:abbreviated,maxwidth=5 id:width=8 commit-title:yes,graph,refs
set tree-view  = date:relative-compact author:abbreviated,maxwidth=5 id:width=8 file-name
set refs-view  = date:relative-compact author:abbreviated,maxwidth=5 id:width=8 ref commit-title

set line-graphics = utf-8
set blame-options = -w

# Only show the top 500 commits.
set main-options = -n500

# Only show commits in the main view (don't show spurious, non-committed
# changes).
set show-changes = no

# Disable conflicting keybindings (otherwise tig complains).
bind generic <Ctrl-Y> none
bind generic J none
bind generic K none
bind generic <Ctrl-j> none
bind generic <Ctrl-k> none
# Disable unused bindings. Otherwise they clutter up the [help] view.
bind generic - none
bind generic <Ctrl-e> none
bind generic <Insert> none
bind generic <Delete> none
bind generic <Ctrl-c> none
bind generic s none

# Keybindings.
bind generic , none
bind generic h parent

bind generic <LessThan> none
bind generic l back

bind generic <Ctrl-n> none
bind generic <Ctrl-j> next

bind generic <Ctrl-p> none
bind generic <Ctrl-k> previous

bind generic <Ctrl-h> view-help
bind generic o view-log

# Copy 40-char hex string of commit.
bind generic y +bash -c "git rev-parse %(commit) \
  | head -c -1 \
  | ~/syscfg/script/copy-clipboard.sh"

bind:copy-commit-human-friendly

# Same as above, but as an Org-style link. <Esc>y means Alt+y (M-y in Emacs).
bind generic <Esc>y +bash -c "git rev-parse %(commit) \
  | head -c -1 \
  | ~/syscfg/script/git/ref-to-org-link.sh \
  | ~/syscfg/script/copy-clipboard.sh"

# Copy commit message.
bind generic <Ctrl-y> +bash -c "git cat-file commit %(commit) \
  | sed -e '1,/^$/d' \
  | ~/syscfg/script/copy-clipboard.sh"

# Force branch to point to current commit.
bind main    B ?+git branch -f "%(prompt Force branch to point here: )" %(commit)

bind generic R none
bind generic <F5> none
bind generic <Ctrl-r> refresh

bind main    R !git -c commit.verbose=true rebase -i %(commit)
bind generic <Backspace> move-page-up

4.1 Getting the commit info

Get human-friendly commit information, like

commit 55d4c735 ("explain the primary reason behind why we have CI", 2026-07-25)

This syntax is similar to what is supported in the Linux Kernel documentation for it to be automatically linked.

bind:copy-commit-human-friendly
bind generic Y +bash -c "git show %(commit) --no-patch --pretty='format:commit %C(auto)%h (\"%s\", %cd)' --date=short \
  | ~/syscfg/script/copy-clipboard.sh"

Page metrics

Tangled files (7)

  1. Cargo.toml
  2. gd/Cargo.toml
  3. gd/Makefile
  4. gd/src/main.rs
  5. git/cfg.personal.conf
  6. git/sendemail-aliases
  7. tig/.tigrc

Named cells (2)

  1. Makefile-git
  2. bind:copy-commit-human-friendly