Skip to content

About

git-ignore

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

17 Commits

Folders and files

Repository files navigation

git-ignore

This is a personal technical study and a small utility I built to explore what's possible with high performance systems programming in Rust using native ecosystem library in Rust. It specifically looks at how to use redb for storing data and gix (gitoxide) for handlin ag Git repositories without the usual overhead.

Warning

This is a pet project of mine. I'm using it to learn and experiment with optimizations, so it's definitely not meant for production use or anything mission critical so please use it at your own risk!

Why build this?

I wanted to see how far I could push the performance of a simple CLI task fetching and managing .gitignore files. Usually, tools like this either call the git command directly or walk through thousands of files on your disk. I wanted to see if I could do better by going deeper into how these libraries work especially native Rust library like gix. I found out that gix already efficient enough for read path by doing everything using mmap I guess and it also do parallelization using rayon in some parts.

I'm using redb as simple key value db also experimenting whether for simple use case it's stable enough or not. I'm storing the template string directly into redb keyed by its lowercase namespaced template name (ex: ${namespace}/${gitignore-template-name/language}). I'm using multiple redb table in here just to keep it simple :').

  • templates : the key is lowercase namespaced template name and value is the template content.

  • template_oids: the key is same as above but the content is oid of the git file commit. This is being used for checking whether there is an update or not when traversing the git diff walks for that template.

  • metadata : the key is last_commit_hash:${source_name} and the value is worktree head oid. This is to check whether our pinned worktree is changed or not (whether the remote head points to new oid or not). if yes then we traverse walk the diff of the git from current oid to remote oid.

Assumptions

I made a few assumptions about what makes a CLI tool fast on Linux, and then I tested them:

  1. Reduce number of syscalls: I assume that reducing syscall is quite important here because of cli tool like this are heavily dealing with rapid teardown during each cli invocations. Having an efficient program that do less syscall seems to be good number i guess.
  2. Static Linking: I built the tool with musl so it's a completely standalone file. It's a bit larger, but it doesn't have to look for libraries on your system when it starts up.
  3. Memory Mapping: I relied on the OS to handle the heavy lifting of reading the database file into memory, which seems a lot more efficient for this kind of work.

What I measured (on my machine)

Warning

This might be a bit outdated :')

These are the results I got using strace -c on my own Linux setup. Your results might be different, but they give a good idea of the footprint:

Task Command Syscall Count Notes
Check Version git-ignore -v 89 Mostly just starting the process.
List Everything git-ignore -l 96 Quick look at the index.
Get a Template git-ignore Rust 111 Reading directly from memory.
Update a File git-ignore -p Node 121 Parsing and merging blocks.

NOTE: A simple "Hello World" in some languages can take over 300 syscalls just to say hello!

Main Features

  • Template Registry: You can pull templates from multiple places at once like the standard GitHub ones plus your own personal repository.
  • Template Diff Mechanism: I built very simple and stupid diff/patch logic that uses git-ignore-start/end markers in your .gitignore. It "blindly" do simple diff on which parts it "owns" so it can update them without messing up your own custom rules. I might revise this later on in the future.
  • Template Change Tracker Mechanism: It only downloads from upstream what has actually changed since the last time you ran it.

How to play with it

What you need

  • Rust (I recommend Nightly for the ultimate static builds)
  • just (for running the build commands)

Just the basics

cargo build --release
just release-static

TODO

  • use usage-rs replacing argh so that I don't need to always update shell completion manually (urgh).
  • Replace the FST using simple rkyv artifact instead since we don't really use FST at runtime for search right now, we just use it for storage :')).
  • Refactor the code a bit, the initial version are not so good but at least it works :')).
  • Simplify some of the logic :')).

License

MIT - Copyright (c) 2026 zerosign

About

git-ignore

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages