Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
394d92e756 | ||
|
|
e6c70554f3 | ||
|
|
432fe58563 |
@@ -14,6 +14,8 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
# The same tool cache as in release.yaml: the same key and the same folders, or
|
||||||
|
# neither job can use what the other saved.
|
||||||
- name: Restore tool cache
|
- name: Restore tool cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
@@ -24,7 +26,10 @@ jobs:
|
|||||||
~/.rustup
|
~/.rustup
|
||||||
~/.local/bin/mise
|
~/.local/bin/mise
|
||||||
~/.local/share/mise
|
~/.local/share/mise
|
||||||
key: tools-check-${{ hashFiles('scripts/ci-setup.sh', 'mise.toml') }}
|
key: tools-${{ hashFiles('scripts/ci-setup.sh', 'mise.toml') }}
|
||||||
|
# After a change to mise.toml, start from the last tools; mise installs only what changed.
|
||||||
|
restore-keys: |
|
||||||
|
tools-
|
||||||
- name: Restore build cache
|
- name: Restore build cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ jobs:
|
|||||||
CARGO_BUILD_JOBS: "2"
|
CARGO_BUILD_JOBS: "2"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
# The same tool cache as in ci.yaml: the same key and the same folders, or
|
||||||
|
# neither job can use what the other saved.
|
||||||
- name: Restore tool cache
|
- name: Restore tool cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
# ~/.cache/cargo-xwin holds the Windows SDK files cargo-xwin downloads.
|
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/bin
|
~/.cargo/bin
|
||||||
~/.cargo/registry
|
~/.cargo/registry
|
||||||
@@ -35,8 +36,22 @@ jobs:
|
|||||||
~/.rustup
|
~/.rustup
|
||||||
~/.local/bin/mise
|
~/.local/bin/mise
|
||||||
~/.local/share/mise
|
~/.local/share/mise
|
||||||
|
key: tools-${{ hashFiles('scripts/ci-setup.sh', 'mise.toml') }}
|
||||||
|
# After a change to mise.toml, start from the last tools; mise installs only what changed.
|
||||||
|
restore-keys: |
|
||||||
|
tools-
|
||||||
|
# cargo-xwin, which takes minutes to compile, and the Windows SDK files it downloads.
|
||||||
|
# The Windows Rust target is left out: rustup lists its installed parts in a file in
|
||||||
|
# the tool cache, and refuses to install the target over files that list does not name.
|
||||||
|
- name: Restore cargo-xwin cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/bin/cargo-xwin
|
||||||
~/.cache/cargo-xwin
|
~/.cache/cargo-xwin
|
||||||
key: tools-release-${{ hashFiles('scripts/ci-setup.sh', 'mise.toml') }}
|
key: cargo-xwin-${{ hashFiles('scripts/ci-setup.sh', 'mise.toml') }}
|
||||||
|
restore-keys: |
|
||||||
|
cargo-xwin-
|
||||||
- name: Restore build cache
|
- name: Restore build cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="logo.svg" width="96" alt="">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1 align="center">gites</h1>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
A colorful viewer for the history of a git repository.<br>
|
||||||
|
Linux and Windows desktop app, driven from the keyboard.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://git.wrobel.it/szaman/gites/releases">Download</a> ·
|
||||||
|
<a href="#keys">Keys</a> ·
|
||||||
|
<a href="#build-from-source">Build from source</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
- **Draws the commit graph.** Every branch gets its own color. Labels on each commit show
|
||||||
|
local branches, remote branches and tags, and the checked-out commit is ringed.
|
||||||
|
- **Hides what you don't need.** Hide one branch with its eye button in the sidebar, or
|
||||||
|
with <kbd>h</kbd> on a commit. Type a pattern such as `prototypes/*` and choose
|
||||||
|
**hide** or **show only**. gites remembers the filters of each repository.
|
||||||
|
- **Folds long straight stretches.** Commits in a row that have no branch, tag, fork or
|
||||||
|
merge fold into one dotted line. <kbd>c</kbd> folds all of them, <kbd>space</kbd>
|
||||||
|
opens or closes the one at the selected commit.
|
||||||
|
- **Shows the selected commit** in a panel at the bottom: the full message, the author
|
||||||
|
and committer, the hash (click to copy), the parents (click to go there), and the
|
||||||
|
files it changed with the number of added and removed lines.
|
||||||
|
- **Shows what changed in a file.** Click a file in the panel, or press <kbd>Enter</kbd>
|
||||||
|
for the first one. Choose one of three layouts with <kbd>v</kbd>:
|
||||||
|
- **One column**, as `git diff` prints it.
|
||||||
|
- **Side by side**, the old file on the left and the new one on the right.
|
||||||
|
- **Inline**, one line per changed line, with removed words struck out and added words
|
||||||
|
marked. Best for prose, such as Markdown.
|
||||||
|
|
||||||
|
In every layout, the words that changed inside a line are marked.
|
||||||
|
- **Opens other repositories** from a list of recent ones, or from a folder picker
|
||||||
|
(<kbd>o</kbd>).
|
||||||
|
- **Stays current.** gites reloads the repository when its window gets focus again.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Download a package from the [releases page](https://git.wrobel.it/szaman/gites/releases):
|
||||||
|
|
||||||
|
| System | File |
|
||||||
|
|---|---|
|
||||||
|
| Debian, Ubuntu | `gites_<version>_amd64.deb` |
|
||||||
|
| Fedora, openSUSE | `gites-<version>-1.x86_64.rpm` |
|
||||||
|
| Any Linux | `gites_<version>_amd64.AppImage` |
|
||||||
|
| Windows, installer | `gites_<version>_x64-setup.exe` |
|
||||||
|
| Windows, no install | `gites_<version>_x64_portable.exe` |
|
||||||
|
|
||||||
|
gites runs the `git` command, so git must be installed and on your `PATH`.
|
||||||
|
|
||||||
|
## Use
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gites # the repository in the current folder
|
||||||
|
gites ~/code/my-project # another repository
|
||||||
|
```
|
||||||
|
|
||||||
|
## Keys
|
||||||
|
|
||||||
|
**In the commit graph**
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|---|---|
|
||||||
|
| <kbd>↑</kbd> <kbd>↓</kbd> or <kbd>k</kbd> <kbd>j</kbd> | Select the previous or next commit |
|
||||||
|
| <kbd>PgUp</kbd> <kbd>PgDn</kbd> | Move one screen up or down |
|
||||||
|
| <kbd>g</kbd> <kbd>G</kbd> or <kbd>Home</kbd> <kbd>End</kbd> | Go to the first or last commit |
|
||||||
|
| <kbd>Enter</kbd> | Show what changed in the first file of the commit |
|
||||||
|
| <kbd>space</kbd> | Fold or unfold the straight stretch at the selected commit |
|
||||||
|
| <kbd>c</kbd> | Fold or unfold all straight stretches |
|
||||||
|
| <kbd>h</kbd> | Hide the branch of the selected commit |
|
||||||
|
| <kbd>y</kbd> | Copy the short hash |
|
||||||
|
| <kbd>/</kbd> | Type a filter pattern |
|
||||||
|
| <kbd>p</kbd> | Show or hide the preview panel |
|
||||||
|
| <kbd>o</kbd> | Open another repository |
|
||||||
|
| <kbd>r</kbd> | Reload |
|
||||||
|
|
||||||
|
**In a file's diff**
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|---|---|
|
||||||
|
| <kbd>↑</kbd> <kbd>↓</kbd> or <kbd>k</kbd> <kbd>j</kbd> | Scroll by one line |
|
||||||
|
| <kbd>PgUp</kbd> <kbd>PgDn</kbd> | Scroll by one screen |
|
||||||
|
| <kbd>g</kbd> <kbd>G</kbd> or <kbd>Home</kbd> <kbd>End</kbd> | Go to the top or bottom |
|
||||||
|
| <kbd>n</kbd> <kbd>N</kbd> | Go to the next or previous change |
|
||||||
|
| <kbd>]</kbd> <kbd>[</kbd> | Show the next or previous file of the commit |
|
||||||
|
| <kbd>v</kbd> | Switch the layout: one column, side by side, inline |
|
||||||
|
| <kbd>Esc</kbd> | Go back to the commit graph |
|
||||||
|
|
||||||
|
## Where gites keeps its settings
|
||||||
|
|
||||||
|
The window layout, the diff layout and the recent repositories are kept in
|
||||||
|
`settings.json`, and the filters of each repository in `filters.json`. Both files are in
|
||||||
|
the `gites` folder of your data folder: `~/.local/share/gites` on Linux,
|
||||||
|
`%APPDATA%\gites` on Windows.
|
||||||
|
|
||||||
|
## Build from source
|
||||||
|
|
||||||
|
gites is a [Tauri](https://tauri.app) app: the window is Vue and TypeScript, and the part
|
||||||
|
that runs git is Rust. [mise](https://mise.jdx.dev) installs the right versions of Node,
|
||||||
|
Bun and Rust.
|
||||||
|
|
||||||
|
On Linux, Tauri also needs the WebKitGTK development packages. `scripts/ci-setup.sh`
|
||||||
|
lists them for Debian and Ubuntu.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mise install # Node, Bun and Rust
|
||||||
|
bun install # packages for the window code
|
||||||
|
|
||||||
|
mise run dev # run gites with live reload; add a path to open a repository
|
||||||
|
mise run test # unit tests for the window code and the Rust code
|
||||||
|
mise run check # type checks for both
|
||||||
|
mise run install # build a release binary and install it as ~/.local/bin/gites
|
||||||
|
```
|
||||||
|
|
||||||
|
Pushing a tag such as `v1.2.3` builds the Linux and Windows packages and publishes them
|
||||||
|
on the releases page.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 149 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 223 KiB |
+11
-6
@@ -32,12 +32,17 @@ pub struct RepoData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn git(dir: &Path, args: &[&str]) -> Result<String, String> {
|
pub fn git(dir: &Path, args: &[&str]) -> Result<String, String> {
|
||||||
let out = Command::new("git")
|
let mut cmd = Command::new("git");
|
||||||
.arg("-C")
|
cmd.arg("-C").arg(dir).args(args);
|
||||||
.arg(dir)
|
// gites has no console, so Windows would open a console window for every git it
|
||||||
.args(args)
|
// starts. Each one flashes on screen and takes the focus, and gites reloads on focus.
|
||||||
.output()
|
#[cfg(windows)]
|
||||||
.map_err(|e| format!("could not run git: {e}"))?;
|
{
|
||||||
|
use std::os::windows::process::CommandExt;
|
||||||
|
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
|
||||||
|
cmd.creation_flags(CREATE_NO_WINDOW);
|
||||||
|
}
|
||||||
|
let out = cmd.output().map_err(|e| format!("could not run git: {e}"))?;
|
||||||
if !out.status.success() {
|
if !out.status.success() {
|
||||||
return Err(String::from_utf8_lossy(&out.stderr).trim().to_string());
|
return Err(String::from_utf8_lossy(&out.stderr).trim().to_string());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,11 +105,18 @@ function startDrag(e: PointerEvent, axis: "x" | "y") {
|
|||||||
|
|
||||||
let filtersLoadedFor: string | null = null;
|
let filtersLoadedFor: string | null = null;
|
||||||
|
|
||||||
|
let loading = false;
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
|
// The window gets focus often; one reload at a time is enough.
|
||||||
|
if (loading) return;
|
||||||
|
loading = true;
|
||||||
try {
|
try {
|
||||||
await applyRepo(await invoke<RepoData>("load_repo"));
|
await applyRepo(await invoke<RepoData>("load_repo"));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error.value = String(e);
|
error.value = String(e);
|
||||||
|
} finally {
|
||||||
|
loading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user