git-issue 🗂️
A Git-native, file-backed issue tracker.
Issues live alongside your code inside .gitissues/, making them platform-independent, version-controlled, branchable, mergeable, reviewable and offline-friendly.
1.) Features
- ✅ Git-native, file-backed issues under
.gitissues/ - ✅ Core commands:
init,new,list,show,set,edit,link - ✅ Each issue has a markdown description incl. attachments
- ✅ Each issue has metadata:
id,title,state,type,labels,reporter,assignee,priority,due_date,created,updated - ✅ Each issue has
relationships: Desired relationship categories (e.g, related, child/parent, ...) are configurable and bidirectional links can be managed automatically - ✅ Issues can be filtered and sorted
- ✅ Highly configurable: default columns for
list, available options forstateandtype, relation ship categories, commit message template, external editor - ✅ External editor renders issue information as markdown
- ✅ Git-integration: auto-commit of changes
- ✅ Possibility to export issue list into CSV file
- ✅ Automated integration tests
- 🚧 Add
searchcommand across all issue titles and descriptions - 🚧 Comments / discussions
2.) Usage
2.1) Installation
Different installation approaches are explained here.
2.1.1) GitHub Release
Download the latest release from GitHub and put the binary on your PATH.
- Go to the Releases page and download the binary for your platform:
git-issue-linux-x86_64git-issue-macos-x86_64orgit-issue-macos-aarch64git-issue-windows-x86_64.exe
- Rename to the canonical name and place on your PATH
- Linux/macOS:
- Windows: rename
git-issue-windows-x86_64.exetogit-issue.exeand move it to a directory on your PATH.
- Linux/macOS:
- Verify:
2.1.2) Cargo
Installation with cargo works as follows:
cargo install --git https://github.com/timonburkard/git-issue
2.1.3) Crates
Package is available on https://crates.io/crates/git-issue, so it can be installed as follows:
cargo install git-issue
2.2) How To
Lets image this is the structure of your git repo, for which you want to add issue tracking:
.git/
src/
README.md
.gitignore
In the root of your repo, run:
This will automatically create the .gitissues/ directory in your git repo:
.git/
.gitissues/
src/
README.md
.gitignore
For infos about the .gitissues/ directory structure, see chapter 4.) Storage Layout.
2.3) Gitignore
This is the suggested content for the .gitignore:
.gitissues/.tmp/
.gitissues/exports/
.gitissues/settings.yaml
2.3) Commands
# Help page
# Version
# Initialize tracking in your repo
# Create a new issue
# List issues
# Show all issue information (markdown) -- launches external text editor
# Change issue meta fields
# Change issue meta fields: labels
# Change issue relationships
# Edit issue description (markdown) -- launches external text editor
2.4) Example
Dummy example project to see how git-issue is used in a repo: Example Project
3.) Configuration
After running git issue init, the following default files are automatically created:
.gitissues/config.yaml: Project configuration file (should be version-controlled).gitissues/settings.yaml: Local user settings file (should not be version-controlled).gitissues/users.yaml: Users (should be version-controlled).gitissues/description.md: Issue description template (should be version-controlled)
These files can be edited by the user.
3.1) config.yaml
This file holds the project configuration. It should be version-controlled.
# Automatically create a git commit after mutating commands
commit_auto: true
# Commit message template
# Available placeholders: {action}, {id}, {title}
commit_message: "[issue] {action} #{id} -- {title}"
# Default columns to display in `issue list`
# ["*"] can be used to include all available columns
list_columns:
- id
- state
- assignee
- title
# Available issue states
# First state in the list is the initial state for new issues
states:
- new
- active
- closed
- deleted
# Available issue types
# Per default the type is empty for new issues
types:
- bug
- feature
- task
# Available relationships between issues
# link: specifies the name of the reciprocal relationship
# - same name: bidirectional, symmetric
# - different name: bidirectional, asymmetric
# - null: unidirectional
relationships:
related:
link: related
parent:
link: child
child:
link: parent
# Separator used when exporting to CSV
export_csv_separator: ','
3.1.1) Options
commit_auto(boolean): Iftrue, automatically commit changes to.gitissues/. Default:truecommit_message(string): Template for git commit messages. Supports placeholders:{id}: Issue ID{title}: Issue title{action}: Command that triggered the commit (new,edit description,set <field>)
list_columns(list of strings): Default columns shown inlistcommandstates(list of strings): Available issue states. Default is the first element.types(list of strings): Available issue types. Default is empty.relationships(object): Available relationships between issuesexport_csv_separator(char): Separator for CSV file exports
3.2) users.yaml
This file holds the available users in the project. It should be version-controlled.
users:
- id: alice
- id: bob
- id: carol
3.3) settings.yaml
This file holds the local user settings. It should not be version-controlled.
# Editor to edit/show issue descriptions
# git = use the git-configured editor
editor: git
# User name
# Used as default reporter for new issues
user: alice
3.3.1) Options
editor(string): External text editor (setgitto use configured git core.editor)user(string): User name, used per default as reporter for new issues (can be '')
3.4) description.md
This file holds the template for the issue descriptions. It is use when a new issue is created with git issue new.
4.) Storage Layout
This is the directory structure of .gitissues/:
.gitissues/
├── .tmp/ # Temporary files (put in `.gitignore`)
├── config.yaml # Project configuration
├── description.md # Description template
├── users.yaml # Available users
├── settings.yaml # Local user settings (put in `.gitignore`)
├── exports/ # Location of CSV exports (put in `.gitignore`)
└── issues/
└── 0000000001/
├── meta.yaml # Structured metadata
├── description.md # Markdown description
└── attachments/ # Attachments of markdown description
├── 0000000002/
├── meta.yaml # Structured metadata
├── description.md # Markdown description
└── attachments/ # Attachments of markdown description
└── ...
4.1) meta.yaml Format
id: 1234 # (Integer) Identifier
title: Login screen is broken # (String) Title
state: new # (String) E.g.: new, active, resolved, junked
type: bug # (String) E.g.: feature, bug, task
labels: # (List of Strings) Labels / tags
- software
- ui
reporter: t.burkard # (String) Who reported the issue
assignee: j.doe # (String) To whom the issue is assigned
priority: P2 # (Enum) Priority: P0 = highest, P2 = default, P4 = lowest
due_date: # (Date) Due date in ISO format: YYYY-MM-DD
relationships: # (Object) Relationships with other issues
related:
- 5678
- 7777
parent:
- 5555
child:
- 3333
- 4444
created: # (Timestamp) Issue was created at
updated: # (Timestamp) Issue was last updated at
Don't edit these files manually. Instead use the git issue set and git issue link commands.
5.) Development
5.1) Building & Testing
# Build
# Format code
# Lint
# Run tests
5.2) Architecture
config/config-default.yaml-- Default configuration, copy-pasted atgit issue initto.gitissues/description-default.md-- Default description template, copy-pasted atgit issue initto.gitissues/users-default.yaml-- Default users, copy-pasted atgit issue initto.gitissues/settings-default.yaml-- Default local user settings, copy-pasted atgit issue initto.gitissues/
src/main.rs-- CLI parsing with clapmodel.rs-- Shared data types, functions and utilitiesedit.rs-- Edit issue description (markdown) with external text editorinit.rs-- Initialize.gitissues/directory and copy default configlink.rs-- Change relationships between issueslist.rs-- List all issuesnew.rs-- Create new issuesset.rs-- Change issue meta fieldsshow.rs-- Show all issue information
tests/-- Automated tests
5.3) Dependencies
clap-- CLI argument parsingchrono-- Timestamp generationserde-- Serialization frameworkserde_yaml-- YAML parsing for meta.yaml filesshell-words-- Process command line according to parsing rules of Unix shellregex-- Regular expressionsindexmap-- Provides IndexMap datatype