# How bat Integrates with Git to Show File Modifications

> Learn how bat integrates with Git to visually display file modifications directly in your terminal. See added, removed, and changed lines with intuitive gutter symbols.

- Repository: [David Peter/bat](https://github.com/sharkdp/bat)
- Tags: how-to-guide
- Published: 2026-03-06

---

**bat uses the optional `git` feature to query repositories for file changes and decorates the gutter with symbols (`+`, `‾`, `_`, `~`) indicating added, removed-above, removed-below, and modified lines.**

The `bat` command-line tool by sharkdp/bat enhances standard file viewing with syntax highlighting and seamless Git integration. When you view files within a Git repository, bat automatically detects modifications and displays visual indicators in the gutter, making it easy to spot changes without running separate diff commands. This integration works through a four-stage pipeline that isolates Git logic in dedicated modules while keeping the feature optional via Cargo features.

## Stage 1: Detecting the Repository and Computing the Diff

The Git integration begins in [`src/diff.rs`](https://github.com/sharkdp/bat/blob/main/src/diff.rs), where the `get_git_diff` function discovers the nearest Git repository and calculates per-line changes. When `Controller::print_input` processes a file, it calls `get_git_diff` only if the `git` feature is enabled and the user requested diff information via `--diff` or by including the *changes* style component.

The function uses `Repository::discover` to find the repository root, then executes `repo.diff_index_to_workdir` with `DiffOptions` limited to the specific file. The resulting `git2::Diff` is walked to extract hunks, which are converted into `LineChange` variants (`Added`, `RemovedAbove`, `RemovedBelow`, `Modified`). These are stored in a `HashMap<u32, LineChange>` (aliased as `LineChanges`) mapping line numbers to their change status.

## Stage 2: Propagating Changes to the Printer

Once the diff is computed, `Controller::print_input` creates an `InteractivePrinter` instance and passes the `line_changes` data to `InteractivePrinter::new`. The printer stores this map in `self.line_changes`, making the Git modification data available during the rendering phase. This propagation occurs in [`src/controller.rs`](https://github.com/sharkdp/bat/blob/main/src/controller.rs) and ensures that the diff information travels from the repository detection layer to the output formatting layer without coupling the Git logic to the printing implementation.

## Stage 3: Configuring Gutter Decorations

During printer initialization in [`src/printer.rs`](https://github.com/sharkdp/bat/blob/main/src/printer.rs), the `InteractivePrinter` builds a list of gutter decorations. The `LineChangesDecoration::new` constructor is called only if the *changes* style component is enabled and the `line_changes` map contains at least one entry. This conditional setup ensures that the Git symbols only appear when relevant, avoiding unnecessary overhead for files without modifications or when the user disables the feature via `--style=plain`.

## Stage 4: Rendering the Modification Symbols

The actual symbol generation happens in [`src/decorations.rs`](https://github.com/sharkdp/bat/blob/main/src/decorations.rs) within `LineChangesDecoration::generate`. For each line processed by `InteractivePrinter::print_line`, the decoration looks up the current line number in `printer.line_changes`. If a `LineChange` exists, the function returns the corresponding cached symbol: `+` for added lines, `‾` for removed-above, `_` for removed-below, and `~` for modified lines. These symbols are painted using the colors defined in `Colors::git_added`, `Colors::git_removed`, and `Colors::git_modified`. If no change exists for the line, a blank space is printed instead.

## Using bat's Git Integration

The Git diff feature is enabled by default in official binaries. You can control it through command-line flags and style options.

To view a file with Git modification markers:

```bash
bat src/main.rs

```

If [`src/main.rs`](https://github.com/sharkdp/bat/blob/main/src/main.rs) has uncommitted changes, the gutter will display:

```

 1  │ fn main() {                # unchanged line

+2  │     println!("new line");  # added line

‾3  │                             # line that was removed above the current line

~4  │     // modified line      # modified line

```

To show only changed lines with context:

```bash
bat --diff src/main.rs

```

To disable Git decorations and show plain output:

```bash
bat --style=plain src/main.rs

```

When building from source, ensure the `git` feature is enabled:

```bash
cargo build --features git --release

```

## Key Source Files and Architecture

The Git integration is isolated in specific modules to maintain clean separation of concerns:

- **[`src/diff.rs`](https://github.com/sharkdp/bat/blob/main/src/diff.rs)** — Contains `get_git_diff` which uses `libgit2` via the `git2` crate to discover repositories and compute file-specific diffs, returning `LineChanges` (a `HashMap<u32, LineChange>`).

- **[`src/controller.rs`](https://github.com/sharkdp/bat/blob/main/src/controller.rs)** — Orchestrates the printing process. `Controller::print_input` calls `get_git_diff` conditionally and passes the resulting `line_changes` to `InteractivePrinter::new`.

- **[`src/printer.rs`](https://github.com/sharkdp/bat/blob/main/src/printer.rs)** — Implements `InteractivePrinter` which stores `line_changes` and conditionally initializes `LineChangesDecoration` when the *changes* style component is active.

- **[`src/decorations.rs`](https://github.com/sharkdp/bat/blob/main/src/decorations.rs)** — Defines `LineChangesDecoration` and its `generate` method, which maps `LineChange` variants to symbols (`+`, `‾`, `_`, `~`) and applies Git-specific colors.

This architecture keeps the optional Git dependency isolated behind the `git` Cargo feature, ensuring that users who do not need Git integration can build a lighter binary.

## Summary

- **bat integrates with Git** through an optional `git` feature that uses the `git2` crate to detect repositories and compute file-specific diffs.
- **Four-stage pipeline**: Repository detection and diff computation ([`src/diff.rs`](https://github.com/sharkdp/bat/blob/main/src/diff.rs)), propagation to printer ([`src/controller.rs`](https://github.com/sharkdp/bat/blob/main/src/controller.rs)), decoration configuration ([`src/printer.rs`](https://github.com/sharkdp/bat/blob/main/src/printer.rs)), and symbol rendering ([`src/decorations.rs`](https://github.com/sharkdp/bat/blob/main/src/decorations.rs)).
- **Visual indicators**: The gutter displays `+` for added lines, `‾` for removed-above, `_` for removed-below, and `~` for modified lines, colored according to Git status.
- **User control**: Enable with `--diff` or style components, disable with `--style=plain`, and compile with `cargo build --features git`.

## Frequently Asked Questions

### How do I enable Git integration when building bat from source?

When compiling bat from the sharkdp/bat repository, you must explicitly enable the `git` feature flag using Cargo. Run `cargo build --features git --release` to include the Git diff functionality. Official pre-built binaries already have this feature enabled by default.

### What do the symbols in the gutter mean when viewing a Git-tracked file?

The gutter symbols indicate line-level changes between the working directory and the Git index. A plus sign (`+`) marks added lines, a tilde (`~`) indicates modified lines, an overline (`‾`) shows that lines were removed above the current line, and an underscore (`_`) shows lines removed below. These symbols are defined in [`src/decorations.rs`](https://github.com/sharkdp/bat/blob/main/src/decorations.rs) within the `LineChangesDecoration::generate` method.

### Can I use bat's Git integration without the `git` feature enabled?

No, the Git integration requires the optional `git` feature to be enabled at compile time. Without this feature, `get_git_diff` in [`src/diff.rs`](https://github.com/sharkdp/bat/blob/main/src/diff.rs) is not available, and the `InteractivePrinter` will not receive line change data. You can verify if your binary supports Git by running `bat --list-features` or attempting to use the `--diff` flag.

### How does bat handle files that are not tracked by Git or repositories without modifications?

When a file has no Git modifications or is not inside a repository, `get_git_diff` returns `None` and the `LineChanges` map remains empty. In [`src/printer.rs`](https://github.com/sharkdp/bat/blob/main/src/printer.rs), the `LineChangesDecoration` is only added to the decoration list when the map contains entries. Consequently, the gutter displays only line numbers (or blank spaces) without modification symbols, ensuring clean output for unchanged files.