Libra is a partial implementation of a Git client, developed using Rust. Our goal is not to create a 100% replica of Git (for those interested in such a project, please refer to the gitoxide). Instead, libra focus on implementing the basic functionalities of Git for learning Git and Rust. A key feature of libra is the replacement of the original Git internal storage architecture with SQLite.
$ libra --help
Simulates git commands
Usage: libra <COMMAND>
Commands:
init Initialize a new repository
clone Clone a repository into a new directory
add Add file contents to the index
rm Remove files from the working tree and from the index
restore Restore working tree files
status Show the working tree status
log Show commit logs
diff Show changes between commits, commit and working tree, etc
branch List, create, or delete branches
commit Record changes to the repository
switch Switch branches
merge Merge changes
push Update remote refs along with associated objects
fetch Download objects and refs from another repository
pull Fetch from and integrate with another repository or a local branch
remote Manage set of tracked repositories
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
Our code is designed to be clean and easy to read, ensuring that it is both maintainable and understandable for developers of all skill levels.
- Windows
- Linux
- MacOS
Our implementation is essentially fully compatible with Git
(developed with reference to the Git documentation),
including formats such as objects, index, pack, and pack-index.
Therefore, it can interact seamlessly with Git servers (like push and pull).
While maintaining compatibility with Git, we have made some innovations and changes:
we use an SQLite database to manage loosely structured files such as config, HEAD, and refs,
achieving unified management.
This section documents the compatibility between Libra’s CLI and Git at the level of commands and options, and serves as a roadmap for closing gaps.
- Status
- âś… Implemented and broadly compatible with Git semantics
⚠️ Implemented but behavior may differ from Git, or Libra-specific extension (Git has no direct equivalent)- ⛔ Not implemented yet
- Priority (for â›” items)
- P0 – High priority: very common in everyday Git workflows, or important for safety
- P1 – Medium priority: advanced workflows or scripting/tooling heavy usage
- P2 – Low priority: niche or rarely used options
Note: The tables below are based on the existing command/flag checklist in this README plus common Git options. If in doubt about exact semantic equality, we err on the conservative side and mark as
⚠️ .
| Command | Option / Form | Git | Libra | Status | Priority (for â›”) | Notes |
|---|---|---|---|---|---|---|
init |
<repo_directory> |
Yes | Yes | âś… | - | Basic repository directory |
--bare |
Yes | Yes | âś… | - | Initialize bare repository | |
--template <path> |
Yes | Yes | âś… | - | Use template directory | |
-b, --initial-branch <name> |
Yes | Yes | âś… | - | Set initial branch name | |
-q, --quiet |
Yes | Yes | âś… | - | Suppress output | |
--shared <perm> |
Yes | Yes | P1 | Supported, but effective semantics may differ from Git in edge cases | ||
--separate-git-dir <dir> |
Yes | No | â›” | P1 | Separate .git directory; useful for advanced layouts |
|
--object-format <alg> |
Yes | No | ⛔ | P0 | Important for SHA‑1/SHA‑256 migration/compatibility | |
clone |
<remote_repo> |
Yes | Yes | âś… | - | Repository URL/path |
[local_path] |
Yes | Yes | âś… | - | Target directory | |
-b, --branch <name> |
Yes | Yes | âś… | - | Check out given branch | |
--depth <n> |
Yes | No | â›” | P0 | Shallow clone, widely used in CI and large repos | |
--single-branch |
Yes | No | â›” | P0 | Clone only the specified branch | |
--recurse-submodules |
Yes | No | ⛔ | P1 | Requires submodule support; important in mono‑repos | |
--bare |
Yes | No | ⛔ | P0 | Bare clone for server‑side usage | |
--mirror |
Yes | No | â›” | P1 | Full mirror including refs, for replication scenarios |
| Command | Option / Form | Git | Libra | Status | Priority (for â›”) | Notes |
|---|---|---|---|---|---|---|
add |
<pathspec...> |
Yes | Yes | âś… | - | Add files matching pathspec |
-A, --all |
Yes | Yes | âś… | - | Add all changes (tracked + untracked) | |
-u, --update |
Yes | Yes | âś… | - | Add only tracked changes | |
--refresh |
Yes | Yes | âś… | - | Refresh the index stat info | |
-v, --verbose |
Yes | Yes | âś… | - | Verbose output | |
-n, --dry-run |
Yes | Yes | âś… | - | Show what would be added | |
--ignore-errors |
Yes | Yes | âś… | - | Continue even if some paths fail | |
-f, --force |
Yes | Yes | âś… | - | Add ignored files | |
-p, --patch |
Yes | No | â›” | P0 | Interactive hunk selection; core to many workflows | |
-i, --interactive |
Yes | No | â›” | P0 | Interactive mode (git add -i) |
|
-N, --intent-to-add |
Yes | No | ⛔ | P1 | Mark paths as “to be added” later | |
--chmod=(+x|-x) |
Yes | No | â›” | P1 | Toggle executable bit | |
--renormalize |
Yes | No | ⛔ | P2 | Re‑normalize line endings / attributes | |
rm |
<pathspec...> |
Yes | Yes | âś… | - | Remove files |
--cached |
Yes | Yes | âś… | - | Remove only from index | |
-r, --recursive |
Yes | Yes | âś… | - | Recurse into directories | |
-f, --force |
Yes | Yes | âś… | - | Force removal | |
--dry-run |
Yes | Yes | âś… | - | Show what would be removed | |
--ignore-unmatch |
Yes | No | ⛔ | P0 | Don’t error if paths don’t match; important for scripts | |
--pathspec-from-file <file> |
Yes | No | â›” | P1 | Read pathspecs from file | |
--pathspec-file-nul |
Yes | No | ⛔ | P1 | NUL‑separated pathspec file | |
restore |
<pathspec...> |
Yes | Yes | âś… | - | Restore paths |
-s, --source <commit> |
Yes | Yes | âś… | - | Restore from specific commit | |
-W, --worktree |
Yes | Yes | âś… | - | Restore working tree only | |
-S, --staged |
Yes | Yes | âś… | - | Restore index (staged) state | |
status |
--porcelain |
Yes | Yes | ✅ | - | Machine‑readable output |
-s, --short |
Yes | Yes | âś… | - | Short format | |
--branch |
Yes | Yes | âś… | - | Show branch info | |
--ignored |
Yes | Yes | âś… | - | Show ignored files | |
--untracked-files[=no|normal|all] |
Yes | No | â›” | P0 | Control visibility of untracked files | |
--show-stash |
No | Yes | P1 | Libra extension; only in standard mode |
| Command | Option / Form | Git | Libra | Status | Priority (for â›”) | Notes |
|---|---|---|---|---|---|---|
commit |
-m, --message <msg> |
Yes | Yes | âś… | - | Commit message |
-F, --file <path> |
Yes | Yes | âś… | - | Read message from file | |
--allow-empty |
Yes | Yes | âś… | - | Allow empty commit | |
--conventional |
No | Yes | P1 | Libra extension for conventional commits | ||
--amend |
Yes | Yes | âś… | - | Amend previous commit | |
-s, --signoff |
Yes | Yes | âś… | - | Add Signed-off-by | |
--disable-pre |
Approx. --no-verify |
Yes | P0 | Behavior should be aligned with Git hook semantics as much as possible | ||
-a, --all |
Yes | Yes | ✅ | - | Auto‑stage tracked changes | |
-p, --patch |
Yes | No | ⛔ | P1 | Patch‑mode commit (often paired with add -p) |
|
--no-verify |
Yes | No | â›” | P0 | Standard way to skip hooks; should coexist with or alias --disable-pre |
|
--no-edit |
Yes | No | â›” | P1 | Reuse previous message | |
--author <name> |
Yes | No | â›” | P0 | Override author identity | |
--date <when> |
Yes | No | â›” | P0 | Override author date | |
-S, --gpg-sign / --no-gpg-sign |
Yes | No | â›” | P1 | GPG signing support | |
log |
-n, --number <n> |
Yes | Yes | âś… | - | Limit number of commits |
--oneline |
Yes | Yes | ✅ | - | One‑line output | |
-p, --patch |
Yes | Yes | âś… | - | Show patch | |
--decorate / --no-decorate |
Yes | Yes | âś… | - | Show/hide ref decorations | |
[pathspec] |
Yes | Yes | âś… | - | Restrict to paths | |
--graph |
Yes | Yes | âś… | - | ASCII commit graph | |
--pretty=<format> |
Yes | No | â›” | P0 | Customizable formatting; heavily used in tooling | |
--abbrev-commit |
Yes | No | â›” | P1 | Shorten commit IDs | |
--name-only / --name-status |
Yes | No | â›” | P0 | Show changed files, with or without status | |
--stat |
Yes | Yes | âś… | - | Diffstat summary | |
--since <date> / --until <date> |
Yes | No | ⛔ | P0 | Time‑based filtering | |
--author <pattern> |
Yes | No | ⛔ | P0 | Author‑based filtering | |
tag |
<name> |
Yes | Yes | âś… | - | Lightweight tag |
-l, --list [pattern] |
Yes | Yes | âś… | - | List tags | |
-d, --delete <name> |
Yes | Yes | âś… | - | Delete tags | |
-m, --message <msg> |
Yes | Yes | âś… | - | Annotated tag message | |
-f, --force |
Yes | Yes | ✅ | - | Force re‑tag | |
-a |
Yes | No | â›” | P0 | Explicit annotated tag | |
-s, --sign |
Yes | No | ⛔ | P1 | GPG‑signed tags | |
-u <keyid> |
Yes | No | â›” | P1 | Select signing key | |
-n <n> |
Yes | No | â›” | P2 | Show annotation lines | |
-v, --verify |
Yes | No | â›” | P1 | Verify tag signatures | |
show |
(basic usage) | Yes | Yes | P1 | Core behavior implemented; detailed flag parity needs further audit | |
reflog |
show [--pretty=<fmt>] |
Yes | Yes | P1 | Supported; --pretty formatting parity may not be full Git parity |
|
delete <selectors...> |
Yes | Yes | âś… | - | Delete reflog entries | |
exists <ref> |
Yes | Yes | âś… | - | Check reflog presence | |
expire [--expire=<time>] |
Yes | No | â›” | P1 | Cleanup policy for reflogs |
| Command | Option / Form | Git | Libra | Status | Priority (for â›”) | Notes |
|---|---|---|---|---|---|---|
branch |
<new_branch> [commit_hash] |
Yes | Yes | âś… | - | Create branch from commit or HEAD |
-D, --delete <branch> |
Yes | Yes | âś… | - | Force delete branch | |
-d, --delete <branch> |
Yes | No | â›” | P1 | Safe delete (refuse if unmerged) | |
-u, --set-upstream-to <upstream> |
Yes | Yes | âś… | - | Set upstream tracking branch | |
--show-current |
Yes | Yes | âś… | - | Show current branch | |
-m, --move [OLD] [NEW] |
Yes | Yes | âś… | - | Rename branches | |
-r, --remotes |
Yes | Yes | âś… | - | List remote branches | |
-a, --all |
Yes | Yes | âś… | - | List all branches | |
--contains <commit> |
Yes | No | â›” | P1 | Useful for branch cleanup and queries | |
--merged / --no-merged |
Yes | No | â›” | P1 | Check merge status into current HEAD | |
switch |
<branch> |
Yes | Yes | âś… | - | Switch to branch |
-c, --create <new_branch> |
Yes | Yes | âś… | - | Create and switch | |
-d, --detach |
Yes | Yes | âś… | - | Detach HEAD | |
-C, --force-create <branch> |
Yes | No | ⛔ | P1 | Force re‑create branch | |
--guess / --no-guess |
Yes | No | â›” | P2 | Heuristic branch name guessing | |
--track |
Yes | No | â›” | P0 | Auto set upstream when switching to remote branch | |
--merge |
Yes | No | â›” | P2 | Merge mode on switch | |
--conflict=<style> |
Yes | No | â›” | P2 | Conflict marker style | |
checkout |
<branch> |
Yes | Yes | âś… | - | Checkout existing branch |
-b <new_branch> [start-point] |
Yes | Yes | âś… | - | Create and checkout branch | |
-B <new_branch> [start-point] |
Yes | No | ⛔ | P1 | Force re‑create branch at start‑point | |
--detach |
Yes | No | â›” | P1 | Detach HEAD at given ref | |
-f, --force |
Yes | No | â›” | P1 | Discard local changes when switching |
| Command | Option / Form | Git | Libra | Status | Priority (for â›”) | Notes |
|---|---|---|---|---|---|---|
merge |
<branch> |
Yes | Yes | âś… | - | Basic merge of given branch |
--no-ff / --ff-only |
Yes | No | ⛔ | P0 | Control merge topology (no‑ff, fast‑forward only) | |
--squash |
Yes | No | â›” | P0 | Squash merges into a single commit | |
--commit / --no-commit |
Yes | No | ⛔ | P1 | Whether to auto‑commit after merge | |
-m, --message <msg> |
Yes | No | â›” | P1 | Specify merge commit message | |
--strategy <name> |
Yes | No | â›” | P1 | Select merge strategy (e.g. ort, recursive) |
|
--strategy-option <opt> |
Yes | No | ⛔ | P2 | Fine‑tune chosen strategy | |
rebase |
<upstream> |
Yes | Yes | âś… | - | Basic rebase onto upstream |
-i, --interactive |
Yes | No | â›” | P1 | Interactive rebase (edit/reorder/squash) | |
--onto <newbase> |
Yes | No | â›” | P1 | Rebase onto different base | |
--autostash |
Yes | No | â›” | P1 | Stash/unstash automatically around rebase | |
--continue / --abort / --skip |
Yes | No | â›” | P0 | Essential state machine for resolving rebase conflicts | |
cherry-pick |
<commits...> |
Yes | Yes | âś… | - | Apply one or more commits |
-n, --no-commit |
Yes | Yes | ✅ | - | Don’t create commit automatically | |
-x |
Yes | No | ⛔ | P1 | Append “(cherry picked from …)” | |
-e, --edit |
Yes | No | â›” | P1 | Edit commit message | |
-m, --mainline <parent> |
Yes | No | â›” | P1 | Specify parent for merge commits | |
--continue / --abort / --quit |
Yes | No | â›” | P0 | Workflow control after conflicts | |
revert |
<commit> |
Yes | Yes | âś… | - | Revert single commit |
-n, --no-commit |
Yes | Yes | ✅ | - | Don’t auto‑commit | |
--edit / --no-edit |
Yes | No | â›” | P1 | Edit or reuse default message | |
-m, --mainline <parent> |
Yes | No | â›” | P1 | Revert merge commits | |
--continue / --abort / --quit |
Yes | No | ⛔ | P0 | Multi‑commit revert / conflict handling |
| Command | Option / Form | Git / Git LFS | Libra | Status | Priority (for â›”) | Notes |
|---|---|---|---|---|---|---|
remote |
add <name> <url> |
Yes | Yes | âś… | - | Add remote |
remove <name> (Git: rm) |
Yes | Yes | âś… | - | Remove remote | |
rename <old> <new> |
Yes | Yes | âś… | - | Rename remote | |
-v (list with URLs) |
Yes | Yes | âś… | - | List remotes verbosely | |
show |
Yes | Yes | âś… | - | Show remote details | |
get-url <name> [--push|--all] |
Yes | Yes | âś… | - | Print configured URLs | |
set-url <name> <newurl> [--add] [--delete] [--push] [--all] |
Yes | Partial | â›” | P1 | Advanced URL management; basic set-url support is P0 |
|
prune <name> |
Yes | No | â›” | P1 | Prune stale remote-tracking refs | |
update [<group>|<remotes>...] |
Yes | No | â›” | P2 | Batch remote updates | |
push |
<repository> <refspec> |
Yes | Yes | âś… | - | Basic push |
-u, --set-upstream |
Yes | Yes | âś… | - | Set upstream on push | |
--force |
Yes | No | â›” | P0 | Force push (use carefully) | |
--force-with-lease |
Yes | No | â›” | P0 | Safer force push; strongly recommended over bare --force |
|
--tags / --all |
Yes | No | â›” | P1 | Push all tags / all branches | |
--delete |
Yes | No | â›” | P1 | Delete remote ref | |
--dry-run |
Yes | No | â›” | P2 | Simulate push | |
fetch |
[<repository>] [<refspec>] |
Yes | Yes | âś… | - | Basic fetch |
-a, --all |
Yes | Yes | âś… | - | Fetch from all remotes | |
--tags |
Yes | No | â›” | P1 | Fetch all tags | |
--prune |
Yes | No | â›” | P0 | Prune removed remote branches | |
--force |
Yes | No | â›” | P1 | Force update of local refs | |
--depth <n> / --shallow-exclude <ref> |
Yes | No | â›” | P0 | Shallow fetch; crucial for large repos | |
--multiple |
Yes | No | â›” | P2 | Fetch from multiple remotes | |
pull |
<repository> <refspec> |
Yes | Yes | âś… | - | Fetch and integrate |
--rebase |
Yes | No | â›” | P0 | pull --rebase workflow |
|
--ff-only / --no-ff |
Yes | No | â›” | P0 | Control merge mode on pull | |
lfs |
track / untrack |
Yes (Git LFS) | Yes | âś… | - | LFS tracking configuration |
locks / lock / unlock |
Yes | Yes | âś… | - | LFS locking | |
install / uninstall |
Yes | No | â›” | P1 | Install LFS filters/hooks | |
fetch / pull / push |
Yes | No | â›” | P0 | Transfer LFS objects with remotes | |
ls-files |
Yes | No | ⛔ | P1 | List LFS‑tracked files | |
env / version |
Yes | No | â›” | P2 | Diagnostic info |
| Command | Option / Form | Git | Libra | Status | Priority (for â›”) | Notes |
|---|---|---|---|---|---|---|
config |
--add <name> <value> |
Yes | Yes | âś… | - | Add config entry |
--get <name> |
Yes | Yes | âś… | - | Get single value | |
--get-all <name> |
Yes | Yes | âś… | - | Get all values | |
--unset <name> |
Yes | Yes | âś… | - | Remove entry | |
--unset-all <name> |
Yes | Yes | âś… | - | Remove all entries | |
-l, --list |
Yes | Yes | âś… | - | List config | |
--name-only |
Yes | Yes | âś… | - | Show names only | |
-d, --default <value> |
Yes | Yes | âś… | - | Default value if missing | |
--global / --system / --local |
Yes | No | â›” | P0 | Select config scope (system/global/repo) | |
--file <path> |
Yes | No | â›” | P1 | Use explicit config file | |
--replace-all |
Yes | No | â›” | P1 | Replace all matching entries | |
--type=<bool|int|path> |
Yes | No | â›” | P2 | Typed config parsing | |
index-pack |
<pack_file> |
Yes | Yes | âś… | - | Operate on given pack file |
-o <index_file> |
Yes | Yes | âś… | - | Output index file path | |
--index-version <n> |
Yes | Yes | âś… | - | Index format version | |
--stdin |
Yes | No | â›” | P2 | Read pack from stdin | |
--fix-thin |
Yes | No | â›” | P2 | Fix thin packs | |
--verify |
Yes | No | â›” | P1 | Validate pack/index correctness |
This section is intended to be kept up to date as new flags and commands are implemented. When implementing a new option:
- Mark the README checklist for that command as
[x]. - Update the corresponding row here:
- Change Libra to “Yes”.
- Update Status from â›” to âś… or
⚠️ as appropriate. - Clear or adjust the Priority field.
Refs to Development