Compare commits

...
112 Commits
Author SHA1 Message Date
Stefan Haller 2f6d20275a Update docs and schema for release (#5353) 2026-03-09 20:49:23 +01:00
Stefan Haller f63f82bd4d Update docs and schema for release 2026-03-09 19:53:24 +01:00
Stefan Haller 487df128e2 Update translations from Crowdin (#5352) 2026-03-09 19:52:33 +01:00
Stefan Haller 327c76ffbb Update translations from Crowdin 2026-03-09 19:49:46 +01:00
Stefan Haller 43fa7a499e Fix diff display of custom pagers after screen mode change (#5349)
We need to re-render the main view after a screen mode change, in case a
custom pager is being used and its output depends on the window width.
2026-03-09 19:44:37 +01:00
Stefan Haller 5b23f80398 Re-render main view when changing screen mode
This is needed for diffs in case a custom pager is used and its output depends
on the window width (e.g. the horizontal lines in delta).
2026-03-09 19:42:28 +01:00
Stefan Haller 46c53ea34f Cleanup: use CurrentSide() instead of private currentSidePanel
They both do the same.
2026-03-09 19:42:28 +01:00
Stefan Haller b05e33df89 Show worktree name next to branch in branches list (#5340)
### PR Description

When a branch is checked out by another worktree, show the worktree name
in the label, e.g. "(worktree cosmos2)" instead of just "(worktree)", so
you can immediately see which worktree holds it.
2026-03-09 11:58:28 +01:00
Ruud Kamphuis 6ad56d5852 Show worktree name next to branch in branches list
When a branch is checked out by another worktree, show the worktree
name in the label, e.g. "(worktree cosmos2)" instead of just
"(worktree)", so you can immediately see which worktree holds it.
2026-03-09 11:34:34 +01:00
Stefan Haller 4c7323b255 README.md: Update Sponsors (#5228)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2026-03-08 17:56:24 +01:00
github-actions[bot] bce1ca58bd README.md: Update Sponsors 2026-03-08 16:53:40 +00:00
Stefan Haller 7ec8c9c0d1 Enable { and } to change diff context size in branches and tags panels in diffing mode (#5258)
When looking at a diff in diffing mode in the branches or tags panels
(e.g. after pressing `W` on a branch and then selecting a different
branch to diff it against the first one) it wasn't possible to change
the diff context size using `{` and `}`, or the rename threshold using
`(` and `)`.

Fixes #5254.
2026-03-08 17:53:30 +01:00
Stefan Haller 9dd121dfa3 Enable { and } to change diff context size in branches and tags panels in diffing mode
Actually, we simply enable them in any panel, even those that can never show a
diff. Since the commands show a toast, that's enough feedback to understand what
happened; the change will take effect the next time you switch to a panel that
does show diffs.

Same for ( and ) to change the rename threshold.
2026-03-08 17:51:00 +01:00
Stefan Haller 17e7044d7c Properly disable clicks in inactive views behind popups (#5313)
We did already have code to prevent clicks in inactive views behind a
popup, but it wasn't good enough. This PR fixes two problems:
- if the previously focused view (behind the panel) was a list view, it
would look like the click would select a different row, because gocui
would still set the view's cursor position, which is used to draw the
highlighted row
- it was still possible to click on tab headers, and this would dismiss
the panel

Fixes #5256.
2026-03-08 17:39:51 +01:00
Stefan Haller b955002d17 Use new ShouldHandleMouseEvent hook to prevent clicks in views behind panels
This fixes two problems:
- if the previously focused view (behind the panel) was a list view, it would
  look like the click would select a different row, because gocui would still
  set the view's cursor position, which is used to draw the highlighted row
- it was still possible to click on tab headers, and this would dismiss the
  panel
2026-03-08 17:32:09 +01:00
Stefan Haller ab86b42eec Bump gocui 2026-03-08 17:31:57 +01:00
Stefan Haller 4d08c8149e Fix off-by-one error when calculating popup panel dimensions (#5312)
The symptom of the bug was that confirmation panels with wrapped text
were one character too wide, which could sometimes result in them being
one line too heigh. One concrete example is the "Discard file changes"
confirmation that appears when pressing `d` in the commit files panel.
2026-03-08 17:27:52 +01:00
Stefan Haller da065b5b63 Add comments
I got confused when I investigated the bug that was fixed in the previous
commit, so hopefully these will be helpful for the next person reading this
code.
2026-03-08 17:24:26 +01:00
Stefan Haller bcfb4e11c0 Fix off-by-one error when calculating popup panel dimensions
The symptom of the bug was that confirmation panels with wrapped text were one
character too wide, which could sometimes result in them being one line too
heigh. One concrete example is the "Discard file changes" confirmation that
appears when pressing `d` in the commit files panel.

I got very confused when investigating this bug, and the reason is that
getPopupPanelDimensionsAux took two parameters panelWidth and panelHeight, but
the second was actually contentHeight. Rename it to contentHeight, and change
the first one to also be the content width rather than the panel width. This is
easier for clients, and less confusing.
2026-03-08 17:24:26 +01:00
Stefan Haller d8f87c6919 Add backward cycling support for log view (using <shift>-a on status page) (#5346)
This commit implements the ability to cycle backward through different
all branches log visualization modes, complementing the existing forward
cycling functionality. Users can now press 'A' (Shift+a) to cycle in
reverse through the available log graph views, improving navigation
efficiency when they overshoot their desired view.
2026-03-08 17:09:31 +01:00
Zak Siddiqui 7d32e45f73 Add backward cycling support for all branches log view
This commit implements the ability to cycle backward through different
all branches log visualization modes, complementing the existing forward
cycling functionality. Users can now press 'A' (Shift+a) to cycle in
reverse through the available log graph views, improving navigation
efficiency when they overshoot their desired view.

Changes:
- Added RotateAllBranchesLogIdxBackward() method to BranchCommands for
  backward rotation through log command candidates
- Introduced AllBranchesLogGraphReverse keybinding configuration with
  default key 'A' (uppercase)
- Implemented switchToOrRotateAllBranchesLogsBackward() handler in
  StatusController that mirrors forward cycling logic
- Added English translation for "Show/cycle all branch logs (reverse)"

The implementation uses modulo arithmetic with proper handling of
negative indices to ensure seamless backward cycling through the
available log visualization options.
2026-03-08 17:06:17 +01:00
Stefan Haller 551f341cf7 Fix typo: MacOS to macOS (#5335)
Corrects macOS capitalization to follow Apple's official branding
guidelines (2 occurrences in README).
2026-03-08 16:33:44 +01:00
04cb 53faf1fcd3 Fix typo: MacOS to macOS 2026-03-08 16:31:07 +01:00
Stefan Haller 25895bfa73 Fix #5302: Create .git/info directory before writing exclude file (#5325)
Fixes #5302

## Problem

When `.git/info` directory does not exist (can happen with bare clones,
manual deletion, or certain Git configurations), selecting "Add to
.git/info/exclude" fails with:

```
open <repo-path>/.git/info/exclude: no such file or directory
```

The `Exclude` function used `os.OpenFile` with `os.O_CREATE` which
creates the file but not its parent directory.

## Fix

Added `os.MkdirAll` to create the `.git/info` directory (with 0755
permissions) before attempting to open the exclude file. `MkdirAll` is a
no-op if the directory already exists, so existing behavior is
unchanged.

## Test

Added integration test `file/exclude_without_info_dir` that:
1. Removes `.git/info` directory during repo setup
2. Attempts to exclude a file via the menu
3. Verifies `.git/info/exclude` is created with the correct content

Test fails without the fix, passes with it.

Tested locally on macOS ARM (Apple Silicon). Unit tests and integration
test pass.
2026-03-08 16:26:40 +01:00
cobyfrombrooklyn-bot 30154aa9c5 Fix #5302: Create .git/info directory before writing exclude file
When .git/info directory does not exist (can happen with bare clones
or manual deletion), the Exclude function failed with 'no such file
or directory'. Added os.MkdirAll to create the directory before
opening the exclude file.

Added integration test exclude_without_info_dir that removes .git/info
before attempting to exclude a file.
2026-03-08 16:23:39 +01:00
Stefan Haller 9b74805d2d Bump github.com/cloudflare/circl from 1.6.1 to 1.6.3 (#5323)
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl)
from 1.6.1 to 1.6.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cloudflare/circl/releases">github.com/cloudflare/circl's
releases</a>.</em></p>
<blockquote>
<h2>CIRCL v1.6.3</h2>
<p>Fix a bug on ecc/p384 scalar multiplication.</p>
<h3>What's Changed</h3>
<ul>
<li>sign/mldsa: Check opts for nil value by <a
href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/582">cloudflare/circl#582</a></li>
<li>ecc/p384: Point addition must handle point doubling case. by <a
href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/583">cloudflare/circl#583</a></li>
<li>Release CIRCL v1.6.3 by <a
href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/584">cloudflare/circl#584</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/cloudflare/circl/compare/v1.6.2...v1.6.3">https://github.com/cloudflare/circl/compare/v1.6.2...v1.6.3</a></p>
<h2>CIRCL v1.6.2</h2>
<ul>
<li>New SLH-DSA, improvements in ML-DSA for arm64.</li>
<li>Tested compilation on WASM.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Optimize pairing product computation by moving exponentiations to
G1. by <a href="https://github.com/dfaranha"><code>@​dfaranha</code></a>
in <a
href="https://redirect.github.com/cloudflare/circl/pull/547">cloudflare/circl#547</a></li>
<li>sign: Adding SLH-DSA signature by <a
href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/512">cloudflare/circl#512</a></li>
<li>Update code generators to CIRCL v1.6.1. by <a
href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/548">cloudflare/circl#548</a></li>
<li>ML-DSA: Add preliminary Wycheproof test vectors by <a
href="https://github.com/bwesterb"><code>@​bwesterb</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/552">cloudflare/circl#552</a></li>
<li>go fmt by <a
href="https://github.com/bwesterb"><code>@​bwesterb</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/554">cloudflare/circl#554</a></li>
<li>gz-compressing test vectors, use of HexBytes and ReadGzip functions.
by <a href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/555">cloudflare/circl#555</a></li>
<li>group: Removes use of elliptic Marshal and Unmarshal functions. by
<a href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/556">cloudflare/circl#556</a></li>
<li>Support encoding/decoding ML-DSA private keys (as long as they
contain seeds) by <a
href="https://github.com/bwesterb"><code>@​bwesterb</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/559">cloudflare/circl#559</a></li>
<li>Update to golangci-lint v2 by <a
href="https://github.com/bwesterb"><code>@​bwesterb</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/560">cloudflare/circl#560</a></li>
<li>Preparation for ARM64 Implementation of poly operations for
dilithium package. by <a
href="https://github.com/elementrics"><code>@​elementrics</code></a> in
<a
href="https://redirect.github.com/cloudflare/circl/pull/562">cloudflare/circl#562</a></li>
<li>prepare power2Round for custom implementations in assembly by <a
href="https://github.com/elementrics"><code>@​elementrics</code></a> in
<a
href="https://redirect.github.com/cloudflare/circl/pull/564">cloudflare/circl#564</a></li>
<li>ARM64 implementation for poly.PackLe16 by <a
href="https://github.com/elementrics"><code>@​elementrics</code></a> in
<a
href="https://redirect.github.com/cloudflare/circl/pull/563">cloudflare/circl#563</a></li>
<li>add arm64 version of polyMulBy2toD by <a
href="https://github.com/elementrics"><code>@​elementrics</code></a> in
<a
href="https://redirect.github.com/cloudflare/circl/pull/565">cloudflare/circl#565</a></li>
<li>add arm64 version of polySub by <a
href="https://github.com/elementrics"><code>@​elementrics</code></a> in
<a
href="https://redirect.github.com/cloudflare/circl/pull/566">cloudflare/circl#566</a></li>
<li>group: add byteLen method for short groups and RandomScalar uses
rand.Int by <a
href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/568">cloudflare/circl#568</a></li>
<li>add arm64 version of poly.Add/Sub by <a
href="https://github.com/elementrics"><code>@​elementrics</code></a> in
<a
href="https://redirect.github.com/cloudflare/circl/pull/572">cloudflare/circl#572</a></li>
<li>group: Adding cryptobyte marshaling to scalars by <a
href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/569">cloudflare/circl#569</a></li>
<li>Bumping up to Go1.25 by <a
href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/574">cloudflare/circl#574</a></li>
<li>ci: Including WASM compilation. by <a
href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/577">cloudflare/circl#577</a></li>
<li>Revert to using package-declared HPKE errors for shortkem instead of
standard library errors by <a
href="https://github.com/harshiniwho"><code>@​harshiniwho</code></a> in
<a
href="https://redirect.github.com/cloudflare/circl/pull/578">cloudflare/circl#578</a></li>
<li>Release v1.6.2 by <a
href="https://github.com/armfazh"><code>@​armfazh</code></a> in <a
href="https://redirect.github.com/cloudflare/circl/pull/579">cloudflare/circl#579</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/dfaranha"><code>@​dfaranha</code></a>
made their first contribution in <a
href="https://redirect.github.com/cloudflare/circl/pull/547">cloudflare/circl#547</a></li>
<li><a
href="https://github.com/elementrics"><code>@​elementrics</code></a>
made their first contribution in <a
href="https://redirect.github.com/cloudflare/circl/pull/562">cloudflare/circl#562</a></li>
<li><a
href="https://github.com/harshiniwho"><code>@​harshiniwho</code></a>
made their first contribution in <a
href="https://redirect.github.com/cloudflare/circl/pull/578">cloudflare/circl#578</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/cloudflare/circl/compare/v1.6.1...v1.6.2">https://github.com/cloudflare/circl/compare/v1.6.1...v1.6.2</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/cloudflare/circl/commit/24ae53c5d6f7fe18203adc125ba3ed76a38703e1"><code>24ae53c</code></a>
Release CIRCL v1.6.3</li>
<li><a
href="https://github.com/cloudflare/circl/commit/581020bd4a836b8ce7bd4e414ba2884c07dbc906"><code>581020b</code></a>
Rename method to oddMultiplesProjective.</li>
<li><a
href="https://github.com/cloudflare/circl/commit/12209a4566605692a8402594e367a5aed5148460"><code>12209a4</code></a>
Removing unused cmov for jacobian points.</li>
<li><a
href="https://github.com/cloudflare/circl/commit/fcba359f4178645d2c9e50f29ab6966337da4b95"><code>fcba359</code></a>
ecc/p384: use of complete projective formulas for scalar
multiplication.</li>
<li><a
href="https://github.com/cloudflare/circl/commit/5e1bae8d8c2df4e717c2c5c2d5b5d60b629b2ac6"><code>5e1bae8</code></a>
ecc/p384: handle point doubling in point addition with Jacobian
coordinates.</li>
<li><a
href="https://github.com/cloudflare/circl/commit/341604685ff97e8f7440ae4b4711ba1c118c648c"><code>3416046</code></a>
Check opts for nil value.</li>
<li><a
href="https://github.com/cloudflare/circl/commit/a763d47a6dce43d1f4f7b697d1d7810463a526f6"><code>a763d47</code></a>
Release CIRCL v1.6.2</li>
<li><a
href="https://github.com/cloudflare/circl/commit/3c70bf9ad53b681fbe5ba6067e454a86549fee8a"><code>3c70bf9</code></a>
Bump x/crypto x/sys dependencies.</li>
<li><a
href="https://github.com/cloudflare/circl/commit/3f0f15b2bfe67bad81a35e8aec81ae42ca78349d"><code>3f0f15b</code></a>
Revert to using package-declared HPKE errors for shortkem instead of
standard...</li>
<li><a
href="https://github.com/cloudflare/circl/commit/23491bd573cf29b6f567057a158203a2c9dfa30d"><code>23491bd</code></a>
Adding generic Power2Round method.</li>
<li>Additional commits viewable in <a
href="https://github.com/cloudflare/circl/compare/v1.6.1...v1.6.3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/cloudflare/circl&package-manager=go_modules&previous-version=1.6.1&new-version=1.6.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/jesseduffield/lazygit/network/alerts).

</details>
2026-03-08 16:09:04 +01:00
dependabot[bot] 386503109b Bump github.com/cloudflare/circl from 1.6.1 to 1.6.3
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.6.1 to 1.6.3.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.6.1...v1.6.3)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  dependency-version: 1.6.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-08 15:06:35 +00:00
Stefan Haller 5b94fd37fc Show branch name and detached HEAD in worktrees tab (#5339)
### PR Description

The worktrees tab now displays the checked-out branch (or detached HEAD
state) for each worktree, making it much easier to see which worktree
holds which branch.

This is useful when you need to "unlock" a branch that's occupied by
another worktree: you can now clearly see which worktrees are on a
branch vs detached, without having to select each one individually.

Also rename the "(main)" label to "(main worktree)" to avoid confusion
with the common "main" branch name, and move it after the branch column.
2026-03-08 12:53:47 +01:00
Ruud Kamphuis 727b4b56dd Show branch name and detached HEAD in worktrees tab
The worktrees tab now displays the checked-out branch (or detached HEAD
state) for each worktree, making it much easier to see which worktree
holds which branch.

This is useful when you need to "unlock" a branch that's occupied by
another worktree: you can now clearly see which worktrees are on a
branch vs detached, without having to select each one individually.

Also rename the "(main)" label to "(main worktree)" to avoid confusion
with the common "main" branch name, and move it after the branch column.
2026-03-08 12:51:46 +01:00
Stefan Haller 35911da3a6 Filter file views rather than search (#5273)
### PR Description

Way back when I implemented filter functionality I could not muster the
motivation to apply it to the file views (files and commit files), but
it really should be used on them.

The text filter matches against the full file path (not just the
filename), which is more useful for navigating large directory trees.

When a text filter is active, all operations respect it consistently:
- **Diffs**: selecting a filtered directory shows only the diff of
visible files, not all files in the directory
- **Staging/unstaging**: pressing space on a filtered directory only
stages/unstages visible files
- **Toggle all (a)**: only toggles staging for visible files
- **Custom patch**: toggling a filtered directory only adds visible
files to the patch

Full disclosure, opus 4.6 wrote this entire PR but reviewing its changes
they seem reasonable, and I have done some local testing and everything
works as expected.
2026-03-07 20:06:36 +01:00
Jesse DuffieldandClaude Opus 4.6 615c566ac4 Filter file views rather than search
Change working tree files and commit files panels to use filtering
(reducing the list) instead of search (highlighting matches). This
matches the behavior of other filterable views.

The text filter matches against the full file path, not just the
filename, which is more useful for navigating large directory trees.

When toggling a directory for a custom patch while a text filter is
active, only the visible filtered files in the directory are affected,
consistent with how staging a directory in the files panel works.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 20:04:31 +01:00
Jesse DuffieldandClaude Opus 4.6 8728da7985 Only reset selection in ReApplyFilter when search prompt is active
Without this check, the selection was being reset to 0 whenever
ReApplyFilter was called for the current filter context, even when
the user wasn't actively typing in the search prompt (e.g. when the
model updates in the background). This was causing unexpected cursor
jumps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 20:04:31 +01:00
Jesse DuffieldandClaude Opus 4.6 ed9693ebcc Reset PrevSearchIndex when opening filter prompt
When opening a filter prompt, reset PrevSearchIndex to -1 to avoid
stale search state from a previous search/filter session.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 20:04:31 +01:00
Jesse DuffieldandClaude Opus 4.6 60316388c0 Rename GetFilter to GetStatusFilter on IFileTree
This avoids a naming collision with GetFilter from the
IFilterableContext interface, which will be implemented by
FileTreeViewModel in the next commit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 20:04:31 +01:00
Stefan Haller 825784fbf4 Allow removing lines from patch directly (#5277)
I always press 'd' in the patch building view, expecting that I can do
exactly what I can do in the staging view, to find out I need to go
space -> ctrl+p -> d and I think it's time to honour the muscle memory
and support this convenience keybinding. I recall we may have had a
debate about this in the past and if so I'm renewing my stance.
2026-03-07 20:02:43 +01:00
Jesse Duffield 5b6a8a304e Prevent patch building panel from briefly appearing when discarding change from commit 2026-03-07 20:47:20 +11:00
Jesse Duffield 0f2f20b900 Allow discarding lines from patch directly
I always press 'd' in the patch building view, expecting that I can do
exactly what I can do in the staging view, to find out I need to go
space -> ctrl+p -> d and I think it's time to honour the muscle memory
and support this convenience keybinding.
2026-03-07 20:47:20 +11:00
Stefan Haller b3d81a0c7c Add DisabledReason for discarding from a multiselection of commits 2026-03-07 20:47:20 +11:00
Stefan Haller 35d06c32d7 Turn error checks in discard handler into DisabledReasons
That's how we usually do this; it's useful to see in the keybindings menu that
the command is disabled.
2026-03-07 20:47:19 +11:00
Stefan Haller 2b65bee675 Remove redundant CantPatchWhileRebasingError checks in handlers
We don't add the commands to the menu when we're rebasing, so it's pointless to
check this in the handlers.

I guess alternatively we could add all commands always, and strike out the ones
that are not applicable using DisabledReasons. But we don't usually do this in
menus (except the global keybindings menu).
2026-03-07 20:47:19 +11:00
Stefan Haller 7f9bfaec08 Warn more prominently about resetting the patch when discarding changes
Only mention resetting the patch when there actually is one. This way users have
to read less text in the normal case, and the added note hopefully stands out
more if there is one. Also, separate the note from the previous text by a blank
line.
2026-03-07 20:47:19 +11:00
Stefan Haller b256215397 Say "discard" instead of "remove" when discard changes from a commit
"Remove" can be confusing when a deleted file is selected; in this cases it
actually "un-removes" it. "Discard" hopefully makes it clearer that we are
talking about the change to a file, and not the file itself.
2026-03-07 20:47:19 +11:00
Stefan Haller 9046d5eb14 Hide the "Fetching..." status of the auto-fetch when bottom line is hidden (#5321)
If the bottom line is hidden (by setting `gui.showBottomLine` to false
in the config), don't show the "Fetching..." status because it changes
the layout, which should happen only in response to user actions.

However, keep the status for the first fetch after startup, and right
after switching repos, because in these cases it is useful to see when
the fetch is done.

Closes #5242.
2026-03-02 10:48:55 +01:00
Stefan Haller 641467bc79 Hide the "Fetching..." status of the auto-fetch when bottom line is not showing
If the bottom line is hidden (by setting gui.showBottomLine to false in the
config), don't show the "Fetching..." status because it changes the layout,
which should happen only in response to user actions.

However, keep the status for the first fetch after startup, and right after
switching repos, because in these cases it is useful to see when the fetch is
done.
2026-03-02 10:46:09 +01:00
Stefan Haller 1b08dc9e9c Rename "Copy commit hash to clipboard" to mention it's an abbreviated hash (#5331)
Fixes #5330.
2026-03-02 10:45:21 +01:00
Stefan Haller c08d32aa4f Rename "Copy commit hash to clipboard" to mention abbreviated hash 2026-03-02 09:53:11 +01:00
Stefan Haller 818ca17f9a Fix matching of lazygit-edit URLs without line numbers (#5311)
### PR Description

Tweak regexp such that a trailing ":" is not included in the file path
extracted from a lazygit-edit URL.

Previously, when matching a URL containing the ":" separator but no line
number, such as `lazygit-edit:///path/to/file.ext:`, the trailing
separator would be included in the matched file path, so lazygit would
open the non-existent file `/path/to/file.ext:`. Notably, such urls are
created when using delta with the hyperlink feature, as suggested in
https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md#delta,
and clicking a file path rather than a line number.

Fixes #5308
2026-02-22 17:27:57 +01:00
Daniel Wennberg 8821770711 Fix matching of lazygit-edit URLs without line numbers
Tweak regexp such that a trailing ":" is not included in the file path
extracted from a lazygit-edit URL.

Previously, when matching a URL containing the ":" separator but no line
number, such as `lazygit-edit:///path/to/file.ext:`, the trailing
separator would be included in the matched file path, so lazygit would
open the non-existent file `/path/to/file.ext:`. Notably, such urls are
created when using delta with the hyperlink feature, as suggested in
https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md#delta,
and clicking a file path rather than a line number.
2026-02-22 17:14:23 +01:00
Stefan Haller f8676ffa5e Add Terra as an alternative Fedora install method (#5281)
### PR Description

Adds Terra as an alternative Fedora install method. There are a few
advantages to this method over the Copr:
- Auto-updates
- Not a sole repo just for lazygit
- Debug packages

Let me know if there are any formatting changes or anything else needed.

### Please check if the PR fulfills these requirements

* [x] Cheatsheets are up-to-date (run `go generate ./...`)
* [x] Code has been formatted (see
[here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting))
* [x] Tests have been added/updated (see
[here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md)
for the integration test guide)
* [x] Text is internationalised (see
[here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation))
* [x] If a new UserConfig entry was added, make sure it can be
hot-reloaded (see
[here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig))
* [x] Docs have been updated if necessary
* [x] You've read through your own file changes for silly mistakes etc

<!--
Be sure to name your PR with an imperative e.g. 'Add worktrees view',
and make sure the title
is suitable to be included as a bullet point in release notes (i.e.
phrased from a user's point
of view).
see https://github.com/jesseduffield/lazygit/releases/tag/v0.40.0 for
examples
-->
2026-02-22 14:46:21 +01:00
Owen Zimmerman 545c4f719e docs: Add Terra install method 2026-02-22 14:43:57 +01:00
Stefan Haller 1d0db51caf Update docs and schema for release (#5276) 2026-02-07 09:33:09 +01:00
Stefan Haller 980a8ca53e Update docs and schema for release 2026-02-07 09:29:34 +01:00
Stefan Haller aa7d26be59 Auto-update cheatsheets after updating translation (#5275)
I keep forgetting to do this, and I think there's no reason to update
translations without also updating cheatsheets, so do it automatically.
2026-02-07 09:24:01 +01:00
Stefan Haller 4b69d93660 Auto-update cheatsheets after updating translation
I keep forgetting to do this, and I think there's no reason to update
translations without also updating cheatsheets, so do it automatically.
2026-02-07 09:21:22 +01:00
Stefan Haller 82e283429a Update translations from Crowdin (#5274) 2026-02-07 09:13:06 +01:00
Stefan Haller 6edf29b0dc Update translations from Crowdin 2026-02-07 09:10:45 +01:00
Stefan Haller c9a883b273 fix(config): add Nushell support for nvim-remote preset (#5250)
Using Nushell's native if/else syntax to avoid '&&' syntax errors in the
nvim-remote editor preset.
Closes #5211
2026-02-07 09:03:18 +01:00
baiyei_dk 7eb561921b fix(config): add Nushell support for nvim-remote preset
Using Nushell's native if/else syntax to avoid '&&' syntax errors
in the nvim-remote editor preset.
Closes #5211
2026-02-07 09:00:10 +01:00
Stefan Haller 48f2e1dfc1 Update README to add GitArbor TUI as an alternative (#5257) 2026-02-07 08:55:32 +01:00
cadamsdev 2f575a0b37 Update README to mention GitArbor as an alternative 2026-02-07 08:53:14 +01:00
Stefan Haller 641740fdec Disable the automatic, scheduled release (#5272)
There's too much manual work involved in releasing now (updating
translations, copying docs-master) to make automatic releases
infeasible. I'm not worried that I forget to release on the first
Saturday of every month.

Keeping the code commented out in case we want to re-enable it at some
point.
2026-02-06 19:39:51 +01:00
Stefan Haller bdc780a890 Disable the automatic, scheduled release
There's too much manual work involved in releasing now (updating translations,
copying docs-master) to make automatic releases infeasible. I'm not worried that
I forget to release on the first Saturday of every month.

Keeping the code commented out in case we want to re-enable it at some point.
2026-02-06 19:36:58 +01:00
Stefan Haller 443452ad6a Fix rendering of the Reflog panel when using up/down to scroll it (#5248)
This is a regression introduced with #5135. I didn't notice it because I
am using `gui.scrollOffBehavior: jump`, in which case the problem
wouldn't appear; it only happened with `scrollOffBehavior: margin`
(which is the default). In that case, if you used the arrow keys (or
j/k) to move the selection so that the view would start to scroll, empty
space would appear.

Fixes #5235.
2026-01-29 14:26:21 +01:00
Stefan Haller d97531aeef Fix rendering of the Reflog panel when using up/down to scroll it
This is a regression introduced with #5135. I didn't notice it because I am
using `gui.scrollOffBehavior: jump`, in which case the problem wouldn't appear;
it only happened with `scrollOffBehavior: margin` (which is the default). In
that case, if you used the arrow keys (or j/k) to move the selection so that the
view would start to scroll, empty space would appear.
2026-01-29 14:23:16 +01:00
Stefan Haller 819212b758 Fix gitignore path collisions (#5245)
### PR Description

Paths added to ignore/exclude files need to be prefixed with a forward
slash to point to a specific file in the directory tree.

Without that prefix a file at root called `file` (added to `.gitignore`
as `file`) would match with `./file` and `./src/file`.

Example flow:
1. User creates a directory called `tests` in root
2. User sees that it's tracked
3. User ignores the directory in Lazygit
4. Changes in `src/tests` are now missing - because `tests` without `/`
matches also directories lower in the tree
2026-01-28 21:12:35 +01:00
Dawid Pietrykowski 48a8a71d31 Fix gitignore path collisions
Paths added to ignore/exclude files need to be prefixed with a forward
slash to point to a specific file in the directory tree.

Without that prefix a file at root called `file` (added to `.gitignore`
as `file`) would match with `./file` and `./src/file`.
2026-01-28 21:10:29 +01:00
Stefan Haller be703f3d27 Fix rendering of CRLF sequence ('\r\n') (#5237)
Fixes #5188.
2026-01-28 20:59:56 +01:00
Stefan Haller 06a9ff12ab Bump gocui
This brings in https://github.com/jesseduffield/gocui/pull/98 with the following
fix:

Fix rendering of CRLF sequence ('\r\n')

The FirstGraphemeCluster call returns this as a single character; we want to
treat it the same way as a single \n.

This would be a problem if e.g. a progress bar used \r repeatedly to paint over
the same line, and then printed a \n to move on to the next line; the last pair
of \r and \n was swallowed.

Another scenario where this was a problem was if you stream output of a command
to the log, and the command used \r\n as line feeds. This happens for example
for a background fetch that fails with an error; in that case we print the
combined output (stdout plus stderr) to the log after the command finished, and
for some reason it uses \r\n in that case (I can't actually explain why; when I
do `git fetch --all | xxd` I see only bare \n characters). All output would
appear on one line then.

Also, filter out escape sequences for character set designation; there's nothing
useful we can do with them. In practice, the only one that you are likely to see
is `ESC ( B`, which is sent as part of tput sgr0, which is sometimes used in
scripts to reset all graphics attributes to defaults.
2026-01-28 20:57:09 +01:00
Stefan Haller 4c9cc1ab7f When moving commits up/down and the selection leaves the view, scroll to make it visible again (#5247)
This used to work before 0.58, but broke with efd4298b5e (#5134).

Fixes #5244.
2026-01-28 20:47:53 +01:00
Stefan Haller 02997d30d9 When moving commits up/down and the selection leaves the view, scroll to make it visible again
This used to work before 0.58, but broke with efd4298b5e
(#5134).
2026-01-28 20:44:09 +01:00
Stefan Haller ce202a5612 Support using the selected commit's message in a fixup (#5233)
### PR Description

I had a spare couple hours so figured I'd whip up a PR for a feature
I've wanted for a while.

I've optimised for muscle memory backwards compatibility here:
- Outside interactive rebase: press 'f' then instead of a confirmation
panel, a menu appears where you can choose to keep the selected commit's
message
- Inside interactive rebase: press 'f' then press 'c' to see the menu
for keeping the message, where if you press 'c' again it will retain the
current message. so 'fcc' is the chord to press.

We're also now showing the -C flag (which is what enables the behaviour)
against the todo.

I've picked the 'c' keybinding because 'C' was taken and it corresponds
to the flag. Previously that showed a warning about a change in
keybinding for cherry picking but it's been ages since we've made that
change so I'm happy to retire it.
2026-01-28 10:31:47 +01:00
Jesse Duffield f317a97ac1 Support using the selected commit's message in a fixup
I've optimised for muscle memory backwards compatibility here:
  - Outside interactive rebase: press 'f' then instead of a confirmation
panel, a menu appears where you can choose to keep the selected commit's
message
  - Inside interactive rebase: press 'f' then press 'c' to see the menu
for keeping the message, where if you press 'c' again it will retain the
current message. so 'fcc' is the chord to press.

We're also now showing the -C flag (which is what enables the behaviour)
against the todo.

I've picked the 'c' keybinding because 'C' was taken and it corresponds
to the flag. Previously that showed a warning about a change in
keybinding for cherry picking but it's been ages since we've made that
change so I'm happy to retire it.
2026-01-28 10:28:52 +01:00
Jesse DuffieldandStefan Haller 6f6545e44f Pass todo flag to EditRebaseTodo
Not used yet, we pass an empty string everywhere, to match the previous
behavior. Just extracting this into a separate commit to make the next one
smaller.

Co-authored-by: Stefan Haller <stefan@haller-berlin.de>
2026-01-28 10:15:51 +01:00
Jesse DuffieldandStefan Haller 99e26be3d9 Show -C for fixup todos in rebase if present
Co-authored-by: Stefan Haller <stefan@haller-berlin.de>
2026-01-28 10:15:48 +01:00
Jesse DuffieldandStefan Haller de98258e39 Add ActionFlag field to Commit
Co-authored-by: Stefan Haller <stefan@haller-berlin.de>
2026-01-28 10:15:45 +01:00
Jesse DuffieldandStefan Haller 3bf833aea7 Remove the "old cherry-pick key" warning
It's been ages since we changed the key, users should hopefully be used to it by
now, and we want to reuse the key for something else later in the branch.

Co-authored-by: Stefan Haller <stefan@haller-berlin.de>
2026-01-28 10:15:15 +01:00
Stefan Haller 39cd4746d5 Limit popup panel widths to a maximum width (#5231)
On very large screens they would get ridiculously wide.

The limits we chose here are a little arbitrary:
- 80 for confirmations and prompts
- 90 for menus
- auto-wrap width plus 25 for the commit message editor (or 100 if
auto-wrap is off)
2026-01-28 09:04:30 +01:00
Stefan Haller 1ede4e6eb9 Limit popup panel widths to a maximum width
On very large screens they would get ridiculously wide.

The limits we chose here are a little arbitrary:
- 80 for confirmations and prompts
- 90 for menus
- auto-wrap width plus 25 for the commit message editor (or 100 if auto-wrap is
  off)
2026-01-28 09:02:27 +01:00
Stefan Haller 4c731abedd Fix opening a menu when a previous menu was scrolled down (#5238)
To reproduce: open the keybindings menu ('?'), press '>' to select the
last line, esc to close it, open it again. The view would appear still
scrolled down, so the selected first line was out of view. Even worse,
if you open a different, shorter menu (e.g. the "View upstream reset
options..." menu in the Files panel), you'd only see the Cancel item,
the other ones were scrolled out of view.

This is a regression introduced with efd4298b5e (#5134).
2026-01-25 16:21:22 +01:00
Stefan Haller c10dfcefcf Fix opening a menu when a previous menu was scrolled down
To reproduce: open the keybindings menu ('?'), press '>' to select the last
line, esc to close it, open it again. The view would appear still scrolled down,
so the selected first line was out of view. Even worse, if you open a different,
shorter menu (e.g. the "View upstream reset options..." menu in the Files
panel), you'd only see the Cancel item, the other ones were scrolled out of
view.

This is a regression introduced with efd4298b5e (#5134).
2026-01-25 16:17:13 +01:00
Stefan Haller 50b5c17d93 Don't log the "git rev-list" call when marking bisect commits (#5236)
When marking commits as good or bad during a bisect, a "git rev-list"
call would appear in the Command log. This is confusing, it's an
internal detail that is not interesting for the user to see.
2026-01-25 11:50:21 +01:00
Stefan Haller 8d36c8b3c1 Don't log the "git rev-list" call when marking bisect commits
When marking commits as good or bad during a bisect, a "git rev-list" call would
appear in the Command log. This is confusing, it's an internal detail that is
not interesting for the user to see.
2026-01-25 11:47:07 +01:00
Stefan Haller 9f44caa568 Exclude commit trailers from line wrapping (#5230)
Bump gocui, which brings in
https://github.com/jesseduffield/gocui/pull/97.

#Fixes #5216.
2026-01-25 11:25:21 +01:00
Stefan Haller 39477172b8 Bump gocui
This brings in https://github.com/jesseduffield/gocui/pull/97 ("Exclude commit
trailers from line wrapping").
2026-01-25 11:23:05 +01:00
Stefan Haller 7545fc48e5 chore: Update outdated GitHub Actions versions (#5220)
### PR Description

- Updated `actions/github-script` from `v7` to `v8` in
`.github/workflows/close-issues.yml`
- Updated `actions/setup-go` from `v5` to `v6` in
`.github/workflows/release.yml`
- Updated `golangci/golangci-lint-action` from `v8` to `v9` in
`.github/workflows/ci.yml`
- Updated `actions/checkout` from `v4` to `v6` in
`.github/workflows/codespell.yml`
- Updated `actions/checkout` from `v4` to `v6` in
`.github/workflows/release.yml`
- Updated `peter-evans/create-pull-request` from `v7` to `v8` in
`.github/workflows/sponsors.yml`
- Updated `actions/download-artifact` from `v4` to `v7` in
`.github/workflows/ci.yml`
- Updated `actions/checkout` from `v4` to `v6` in
`.github/workflows/ci.yml`
- Updated `actions/checkout` from `v4` to `v6` in
`.github/workflows/sponsors.yml`
- Updated `actions/setup-go` from `v5` to `v6` in
`.github/workflows/ci.yml`

The changes ensure that the GitHub Action workflows are using the latest
versions of the actions, which include improved functionality and
compatibility. These updates will be tested in the CI pipeline of the
pull request.
2026-01-24 16:28:57 +01:00
Padraic Slattery 3d78263e0c chore: Update outdated GitHub Actions versions 2026-01-24 16:26:11 +01:00
Stefan Haller 11e877cbad Have "Find base commit for fixup" ignore fixup commits for the found base commit (#5210)
If the ctrl-f function (Find base commit for fixup) finds a base commit
plus a bunch of fixup! commits for that base commit, it ignores those
fixups and selects the base commit. For the purpose of creating another
fixup commit on top this is always what you want, so I'm doing this
without adding a confirmation. If the user presses shift-A after that to
amend their changes though, they are guaranteed to get conflicts, so for
that case a warning might be useful; however, I find it unlikely that
users will want to amend changes to a commit that they already created
fixups for, so I'm just hoping that this won't happen in practice.

This implementation is a bit stricter than #5201, in that it only
ignores fixups if the first found commit is not a fixup itself; because
if it is, it's not clear whether the user wants to create another fixup
for both on top, or amend the changes into each one, in which case they
need to be staged individually.
2026-01-24 16:06:38 +01:00
Stefan Haller 268d1934f8 Ignore fixup commits for a found base commit when doing ctrl-f 2026-01-24 16:04:35 +01:00
Stefan Haller 4bcf3e181c Extract a helper method getCommitsForHashes 2026-01-24 16:04:35 +01:00
Stefan Haller df1e5512da Make getHashesAndSubjects a free-standing function
There's no reason for this to be a method.
2026-01-24 16:04:35 +01:00
Stefan Haller 2ba3c1dc3f Move isFixupCommit to FixupHelper 2026-01-24 16:04:35 +01:00
Stefan Haller b41bb8f845 Add a test that documents the current behavior
Currently we get an annoying error message, but we'd like the base commit to be
selected, disregarding the fixup.
2026-01-24 16:04:35 +01:00
Jesse Duffield 0339b414d9 README.md: Update Sponsors (#5095)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2026-01-24 17:33:11 +11:00
github-actions[bot] cb719c11c5 README.md: Update Sponsors 2026-01-17 10:59:48 +00:00
Stefan Haller 19605ad476 Update devcontainer VARIANT to 1-trixie (#5204)
### PR Description

The previous `1-bullseye` did not have the required go version 1.25.0
2026-01-17 11:59:37 +01:00
mricherzhagen e0c1d1c752 Update devcontainer VARIANT to 1-trixie
The previous `1-bullseye` did not have the required go version 1.25.0
2026-01-13 19:04:57 +00:00
Stefan Haller 4486c86271 Fix rendering artefacts after double-width characters (e.g. "⚠️") on some terminals (#5198)
Fixes
https://github.com/jesseduffield/lazygit/issues/5171#issuecomment-3710757175.
2026-01-12 10:02:27 +01:00
Stefan Haller b44a369295 Bump tcell
This fixes rendering artefacts after double-width characters such as "⚠️" on
some terminals.
2026-01-12 09:57:50 +01:00
Stefan Haller 498bc457fc Don't log the "git ls-remote" call when opening a PR (#5195)
When opening a PR, a "git ls-remote" call would appear in the Command
log. This is confusing, it's an internal detail that is not interesting
for the user to see.
2026-01-11 20:04:54 +01:00
Stefan Haller 7f957f059b Don't log the "git ls-remote" call when opening a PR
When opening a PR, a "git ls-remote" call would appear in the Command log. This
is confusing, it's an internal detail that is not interesting for the user to
see.
2026-01-11 20:02:08 +01:00
Stefan Haller 1a4af359ec Request info about terminal in issue template (#5194)
For some types of bugs it can be relevant what terminal is being used,
so ask users to provide this information when they file an issue.
2026-01-11 20:00:34 +01:00
Stefan Haller f16bec2ce3 Ask users to provide information about their terminal 2026-01-11 19:56:47 +01:00
Stefan Haller 798fe4a1ef Remove git version
It's unnecessary to ask users to provide this; the output of `lazygit --version`
contains it already.
2026-01-11 19:56:47 +01:00
Stefan Haller bb2e5fa886 Update tcell dependency (#5192)
This provides two fixes:
- proper handling of keypad keys on certain terminals (e.g. iTerm2)
- fix problems pasting certain emojis or east asian text on Windows
Terminal

Fixes #5171
Fixes #5173
2026-01-11 18:30:51 +01:00
Stefan Haller 3067ff1cac bump tcell
This provides two fixes:
- proper handling of keypad keys on certain terminals (e.g. iTerm2)
- fix problems pasting certain emojis or east asian text on Windows Terminal
2026-01-11 18:15:54 +01:00
Stefan Haller 312feff130 Fix pasting multi-line text into the commit description (#5186)
This fixes a regression in 0.58.

Fixes #5181.
2026-01-11 18:10:17 +01:00
Stefan Haller ee60102fdc Bump gocui
This fixes pasting multi-line text into the commit message editor; see
https://github.com/jesseduffield/gocui/pull/96.
2026-01-11 18:07:30 +01:00
Stefan Haller 7b969a03ad When doing ctrl-f, and the resulting commit is not visible, scroll it into view (#5182)
This used to work in the last version, but broke with efd4298b5e
(#5134).
2026-01-11 18:01:54 +01:00
Stefan Haller 1f7e5d7767 When doing ctrl-f, and the resulting commit is not visible, scroll it into view
This used to work in the last version, but broke with efd4298b5e (#5134).
2026-01-06 16:17:33 +01:00
Stefan Haller 80dd695d7a Update search position (match x of y) when changing the selection in a list view (#5169)
When searching (not filtering) in a list view using `/`, moving the
selection now updates the "x of y" indicator of the search results to
the last one before the selection. Pressing `n` again searches from
there rather than from the previously shown result.

Also see corresponding gocui PR at
https://github.com/jesseduffield/gocui/pull/95.
2026-01-04 18:54:28 +01:00
Stefan Haller 65edd99fd0 Update search position (match x of y) when changing the selection in a list view
or in the staging view.
2026-01-04 18:51:45 +01:00
Stefan Haller 98bf8f86d1 Bump gocui and adapt code accordingly 2026-01-04 18:48:47 +01:00
178 changed files with 8264 additions and 36396 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
# adapted from https://github.com/devcontainers/images/blob/main/src/go/.devcontainer/Dockerfile
# [Choice] Go version (use -bullseye variants on local arm64/Apple Silicon): 1, 1.19, 1.18, 1-bullseye, 1.19-bullseye, 1.18-bullseye, 1-buster, 1.19-buster, 1.18-buster
ARG VARIANT=1-bullseye
ARG VARIANT=1-trixie
FROM golang:${VARIANT}
RUN go install mvdan.cc/gofumpt@latest
+3 -1
View File
@@ -26,7 +26,9 @@ If applicable, add screenshots to help explain your problem.
### Version info:
* _Run `lazygit --version` and paste the result here_
* _Run `git --version` and paste the result here_
### Terminal info:
What terminal are you using, and which version? For some types of bugs this information can be relevant.
### Additional context
Add any other context about the problem here.
+17 -17
View File
@@ -28,9 +28,9 @@ jobs:
GOFLAGS: -mod=vendor
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: 1.25.x
- name: Test code
@@ -39,7 +39,7 @@ jobs:
mkdir -p /tmp/code_coverage
go test ./... -short -cover -args "-test.gocoverdir=/tmp/code_coverage"
- name: Upload code coverage artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: coverage-unit-${{ matrix.os }}-${{ github.run_id }}
path: /tmp/code_coverage
@@ -59,7 +59,7 @@ jobs:
GOFLAGS: -mod=vendor
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Restore Git cache
if: matrix.git-version != 'latest'
id: cache-git-restore
@@ -85,7 +85,7 @@ jobs:
path: ~/git-${{matrix.git-version}}
key: ${{runner.os}}-git-${{matrix.git-version}}
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: 1.25.x
- name: Print git version
@@ -98,7 +98,7 @@ jobs:
mkdir -p /tmp/code_coverage
./scripts/run_integration_tests.sh
- name: Upload code coverage artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: coverage-integration-${{ matrix.git-version }}-${{ github.run_id }}
path: /tmp/code_coverage
@@ -109,9 +109,9 @@ jobs:
GOARCH: amd64
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: 1.25.x
- name: Build linux binary
@@ -136,9 +136,9 @@ jobs:
GOARCH: amd64
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: 1.25.x
- name: Check Vendor Directory
@@ -162,13 +162,13 @@ jobs:
GOFLAGS: -mod=vendor
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: 1.25.x
- name: Lint
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
# If you change this, make sure to also update scripts/golangci-lint-shim.sh
version: v2.4.0
@@ -182,15 +182,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: 1.25.x
- name: Download all coverage artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v7
with:
path: /tmp/code_coverage
@@ -219,7 +219,7 @@ jobs:
run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} ))" >> "${GITHUB_ENV}"
- name: "Checkout PR branch and all PR commits"
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.ref }}
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
if: ${{ github.event.issue.pull_request == null && startsWith(github.event.comment.body, '/close') }}
steps:
- uses: actions/github-script@v7
- uses: actions/github-script@v8
with:
script: |
const trustedUsers = ['ChrisMcD1', 'jesseduffield', 'stefanhaller']
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Annotate locations with typos
uses: codespell-project/codespell-problem-matcher@v1
- name: Codespell
+7 -6
View File
@@ -1,10 +1,11 @@
name: Release
on:
schedule:
# Runs at 8:00 AM UTC on every Saturday
# We'll check below if it's the first Saturday of the month, and fail if not
- cron: '0 8 * * 6'
# schedule:
# # Runs at 8:00 AM UTC on every Saturday
# # We'll check below if it's the first Saturday of the month, and fail if not
# - cron: '0 8 * * 6'
# Allow manual triggering of the workflow
workflow_dispatch:
inputs:
@@ -45,7 +46,7 @@ jobs:
fi
- name: Checkout Code
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
repository: jesseduffield/lazygit
token: ${{ secrets.LAZYGIT_RELEASE_PAT }}
@@ -146,7 +147,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.LAZYGIT_RELEASE_PAT }}
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: 1.25.x
+2 -2
View File
@@ -10,7 +10,7 @@ jobs:
if: ${{ github.repository == 'jesseduffield/lazygit' }}
steps:
- name: Checkout 🛎️
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Generate Sponsors 💖
uses: JamesIves/github-sponsors-readme-action@v1.2.2
@@ -19,7 +19,7 @@ jobs:
file: "README.md"
- name: Create Pull Request 🚀
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@v8
with:
commit-message: "README.md: Update Sponsors"
title: "README.md: Update Sponsors"
+18 -3
View File
File diff suppressed because one or more lines are too long
+2
View File
@@ -666,6 +666,7 @@ keybinding:
checkForUpdate: u
recentRepos: <enter>
allBranchesLogGraph: a
allBranchesLogGraphReverse: A
files:
commitChanges: c
commitChangesWithoutHook: w
@@ -713,6 +714,7 @@ keybinding:
renameCommitWithEditor: R
viewResetOptions: g
markCommitAsFixup: f
setFixupMessage: c
createFixupCommit: F
squashAboveCommits: S
moveDownCommit: <c-j>
+9 -6
View File
@@ -60,7 +60,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` <c-o> `` | Copy path to clipboard | |
| `` y `` | Copy to clipboard | |
| `` c `` | Checkout | Checkout file. This replaces the file in your working tree with the version from the selected commit. |
| `` d `` | Remove | Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file. |
| `` d `` | Discard | Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file. |
| `` o `` | Open file | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
@@ -71,7 +71,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Search the current view by text | |
| `` / `` | Filter the current view by text | |
## Commit summary
@@ -84,11 +84,12 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
| `` b `` | View bisect options | |
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Reword | Reword the selected commit's message. |
| `` R `` | Reword with editor | |
| `` d `` | Drop | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -159,7 +160,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Search the current view by text | |
| `` / `` | Filter the current view by text | |
## Input prompt
@@ -236,6 +237,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` o `` | Open file | Open file in default application. |
| `` e `` | Edit file | Open file in external editor. |
| `` <space> `` | Toggle lines in patch | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Exit custom patch builder | |
| `` / `` | Search the current view by text | |
@@ -273,7 +275,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Checkout | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
@@ -351,13 +353,14 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` u `` | Check for update | |
| `` <enter> `` | Switch to a recent repo | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Checkout | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
+11 -8
View File
@@ -64,11 +64,12 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | コミットハッシュをクリップボードにコピー | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | コピーされた(チェリーピックされた)コミットの選択をリセット | |
| `` b `` | bisectオプションを表示 | |
| `` s `` | スカッシュ | 選択したコミットをその下のコミットにスカッシュします。スカッシュとは複数のコミットを1つにまとめる操作です。選択したコミットのメッセージが下のコミットに追加されます。 |
| `` f `` | フィックスアップ | 選択したコミットをその下のコミットにマージします。フィックスアップはスカッシュと似ていますが、選択したコミットのメッセージは破棄され、下のコミットのメッセージのみが保持されます。 |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | メッセージ変更 | 選択したコミットのメッセージを変更します。 |
| `` R `` | エディタでメッセージ変更 | |
| `` d `` | 削除 | 選択したコミットを削除します。これはリベースを通じてブランチからコミットを削除します。コミットが後続のコミットが依存する変更を行っている場合、マージコンフリクトを解決する必要があるかもしれません。 |
@@ -107,18 +108,18 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| `` <c-o> `` | パスをクリップボードにコピー | |
| `` y `` | クリップボードにコピー | |
| `` c `` | チェックアウト(ブランチの切り替え) | ファイルをチェックアウトします。これにより、作業ツリー内のファイルが選択したコミットのバージョンに置き換えられます。 |
| `` d `` | 削除 | このコミットのこのファイルへの変更を破棄します。これはバックグラウンドで対話的なリベースを実行するため、後のコミットでもこのファイルが変更されている場合、マージコンフリクトが発生する可能性があります。 |
| `` d `` | 破棄 | このコミットのこのファイルへの変更を破棄します。これはバックグラウンドで対話的なリベースを実行するため、後のコミットでもこのファイルが変更されている場合、マージコンフリクトが発生する可能性があります。 |
| `` o `` | ファイルを開く | デフォルトのアプリケーションでファイルを開きます。 |
| `` e `` | 編集 | 外部エディタでファイルを開きます。 |
| `` <c-t> `` | 外部差分ツールを開く(git difftool) | |
| `` <space> `` | パッチに含めるファイルを切り替え | ファイルがカスタムパッチに含まれるかどうかを切り替えます。https://github.com/jesseduffield/lazygit#rebase-magic-custom-patchesを参照してください。 |
| `` a `` | すべてのファイルを切り替え | コミットのすべてのファイルをカスタムパッチに追加/削除します。https://github.com/jesseduffield/lazygit#rebase-magic-custom-patchesを参照してください。 |
| `` <enter> `` | ファイルに入る / ディレクトリの折りたたみを切り替える | ファイルが選択されている場合、そのファイルに入ってカスタムパッチに個々の行を追加/削除できます。ディレクトリが選択されている場合、ディレクトリを切り替えます。 |
| `` ` `` | ファイルツリービューを切り替え | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory.<br><br>The default can be changed in the config file with the key 'gui.showFileTree'. |
| `` ` `` | ファイルツリービューを切り替え | ファイル表示をフラット表示とツリー表示で切り替えます。フラット表示はすべてのファイルパスを一覧で表示し、ツリー表示はディレクトリごとにファイルをグループ化します。<br><br>デフォルトは設定ファイル内の 'gui.showFileTree' キーで変更できます。 |
| `` - `` | すべてのファイルを折りたたむ | ファイルツリー内のすべてのディレクトリを折りたたみます |
| `` = `` | すべてのファイルを展開 | ファイルツリー内のすべてのディレクトリを展開します |
| `` 0 `` | メインビューにフォーカス | |
| `` / `` | 現在のビューをテキストで検索 | |
| `` / `` | 現在のビューをテキストでフィルタリング | |
## コミット概要
@@ -131,7 +132,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | コミットハッシュをクリップボードにコピー | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | チェックアウト(ブランチの切り替え) | 選択したコミットをデタッチドヘッド(特定のブランチに属さない状態)としてチェックアウトします。 |
| `` y `` | コミット属性をクリップボードにコピー | コミット属性をクリップボードにコピーします(例:ハッシュ、URL、差分、メッセージ、作者)。 |
| `` o `` | ブラウザでコミットを開く | |
@@ -184,6 +185,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| `` u `` | 更新を確認 | |
| `` <enter> `` | 最近のリポジトリをチェックアウト | |
| `` a `` | ブランチログの表示モードを順に切り替え | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | メインビューにフォーカス | |
## セカンダリ
@@ -234,14 +236,14 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| `` d `` | 破棄 | 選択したファイルの変更を破棄するオプションを表示します。 |
| `` g `` | アップストリームへのリセットオプションを表示 | |
| `` D `` | リセット | 作業ツリーのリセットオプション(例:作業ツリーの完全破棄)を表示します。 |
| `` ` `` | ファイルツリービューを切り替え | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory.<br><br>The default can be changed in the config file with the key 'gui.showFileTree'. |
| `` ` `` | ファイルツリービューを切り替え | ファイル表示をフラット表示とツリー表示で切り替えます。フラット表示はすべてのファイルパスを一覧で表示し、ツリー表示はディレクトリごとにファイルをグループ化します。<br><br>デフォルトは設定ファイル内の 'gui.showFileTree' キーで変更できます。 |
| `` <c-t> `` | 外部差分ツールを開く(git difftool) | |
| `` M `` | View merge conflict options | View options for resolving merge conflicts. |
| `` f `` | フェッチ | リモートから変更をフェッチします。 |
| `` - `` | すべてのファイルを折りたたむ | ファイルツリー内のすべてのディレクトリを折りたたみます |
| `` = `` | すべてのファイルを展開 | ファイルツリー内のすべてのディレクトリを展開します |
| `` 0 `` | メインビューにフォーカス | |
| `` / `` | 現在のビューをテキストで検索 | |
| `` / `` | 現在のビューをテキストでフィルタリング | |
## メインパネル(ステージング)
@@ -277,6 +279,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| `` o `` | ファイルを開く | デフォルトのアプリケーションでファイルを開きます。 |
| `` e `` | ファイルを編集 | 外部エディタでファイルを開きます。 |
| `` <space> `` | パッチ内の行を切り替え | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | カスタムパッチビルダーを終了 | |
| `` / `` | 現在のビューをテキストで検索 | |
@@ -318,7 +321,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | コミットハッシュをクリップボードにコピー | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | チェックアウト(ブランチの切り替え) | 選択したコミットをデタッチドヘッド(特定のブランチに属さない状態)としてチェックアウトします。 |
| `` y `` | コミット属性をクリップボードにコピー | コミット属性をクリップボードにコピーします(例:ハッシュ、URL、差分、メッセージ、作者)。 |
| `` o `` | ブラウザでコミットを開く | |
+9 -6
View File
@@ -64,7 +64,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 커밋 해시를 클립보드에 복사 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 브라우저에서 커밋 열기 | |
@@ -106,7 +106,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 커밋 해시를 클립보드에 복사 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 브라우저에서 커밋 열기 | |
@@ -178,6 +178,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` o `` | 파일 닫기 | Open file in default application. |
| `` e `` | 파일 편집 | Open file in external editor. |
| `` <space> `` | Line(s)을 패치에 추가/삭제 | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Exit custom patch builder | |
| `` / `` | 검색 시작 | |
@@ -242,6 +243,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` u `` | 업데이트 확인 | |
| `` <enter> `` | 최근에 사용한 저장소로 전환 | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## 서브모듈
@@ -293,11 +295,12 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 커밋 해시를 클립보드에 복사 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Reset cherry-picked (copied) commits selection | |
| `` b `` | Bisect 옵션 보기 | |
| `` s `` | 스쿼시 | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | 커밋메시지 변경 | Reword the selected commit's message. |
| `` R `` | 에디터에서 커밋메시지 수정 | |
| `` d `` | 커밋 삭제 | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -336,7 +339,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` <c-o> `` | 파일명을 클립보드에 복사 | |
| `` y `` | 클립보드에 복사 | |
| `` c `` | 체크아웃 | Checkout file |
| `` d `` | Remove | Discard this commit's changes to this file |
| `` d `` | View 'discard changes' options | Discard this commit's changes to this file |
| `` o `` | 파일 닫기 | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
@@ -347,7 +350,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | 검색 시작 | |
| `` / `` | Filter the current view by text | |
## 커밋메시지
@@ -403,7 +406,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | 검색 시작 | |
| `` / `` | Filter the current view by text | |
## 확인 패널
+9 -6
View File
@@ -84,7 +84,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Start met zoeken | |
| `` / `` | Filter the current view by text | |
## Bevestigingspaneel
@@ -138,7 +138,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` <c-o> `` | Kopieer de bestandsnaam naar het klembord | |
| `` y `` | Copy to clipboard | |
| `` c `` | Uitchecken | Bestand uitchecken |
| `` d `` | Remove | Uitsluit deze commit zijn veranderingen aan dit bestand |
| `` d `` | Bekijk 'veranderingen ongedaan maken' opties | Uitsluit deze commit zijn veranderingen aan dit bestand |
| `` o `` | Open bestand | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
@@ -149,17 +149,18 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Start met zoeken | |
| `` / `` | Filter the current view by text | |
## Commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer commit hash naar klembord | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Reset cherry-picked (gekopieerde) commits selectie | |
| `` b `` | View bisect options | |
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Hernoem commit | Reword the selected commit's message. |
| `` R `` | Hernoem commit met editor | |
| `` d `` | Verwijder commit | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -244,6 +245,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` o `` | Open bestand | Open file in default application. |
| `` e `` | Verander bestand | Open file in external editor. |
| `` <space> `` | Voeg toe/verwijder lijn(en) in patch | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Sluit lijn-bij-lijn modus | |
| `` / `` | Start met zoeken | |
@@ -251,7 +253,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer commit hash naar klembord | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Uitchecken | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
@@ -351,13 +353,14 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` u `` | Check voor updates | |
| `` <enter> `` | Wissel naar een recente repo | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer commit hash naar klembord | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Uitchecken | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
+9 -6
View File
@@ -57,11 +57,12 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj hash commita do schowka | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Resetuj wybrane (cherry-picked) commity | |
| `` b `` | Zobacz opcje bisect | |
| `` s `` | Scal | Scal wybrany commit z commitami poniżej. Wiadomość wybranego commita zostanie dołączona do commita poniżej. |
| `` f `` | Poprawka | Włącz wybrany commit do commita poniżej. Podobnie do fixup, ale wiadomość wybranego commita zostanie odrzucona. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Przeformułuj | Przeformułuj wiadomość wybranego commita. |
| `` R `` | Przeformułuj za pomocą edytora | |
| `` d `` | Usuń | Usuń wybrany commit. To usunie commit z gałęzi za pomocą rebazowania. Jeśli commit wprowadza zmiany, od których zależą późniejsze commity, być może będziesz musiał rozwiązać konflikty scalania. |
@@ -123,6 +124,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` o `` | Otwórz plik | Otwórz plik w domyślnej aplikacji. |
| `` e `` | Edytuj plik | Otwórz plik w zewnętrznym edytorze. |
| `` <space> `` | Przełącz linie w łatce | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Wyjdź z budowniczego niestandardowej łatki | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
@@ -258,7 +260,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
| `` / `` | Filtruj bieżący widok po tekście | |
## Pliki commita
@@ -267,7 +269,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` <c-o> `` | Kopiuj ścieżkę do schowka | |
| `` y `` | Kopiuj do schowka | |
| `` c `` | Przełącz | Przełącz plik. Zastępuje plik w twoim drzewie roboczym wersją z wybranego commita. |
| `` d `` | Usuń | Odrzuć zmiany w tym pliku z tego commita. Uruchamia interaktywny rebase w tle, więc możesz otrzymać konflikt scalania, jeśli późniejszy commit również zmienia ten plik. |
| `` d `` | Odrzuć | Odrzuć zmiany w tym pliku z tego commita. Uruchamia interaktywny rebase w tle, więc możesz otrzymać konflikt scalania, jeśli późniejszy commit również zmienia ten plik. |
| `` o `` | Otwórz plik | Otwórz plik w domyślnej aplikacji. |
| `` e `` | Edytuj | Otwórz plik w zewnętrznym edytorze. |
| `` <c-t> `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | |
@@ -278,7 +280,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
| `` / `` | Filtruj bieżący widok po tekście | |
## Podsumowanie commita
@@ -291,7 +293,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj hash commita do schowka | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Przełącz | Przełącz wybrany commit jako odłączoną HEAD. |
| `` y `` | Kopiuj atrybut commita do schowka | Kopiuj atrybut commita do schowka (np. hash, URL, różnice, wiadomość, autor). |
| `` o `` | Otwórz commit w przeglądarce | |
@@ -330,13 +332,14 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` u `` | Sprawdź aktualizacje | |
| `` <enter> `` | Przełącz na ostatnie repozytorium | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## Sub-commity
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj hash commita do schowka | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Przełącz | Przełącz wybrany commit jako odłączoną HEAD. |
| `` y `` | Kopiuj atrybut commita do schowka | Kopiuj atrybut commita do schowka (np. hash, URL, różnice, wiadomość, autor). |
| `` o `` | Otwórz commit w przeglądarce | |
+9 -6
View File
@@ -84,7 +84,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Recolher todos os arquivos | Recolher todos os diretórios na árvore de arquivos |
| `` = `` | Expandir todos os arquivos | Expandir todos os diretórios na árvore do arquivo |
| `` 0 `` | Focus main view | |
| `` / `` | Search the current view by text | |
| `` / `` | Filter the current view by text | |
## Branches locais
@@ -142,7 +142,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` <c-o> `` | Copy path to clipboard | |
| `` y `` | Copy to clipboard | |
| `` c `` | Verificar | Arquivo de check-out. Isso substitui o arquivo em sua árvore de trabalho com a versão do commit selecionado. |
| `` d `` | Remover | Descartar as alterações desse commit para este arquivo. Isso executa uma rebase interativa em segundo plano, então você pode ter um conflito de merge se um commit posterior também alterar este arquivo. |
| `` d `` | Descartar | Descartar as alterações desse commit para este arquivo. Isso executa uma rebase interativa em segundo plano, então você pode ter um conflito de merge se um commit posterior também alterar este arquivo. |
| `` o `` | Abrir arquivo | Abrir arquivo no aplicativo padrão. |
| `` e `` | Editar | Abrir arquivo no editor externo. |
| `` <c-t> `` | Abrir ferramenta de diff externa (git difftool) | |
@@ -153,17 +153,18 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Recolher todos os arquivos | Recolher todos os diretórios na árvore de arquivos |
| `` = `` | Expandir todos os arquivos | Expandir todos os diretórios na árvore do arquivo |
| `` 0 `` | Focus main view | |
| `` / `` | Search the current view by text | |
| `` / `` | Filter the current view by text | |
## Commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
| `` b `` | View bisect options | |
| `` s `` | Squash | Squash o commit selecionado no commit abaixo dele. A mensagem do commit selecionado será anexada ao commit abaixo dele. |
| `` f `` | Fixup | Faça o commit selecionado no commit abaixo dele. Semelhante para o squash, mas a mensagem do commit selecionado será descartada. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Reword | Repetir a mensagem de submissão selecionada. |
| `` R `` | Republicar com o editor | |
| `` d `` | Descartar | Solte o commit selecionado. Isso irá remover o commit do branch através de uma rebase. Se o commit faz com que as alterações em commits posteriores dependem, você pode precisar resolver conflitos de merge. |
@@ -294,6 +295,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` o `` | Abrir arquivo | Abrir arquivo no aplicativo padrão. |
| `` e `` | Editar arquivo | Abrir arquivo no editor externo. |
| `` <space> `` | Alternar linhas no caminho | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Sair do construtor de patch personalizado | |
| `` / `` | Search the current view by text | |
@@ -301,7 +303,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Verificar | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
@@ -360,13 +362,14 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` u `` | Verificar atualização | |
| `` <enter> `` | Mudar para um repositório recente | |
| `` a `` | Mostrar/ciclo todos os logs de filiais | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Verificar | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
+9 -6
View File
@@ -138,6 +138,7 @@ _Связки клавиш_
| `` o `` | Открыть файл | Open file in default application. |
| `` e `` | Редактировать файл | Open file in external editor. |
| `` <space> `` | Добавить/удалить строку(и) для патча | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Выйти из сборщика пользовательских патчей | |
| `` / `` | Найти | |
@@ -145,7 +146,7 @@ _Связки клавиш_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать hash коммита в буфер обмена | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Открыть коммит в браузере | |
@@ -165,11 +166,12 @@ _Связки клавиш_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать hash коммита в буфер обмена | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Сбросить отобранную (скопированную \| cherry-picked) выборку коммитов | |
| `` b `` | Просмотреть параметры бинарного поиска | |
| `` s `` | Объединить коммиты (Squash) | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Объединить несколько коммитов в один отбросив сообщение коммита (Fixup) | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Перефразировать коммит | Reword the selected commit's message. |
| `` R `` | Переписать коммит с помощью редактора | |
| `` d `` | Удалить коммит | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -251,7 +253,7 @@ _Связки клавиш_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать hash коммита в буфер обмена | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Открыть коммит в браузере | |
@@ -295,7 +297,7 @@ _Связки клавиш_
| `` <c-o> `` | Скопировать название файла в буфер обмена | |
| `` y `` | Copy to clipboard | |
| `` c `` | Переключить | Переключить файл |
| `` d `` | Remove | Отменить изменения коммита в этом файле |
| `` d `` | Просмотреть параметры «отмены изменении» | Отменить изменения коммита в этом файле |
| `` o `` | Открыть файл | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
@@ -306,7 +308,7 @@ _Связки клавиш_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Найти | |
| `` / `` | Filter the current view by text | |
## Статус
@@ -317,6 +319,7 @@ _Связки клавиш_
| `` u `` | Проверить обновления | |
| `` <enter> `` | Переключиться на последний репозиторий | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## Теги
@@ -397,7 +400,7 @@ _Связки клавиш_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Найти | |
| `` / `` | Filter the current view by text | |
## Хранилище
+11 -8
View File
@@ -57,7 +57,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 复制提交哈希到剪贴板 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 检出 | 检出所选择的提交作为分离HEAD。 |
| `` y `` | 复制提交属性到剪贴板 | 复制提交属性到剪贴板(如hash、URL、diff、消息、作者)。 |
| `` o `` | 在浏览器中打开提交 | |
@@ -101,7 +101,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 复制提交哈希到剪贴板 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 检出 | 检出所选择的提交作为分离HEAD。 |
| `` y `` | 复制提交属性到剪贴板 | 复制提交属性到剪贴板(如hash、URL、diff、消息、作者)。 |
| `` o `` | 在浏览器中打开提交 | |
@@ -121,11 +121,12 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 复制提交哈希到剪贴板 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | 重置已拣选(复制)的提交 | |
| `` b `` | 查看二分查找选项 | |
| `` s `` | 压缩(Squash) | 将已选提交压缩到该提交之下。这些选定的提交的消息会附加到该提交的消息之下。 |
| `` f `` | 修正 (fixup) | 将选定的提交合并到其下面的提交中。与压缩类似,但所选提交的消息将被丢弃。 |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | 改写提交 | 重写所选提交的消息。 |
| `` R `` | 使用编辑器重命名提交 | |
| `` d `` | 删除提交 | 删除选中的提交。这将通过变基从分支中删除该提交,如果该提交修改的内容依赖于后续的提交,则需要解决合并冲突。 |
@@ -171,7 +172,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` <c-o> `` | 复制路径到剪贴板 | |
| `` y `` | 复制到剪贴板 | |
| `` c `` | 检出 | 检出文件 |
| `` d `` | 删除 | 放弃对此文件的提交变更 |
| `` d `` | 查看'放弃变更'选项 | 放弃对此文件的提交变更 |
| `` o `` | 打开文件 | 使用默认程序打开该文件 |
| `` e `` | 编辑(Edit) | 使用外部编辑器打开文件 |
| `` <c-t> `` | 使用外部差异比较工具(git difftool) | |
@@ -182,7 +183,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` - `` | 折叠全部文件 | 折叠文件树中的全部目录 |
| `` = `` | 展开全部文件 | 展开文件树中的全部目录 |
| `` 0 `` | 聚焦主视图 | |
| `` / `` | 开始搜索 | |
| `` / `` | 通过文本过滤当前视图 | |
## 文件
@@ -215,7 +216,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` - `` | 折叠全部文件 | 折叠文件树中的全部目录 |
| `` = `` | 展开全部文件 | 展开文件树中的全部目录 |
| `` 0 `` | 聚焦主视图 | |
| `` / `` | 开始搜索 | |
| `` / `` | 通过文本过滤当前视图 | |
## 本地分支
@@ -234,7 +235,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` F `` | 强制检出 | 强制检出所选分支。这将在检出所选分支之前放弃工作目录中的所有本地更改。 |
| `` d `` | 删除 | 查看本地/远程分支的删除选项 |
| `` r `` | 变基 | 将检出的分支变基到所选的分支上。 |
| `` M `` | 合并到当前检出的分支 | Merge selected branch into currently checked out branch. |
| `` M `` | 合并到当前检出的分支 | 查看将选中项合并到当前分支的选项(正常合并,压缩合并) |
| `` f `` | 从上游快进此分支 | 将当前分支直接移动到远程追踪分支的最新提交 |
| `` T `` | 创建标签 | |
| `` s `` | 排序 | |
@@ -259,6 +260,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` o `` | 打开文件 | 使用默认程序打开该文件 |
| `` e `` | 编辑文件 | 使用外部编辑器打开文件 |
| `` <space> `` | 添加/移除 行到补丁 | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | 退出逐行模式 | |
| `` / `` | 开始搜索 | |
@@ -343,6 +345,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` u `` | 检查更新 | |
| `` <enter> `` | 切换到最近的仓库 | |
| `` a `` | 显示/循环所有分支日志 | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | 聚焦主视图 | |
## 确认面板
@@ -401,7 +404,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` <c-o> `` | 复制分支名称到剪贴板 | |
| `` <space> `` | 检出 | 基于当前选中的远程分支检出一个新的本地分支,或者将远程分支作分离的HEAD。 |
| `` n `` | 新分支 | |
| `` M `` | 合并到当前检出的分支 | Merge selected branch into currently checked out branch. |
| `` M `` | 合并到当前检出的分支 | 查看将选中项合并到当前分支的选项(正常合并,压缩合并) |
| `` r `` | 变基 | 将检出的分支变基到所选的分支上。 |
| `` d `` | 删除 | 从远程删除远程分支。 |
| `` u `` | 设置为上游 | 设置为检出分支的上游 |
+7 -4
View File
@@ -72,6 +72,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| `` o `` | 開啟檔案 | 使用預設軟體開啟 |
| `` e `` | 編輯檔案 | 使用外部編輯器開啟 |
| `` <space> `` | 向 (或從) 補丁中添加/刪除行 | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | 退出自訂補丁建立器 | |
| `` / `` | 搜尋 | |
@@ -135,7 +136,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製提交 hash 到剪貼簿 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 在瀏覽器中開啟提交 | |
@@ -179,11 +180,12 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製提交 hash 到剪貼簿 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | 重設選定的揀選 (複製) 提交 | |
| `` b `` | 查看二分選項 | |
| `` s `` | 壓縮 (Squash) | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | 修復 (Fixup) | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | 改寫提交 | 改寫選中的提交訊息 |
| `` R `` | 使用編輯器改寫提交 | |
| `` d `` | 刪除提交 | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -229,7 +231,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| `` <c-o> `` | 複製檔案名稱到剪貼簿 | |
| `` y `` | 複製到剪貼簿 | |
| `` c `` | 檢出 | 檢出檔案 |
| `` d `` | Remove | Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file. |
| `` d `` | 捨棄 | Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file. |
| `` o `` | 開啟檔案 | 使用預設軟體開啟 |
| `` e `` | 編輯 | 使用外部編輯器開啟 |
| `` <c-t> `` | 開啟外部差異工具 (git difftool) | |
@@ -260,7 +262,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製提交 hash 到剪貼簿 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 在瀏覽器中開啟提交 | |
@@ -372,6 +374,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| `` u `` | 檢查更新 | |
| `` <enter> `` | 切換到最近使用的版本庫 | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## 確認面板
+2
View File
@@ -666,6 +666,7 @@ keybinding:
checkForUpdate: u
recentRepos: <enter>
allBranchesLogGraph: a
allBranchesLogGraphReverse: A
files:
commitChanges: c
commitChangesWithoutHook: w
@@ -713,6 +714,7 @@ keybinding:
renameCommitWithEditor: R
viewResetOptions: g
markCommitAsFixup: f
setFixupMessage: c
createFixupCommit: F
squashAboveCommits: S
moveDownCommit: <c-j>
+9 -6
View File
@@ -60,7 +60,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` <c-o> `` | Copy path to clipboard | |
| `` y `` | Copy to clipboard | |
| `` c `` | Checkout | Checkout file. This replaces the file in your working tree with the version from the selected commit. |
| `` d `` | Remove | Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file. |
| `` d `` | Discard | Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file. |
| `` o `` | Open file | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
@@ -71,7 +71,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Search the current view by text | |
| `` / `` | Filter the current view by text | |
## Commit summary
@@ -84,11 +84,12 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
| `` b `` | View bisect options | |
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Reword | Reword the selected commit's message. |
| `` R `` | Reword with editor | |
| `` d `` | Drop | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -159,7 +160,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Search the current view by text | |
| `` / `` | Filter the current view by text | |
## Input prompt
@@ -236,6 +237,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` o `` | Open file | Open file in default application. |
| `` e `` | Edit file | Open file in external editor. |
| `` <space> `` | Toggle lines in patch | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Exit custom patch builder | |
| `` / `` | Search the current view by text | |
@@ -273,7 +275,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Checkout | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
@@ -351,13 +353,14 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` u `` | Check for update | |
| `` <enter> `` | Switch to a recent repo | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Checkout | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
+11 -8
View File
@@ -64,11 +64,12 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | コミットハッシュをクリップボードにコピー | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | コピーされた(チェリーピックされた)コミットの選択をリセット | |
| `` b `` | bisectオプションを表示 | |
| `` s `` | スカッシュ | 選択したコミットをその下のコミットにスカッシュします。スカッシュとは複数のコミットを1つにまとめる操作です。選択したコミットのメッセージが下のコミットに追加されます。 |
| `` f `` | フィックスアップ | 選択したコミットをその下のコミットにマージします。フィックスアップはスカッシュと似ていますが、選択したコミットのメッセージは破棄され、下のコミットのメッセージのみが保持されます。 |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | メッセージ変更 | 選択したコミットのメッセージを変更します。 |
| `` R `` | エディタでメッセージ変更 | |
| `` d `` | 削除 | 選択したコミットを削除します。これはリベースを通じてブランチからコミットを削除します。コミットが後続のコミットが依存する変更を行っている場合、マージコンフリクトを解決する必要があるかもしれません。 |
@@ -107,18 +108,18 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| `` <c-o> `` | パスをクリップボードにコピー | |
| `` y `` | クリップボードにコピー | |
| `` c `` | チェックアウト(ブランチの切り替え) | ファイルをチェックアウトします。これにより、作業ツリー内のファイルが選択したコミットのバージョンに置き換えられます。 |
| `` d `` | 削除 | このコミットのこのファイルへの変更を破棄します。これはバックグラウンドで対話的なリベースを実行するため、後のコミットでもこのファイルが変更されている場合、マージコンフリクトが発生する可能性があります。 |
| `` d `` | 破棄 | このコミットのこのファイルへの変更を破棄します。これはバックグラウンドで対話的なリベースを実行するため、後のコミットでもこのファイルが変更されている場合、マージコンフリクトが発生する可能性があります。 |
| `` o `` | ファイルを開く | デフォルトのアプリケーションでファイルを開きます。 |
| `` e `` | 編集 | 外部エディタでファイルを開きます。 |
| `` <c-t> `` | 外部差分ツールを開く(git difftool) | |
| `` <space> `` | パッチに含めるファイルを切り替え | ファイルがカスタムパッチに含まれるかどうかを切り替えます。https://github.com/jesseduffield/lazygit#rebase-magic-custom-patchesを参照してください。 |
| `` a `` | すべてのファイルを切り替え | コミットのすべてのファイルをカスタムパッチに追加/削除します。https://github.com/jesseduffield/lazygit#rebase-magic-custom-patchesを参照してください。 |
| `` <enter> `` | ファイルに入る / ディレクトリの折りたたみを切り替える | ファイルが選択されている場合、そのファイルに入ってカスタムパッチに個々の行を追加/削除できます。ディレクトリが選択されている場合、ディレクトリを切り替えます。 |
| `` ` `` | ファイルツリービューを切り替え | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory.<br><br>The default can be changed in the config file with the key 'gui.showFileTree'. |
| `` ` `` | ファイルツリービューを切り替え | ファイル表示をフラット表示とツリー表示で切り替えます。フラット表示はすべてのファイルパスを一覧で表示し、ツリー表示はディレクトリごとにファイルをグループ化します。<br><br>デフォルトは設定ファイル内の 'gui.showFileTree' キーで変更できます。 |
| `` - `` | すべてのファイルを折りたたむ | ファイルツリー内のすべてのディレクトリを折りたたみます |
| `` = `` | すべてのファイルを展開 | ファイルツリー内のすべてのディレクトリを展開します |
| `` 0 `` | メインビューにフォーカス | |
| `` / `` | 現在のビューをテキストで検索 | |
| `` / `` | 現在のビューをテキストでフィルタリング | |
## コミット概要
@@ -131,7 +132,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | コミットハッシュをクリップボードにコピー | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | チェックアウト(ブランチの切り替え) | 選択したコミットをデタッチドヘッド(特定のブランチに属さない状態)としてチェックアウトします。 |
| `` y `` | コミット属性をクリップボードにコピー | コミット属性をクリップボードにコピーします(例:ハッシュ、URL、差分、メッセージ、作者)。 |
| `` o `` | ブラウザでコミットを開く | |
@@ -184,6 +185,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| `` u `` | 更新を確認 | |
| `` <enter> `` | 最近のリポジトリをチェックアウト | |
| `` a `` | ブランチログの表示モードを順に切り替え | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | メインビューにフォーカス | |
## セカンダリ
@@ -234,14 +236,14 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| `` d `` | 破棄 | 選択したファイルの変更を破棄するオプションを表示します。 |
| `` g `` | アップストリームへのリセットオプションを表示 | |
| `` D `` | リセット | 作業ツリーのリセットオプション(例:作業ツリーの完全破棄)を表示します。 |
| `` ` `` | ファイルツリービューを切り替え | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory.<br><br>The default can be changed in the config file with the key 'gui.showFileTree'. |
| `` ` `` | ファイルツリービューを切り替え | ファイル表示をフラット表示とツリー表示で切り替えます。フラット表示はすべてのファイルパスを一覧で表示し、ツリー表示はディレクトリごとにファイルをグループ化します。<br><br>デフォルトは設定ファイル内の 'gui.showFileTree' キーで変更できます。 |
| `` <c-t> `` | 外部差分ツールを開く(git difftool) | |
| `` M `` | View merge conflict options | View options for resolving merge conflicts. |
| `` f `` | フェッチ | リモートから変更をフェッチします。 |
| `` - `` | すべてのファイルを折りたたむ | ファイルツリー内のすべてのディレクトリを折りたたみます |
| `` = `` | すべてのファイルを展開 | ファイルツリー内のすべてのディレクトリを展開します |
| `` 0 `` | メインビューにフォーカス | |
| `` / `` | 現在のビューをテキストで検索 | |
| `` / `` | 現在のビューをテキストでフィルタリング | |
## メインパネル(ステージング)
@@ -277,6 +279,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| `` o `` | ファイルを開く | デフォルトのアプリケーションでファイルを開きます。 |
| `` e `` | ファイルを編集 | 外部エディタでファイルを開きます。 |
| `` <space> `` | パッチ内の行を切り替え | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | カスタムパッチビルダーを終了 | |
| `` / `` | 現在のビューをテキストで検索 | |
@@ -318,7 +321,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | コミットハッシュをクリップボードにコピー | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | チェックアウト(ブランチの切り替え) | 選択したコミットをデタッチドヘッド(特定のブランチに属さない状態)としてチェックアウトします。 |
| `` y `` | コミット属性をクリップボードにコピー | コミット属性をクリップボードにコピーします(例:ハッシュ、URL、差分、メッセージ、作者)。 |
| `` o `` | ブラウザでコミットを開く | |
+9 -6
View File
@@ -64,7 +64,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 커밋 해시를 클립보드에 복사 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 브라우저에서 커밋 열기 | |
@@ -106,7 +106,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 커밋 해시를 클립보드에 복사 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 브라우저에서 커밋 열기 | |
@@ -178,6 +178,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` o `` | 파일 닫기 | Open file in default application. |
| `` e `` | 파일 편집 | Open file in external editor. |
| `` <space> `` | Line(s)을 패치에 추가/삭제 | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Exit custom patch builder | |
| `` / `` | 검색 시작 | |
@@ -242,6 +243,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` u `` | 업데이트 확인 | |
| `` <enter> `` | 최근에 사용한 저장소로 전환 | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## 서브모듈
@@ -293,11 +295,12 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 커밋 해시를 클립보드에 복사 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Reset cherry-picked (copied) commits selection | |
| `` b `` | Bisect 옵션 보기 | |
| `` s `` | 스쿼시 | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | 커밋메시지 변경 | Reword the selected commit's message. |
| `` R `` | 에디터에서 커밋메시지 수정 | |
| `` d `` | 커밋 삭제 | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -336,7 +339,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` <c-o> `` | 파일명을 클립보드에 복사 | |
| `` y `` | 클립보드에 복사 | |
| `` c `` | 체크아웃 | Checkout file |
| `` d `` | Remove | Discard this commit's changes to this file |
| `` d `` | View 'discard changes' options | Discard this commit's changes to this file |
| `` o `` | 파일 닫기 | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
@@ -347,7 +350,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | 검색 시작 | |
| `` / `` | Filter the current view by text | |
## 커밋메시지
@@ -403,7 +406,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | 검색 시작 | |
| `` / `` | Filter the current view by text | |
## 확인 패널
+9 -6
View File
@@ -84,7 +84,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Start met zoeken | |
| `` / `` | Filter the current view by text | |
## Bevestigingspaneel
@@ -138,7 +138,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` <c-o> `` | Kopieer de bestandsnaam naar het klembord | |
| `` y `` | Copy to clipboard | |
| `` c `` | Uitchecken | Bestand uitchecken |
| `` d `` | Remove | Uitsluit deze commit zijn veranderingen aan dit bestand |
| `` d `` | Bekijk 'veranderingen ongedaan maken' opties | Uitsluit deze commit zijn veranderingen aan dit bestand |
| `` o `` | Open bestand | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
@@ -149,17 +149,18 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Start met zoeken | |
| `` / `` | Filter the current view by text | |
## Commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer commit hash naar klembord | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Reset cherry-picked (gekopieerde) commits selectie | |
| `` b `` | View bisect options | |
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Hernoem commit | Reword the selected commit's message. |
| `` R `` | Hernoem commit met editor | |
| `` d `` | Verwijder commit | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -244,6 +245,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` o `` | Open bestand | Open file in default application. |
| `` e `` | Verander bestand | Open file in external editor. |
| `` <space> `` | Voeg toe/verwijder lijn(en) in patch | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Sluit lijn-bij-lijn modus | |
| `` / `` | Start met zoeken | |
@@ -251,7 +253,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer commit hash naar klembord | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Uitchecken | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
@@ -351,13 +353,14 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` u `` | Check voor updates | |
| `` <enter> `` | Wissel naar een recente repo | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer commit hash naar klembord | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Uitchecken | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
+9 -6
View File
@@ -57,11 +57,12 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj hash commita do schowka | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Resetuj wybrane (cherry-picked) commity | |
| `` b `` | Zobacz opcje bisect | |
| `` s `` | Scal | Scal wybrany commit z commitami poniżej. Wiadomość wybranego commita zostanie dołączona do commita poniżej. |
| `` f `` | Poprawka | Włącz wybrany commit do commita poniżej. Podobnie do fixup, ale wiadomość wybranego commita zostanie odrzucona. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Przeformułuj | Przeformułuj wiadomość wybranego commita. |
| `` R `` | Przeformułuj za pomocą edytora | |
| `` d `` | Usuń | Usuń wybrany commit. To usunie commit z gałęzi za pomocą rebazowania. Jeśli commit wprowadza zmiany, od których zależą późniejsze commity, być może będziesz musiał rozwiązać konflikty scalania. |
@@ -123,6 +124,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` o `` | Otwórz plik | Otwórz plik w domyślnej aplikacji. |
| `` e `` | Edytuj plik | Otwórz plik w zewnętrznym edytorze. |
| `` <space> `` | Przełącz linie w łatce | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Wyjdź z budowniczego niestandardowej łatki | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
@@ -258,7 +260,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
| `` / `` | Filtruj bieżący widok po tekście | |
## Pliki commita
@@ -267,7 +269,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` <c-o> `` | Kopiuj ścieżkę do schowka | |
| `` y `` | Kopiuj do schowka | |
| `` c `` | Przełącz | Przełącz plik. Zastępuje plik w twoim drzewie roboczym wersją z wybranego commita. |
| `` d `` | Usuń | Odrzuć zmiany w tym pliku z tego commita. Uruchamia interaktywny rebase w tle, więc możesz otrzymać konflikt scalania, jeśli późniejszy commit również zmienia ten plik. |
| `` d `` | Odrzuć | Odrzuć zmiany w tym pliku z tego commita. Uruchamia interaktywny rebase w tle, więc możesz otrzymać konflikt scalania, jeśli późniejszy commit również zmienia ten plik. |
| `` o `` | Otwórz plik | Otwórz plik w domyślnej aplikacji. |
| `` e `` | Edytuj | Otwórz plik w zewnętrznym edytorze. |
| `` <c-t> `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | |
@@ -278,7 +280,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
| `` / `` | Filtruj bieżący widok po tekście | |
## Podsumowanie commita
@@ -291,7 +293,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj hash commita do schowka | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Przełącz | Przełącz wybrany commit jako odłączoną HEAD. |
| `` y `` | Kopiuj atrybut commita do schowka | Kopiuj atrybut commita do schowka (np. hash, URL, różnice, wiadomość, autor). |
| `` o `` | Otwórz commit w przeglądarce | |
@@ -330,13 +332,14 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` u `` | Sprawdź aktualizacje | |
| `` <enter> `` | Przełącz na ostatnie repozytorium | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## Sub-commity
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj hash commita do schowka | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Przełącz | Przełącz wybrany commit jako odłączoną HEAD. |
| `` y `` | Kopiuj atrybut commita do schowka | Kopiuj atrybut commita do schowka (np. hash, URL, różnice, wiadomość, autor). |
| `` o `` | Otwórz commit w przeglądarce | |
+9 -6
View File
@@ -84,7 +84,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Recolher todos os arquivos | Recolher todos os diretórios na árvore de arquivos |
| `` = `` | Expandir todos os arquivos | Expandir todos os diretórios na árvore do arquivo |
| `` 0 `` | Focus main view | |
| `` / `` | Search the current view by text | |
| `` / `` | Filter the current view by text | |
## Branches locais
@@ -142,7 +142,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` <c-o> `` | Copy path to clipboard | |
| `` y `` | Copy to clipboard | |
| `` c `` | Verificar | Arquivo de check-out. Isso substitui o arquivo em sua árvore de trabalho com a versão do commit selecionado. |
| `` d `` | Remover | Descartar as alterações desse commit para este arquivo. Isso executa uma rebase interativa em segundo plano, então você pode ter um conflito de merge se um commit posterior também alterar este arquivo. |
| `` d `` | Descartar | Descartar as alterações desse commit para este arquivo. Isso executa uma rebase interativa em segundo plano, então você pode ter um conflito de merge se um commit posterior também alterar este arquivo. |
| `` o `` | Abrir arquivo | Abrir arquivo no aplicativo padrão. |
| `` e `` | Editar | Abrir arquivo no editor externo. |
| `` <c-t> `` | Abrir ferramenta de diff externa (git difftool) | |
@@ -153,17 +153,18 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` - `` | Recolher todos os arquivos | Recolher todos os diretórios na árvore de arquivos |
| `` = `` | Expandir todos os arquivos | Expandir todos os diretórios na árvore do arquivo |
| `` 0 `` | Focus main view | |
| `` / `` | Search the current view by text | |
| `` / `` | Filter the current view by text | |
## Commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
| `` b `` | View bisect options | |
| `` s `` | Squash | Squash o commit selecionado no commit abaixo dele. A mensagem do commit selecionado será anexada ao commit abaixo dele. |
| `` f `` | Fixup | Faça o commit selecionado no commit abaixo dele. Semelhante para o squash, mas a mensagem do commit selecionado será descartada. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Reword | Repetir a mensagem de submissão selecionada. |
| `` R `` | Republicar com o editor | |
| `` d `` | Descartar | Solte o commit selecionado. Isso irá remover o commit do branch através de uma rebase. Se o commit faz com que as alterações em commits posteriores dependem, você pode precisar resolver conflitos de merge. |
@@ -294,6 +295,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` o `` | Abrir arquivo | Abrir arquivo no aplicativo padrão. |
| `` e `` | Editar arquivo | Abrir arquivo no editor externo. |
| `` <space> `` | Alternar linhas no caminho | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Sair do construtor de patch personalizado | |
| `` / `` | Search the current view by text | |
@@ -301,7 +303,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Verificar | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
@@ -360,13 +362,14 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` u `` | Verificar atualização | |
| `` <enter> `` | Mudar para um repositório recente | |
| `` a `` | Mostrar/ciclo todos os logs de filiais | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit hash to clipboard | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Verificar | Checkout the selected commit as a detached HEAD. |
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Open commit in browser | |
+9 -6
View File
@@ -138,6 +138,7 @@ _Связки клавиш_
| `` o `` | Открыть файл | Open file in default application. |
| `` e `` | Редактировать файл | Open file in external editor. |
| `` <space> `` | Добавить/удалить строку(и) для патча | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | Выйти из сборщика пользовательских патчей | |
| `` / `` | Найти | |
@@ -145,7 +146,7 @@ _Связки клавиш_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать hash коммита в буфер обмена | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Открыть коммит в браузере | |
@@ -165,11 +166,12 @@ _Связки клавиш_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать hash коммита в буфер обмена | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | Сбросить отобранную (скопированную \| cherry-picked) выборку коммитов | |
| `` b `` | Просмотреть параметры бинарного поиска | |
| `` s `` | Объединить коммиты (Squash) | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Объединить несколько коммитов в один отбросив сообщение коммита (Fixup) | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Перефразировать коммит | Reword the selected commit's message. |
| `` R `` | Переписать коммит с помощью редактора | |
| `` d `` | Удалить коммит | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -251,7 +253,7 @@ _Связки клавиш_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать hash коммита в буфер обмена | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Открыть коммит в браузере | |
@@ -295,7 +297,7 @@ _Связки клавиш_
| `` <c-o> `` | Скопировать название файла в буфер обмена | |
| `` y `` | Copy to clipboard | |
| `` c `` | Переключить | Переключить файл |
| `` d `` | Remove | Отменить изменения коммита в этом файле |
| `` d `` | Просмотреть параметры «отмены изменении» | Отменить изменения коммита в этом файле |
| `` o `` | Открыть файл | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
@@ -306,7 +308,7 @@ _Связки клавиш_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Найти | |
| `` / `` | Filter the current view by text | |
## Статус
@@ -317,6 +319,7 @@ _Связки клавиш_
| `` u `` | Проверить обновления | |
| `` <enter> `` | Переключиться на последний репозиторий | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## Теги
@@ -397,7 +400,7 @@ _Связки клавиш_
| `` - `` | Collapse all files | Collapse all directories in the files tree |
| `` = `` | Expand all files | Expand all directories in the file tree |
| `` 0 `` | Focus main view | |
| `` / `` | Найти | |
| `` / `` | Filter the current view by text | |
## Хранилище
+11 -8
View File
@@ -57,7 +57,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 复制提交哈希到剪贴板 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 检出 | 检出所选择的提交作为分离HEAD。 |
| `` y `` | 复制提交属性到剪贴板 | 复制提交属性到剪贴板(如hash、URL、diff、消息、作者)。 |
| `` o `` | 在浏览器中打开提交 | |
@@ -101,7 +101,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 复制提交哈希到剪贴板 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 检出 | 检出所选择的提交作为分离HEAD。 |
| `` y `` | 复制提交属性到剪贴板 | 复制提交属性到剪贴板(如hash、URL、diff、消息、作者)。 |
| `` o `` | 在浏览器中打开提交 | |
@@ -121,11 +121,12 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 复制提交哈希到剪贴板 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | 重置已拣选(复制)的提交 | |
| `` b `` | 查看二分查找选项 | |
| `` s `` | 压缩(Squash) | 将已选提交压缩到该提交之下。这些选定的提交的消息会附加到该提交的消息之下。 |
| `` f `` | 修正 (fixup) | 将选定的提交合并到其下面的提交中。与压缩类似,但所选提交的消息将被丢弃。 |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | 改写提交 | 重写所选提交的消息。 |
| `` R `` | 使用编辑器重命名提交 | |
| `` d `` | 删除提交 | 删除选中的提交。这将通过变基从分支中删除该提交,如果该提交修改的内容依赖于后续的提交,则需要解决合并冲突。 |
@@ -171,7 +172,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` <c-o> `` | 复制路径到剪贴板 | |
| `` y `` | 复制到剪贴板 | |
| `` c `` | 检出 | 检出文件 |
| `` d `` | 删除 | 放弃对此文件的提交变更 |
| `` d `` | 查看'放弃变更'选项 | 放弃对此文件的提交变更 |
| `` o `` | 打开文件 | 使用默认程序打开该文件 |
| `` e `` | 编辑(Edit) | 使用外部编辑器打开文件 |
| `` <c-t> `` | 使用外部差异比较工具(git difftool) | |
@@ -182,7 +183,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` - `` | 折叠全部文件 | 折叠文件树中的全部目录 |
| `` = `` | 展开全部文件 | 展开文件树中的全部目录 |
| `` 0 `` | 聚焦主视图 | |
| `` / `` | 开始搜索 | |
| `` / `` | 通过文本过滤当前视图 | |
## 文件
@@ -215,7 +216,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` - `` | 折叠全部文件 | 折叠文件树中的全部目录 |
| `` = `` | 展开全部文件 | 展开文件树中的全部目录 |
| `` 0 `` | 聚焦主视图 | |
| `` / `` | 开始搜索 | |
| `` / `` | 通过文本过滤当前视图 | |
## 本地分支
@@ -234,7 +235,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` F `` | 强制检出 | 强制检出所选分支。这将在检出所选分支之前放弃工作目录中的所有本地更改。 |
| `` d `` | 删除 | 查看本地/远程分支的删除选项 |
| `` r `` | 变基 | 将检出的分支变基到所选的分支上。 |
| `` M `` | 合并到当前检出的分支 | Merge selected branch into currently checked out branch. |
| `` M `` | 合并到当前检出的分支 | 查看将选中项合并到当前分支的选项(正常合并,压缩合并) |
| `` f `` | 从上游快进此分支 | 将当前分支直接移动到远程追踪分支的最新提交 |
| `` T `` | 创建标签 | |
| `` s `` | 排序 | |
@@ -259,6 +260,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` o `` | 打开文件 | 使用默认程序打开该文件 |
| `` e `` | 编辑文件 | 使用外部编辑器打开文件 |
| `` <space> `` | 添加/移除 行到补丁 | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | 退出逐行模式 | |
| `` / `` | 开始搜索 | |
@@ -343,6 +345,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` u `` | 检查更新 | |
| `` <enter> `` | 切换到最近的仓库 | |
| `` a `` | 显示/循环所有分支日志 | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | 聚焦主视图 | |
## 确认面板
@@ -401,7 +404,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` <c-o> `` | 复制分支名称到剪贴板 | |
| `` <space> `` | 检出 | 基于当前选中的远程分支检出一个新的本地分支,或者将远程分支作分离的HEAD。 |
| `` n `` | 新分支 | |
| `` M `` | 合并到当前检出的分支 | Merge selected branch into currently checked out branch. |
| `` M `` | 合并到当前检出的分支 | 查看将选中项合并到当前分支的选项(正常合并,压缩合并) |
| `` r `` | 变基 | 将检出的分支变基到所选的分支上。 |
| `` d `` | 删除 | 从远程删除远程分支。 |
| `` u `` | 设置为上游 | 设置为检出分支的上游 |
+7 -4
View File
@@ -72,6 +72,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| `` o `` | 開啟檔案 | 使用預設軟體開啟 |
| `` e `` | 編輯檔案 | 使用外部編輯器開啟 |
| `` <space> `` | 向 (或從) 補丁中添加/刪除行 | |
| `` d `` | Remove lines from commit | Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines. |
| `` <esc> `` | 退出自訂補丁建立器 | |
| `` / `` | 搜尋 | |
@@ -135,7 +136,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製提交 hash 到剪貼簿 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 在瀏覽器中開啟提交 | |
@@ -179,11 +180,12 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製提交 hash 到剪貼簿 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <c-r> `` | 重設選定的揀選 (複製) 提交 | |
| `` b `` | 查看二分選項 | |
| `` s `` | 壓縮 (Squash) | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | 修復 (Fixup) | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | 改寫提交 | 改寫選中的提交訊息 |
| `` R `` | 使用編輯器改寫提交 | |
| `` d `` | 刪除提交 | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -229,7 +231,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| `` <c-o> `` | 複製檔案名稱到剪貼簿 | |
| `` y `` | 複製到剪貼簿 | |
| `` c `` | 檢出 | 檢出檔案 |
| `` d `` | Remove | Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file. |
| `` d `` | 捨棄 | Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file. |
| `` o `` | 開啟檔案 | 使用預設軟體開啟 |
| `` e `` | 編輯 | 使用外部編輯器開啟 |
| `` <c-t> `` | 開啟外部差異工具 (git difftool) | |
@@ -260,7 +262,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製提交 hash 到剪貼簿 | |
| `` <c-o> `` | Copy abbreviated commit hash to clipboard | |
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 在瀏覽器中開啟提交 | |
@@ -372,6 +374,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| `` u `` | 檢查更新 | |
| `` <enter> `` | 切換到最近使用的版本庫 | |
| `` a `` | Show/cycle all branch logs | |
| `` A `` | Show/cycle all branch logs (reverse) | |
| `` 0 `` | Focus main view | |
## 確認面板
+6 -6
View File
@@ -12,13 +12,13 @@ require (
github.com/aybabtme/humanlog v0.4.1
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/creack/pty v1.1.11
github.com/gdamore/tcell/v2 v2.13.5
github.com/gdamore/tcell/v2 v2.13.8
github.com/go-errors/errors v1.5.1
github.com/gookit/color v1.4.2
github.com/integrii/flaggy v1.4.0
github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c
github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd
github.com/jesseduffield/gocui v0.3.1-0.20260103133810-b7e030324985
github.com/jesseduffield/gocui v0.3.1-0.20260308162933-5e45e57b5564
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
github.com/karimkhaleel/jsonschema v0.0.0-20231001195015-d933f0d94ea3
@@ -39,7 +39,7 @@ require (
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
golang.org/x/sync v0.19.0
golang.org/x/sys v0.39.0
golang.org/x/sys v0.42.0
gopkg.in/ozeidan/fuzzy-patricia.v3 v3.0.0
gopkg.in/yaml.v3 v3.0.1
)
@@ -49,7 +49,7 @@ require (
github.com/ProtonMail/go-crypto v1.1.6 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/cloudflare/circl v1.6.3 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
@@ -78,8 +78,8 @@ require (
github.com/xanzy/ssh-agent v0.3.3 // indirect
golang.org/x/crypto v0.45.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/term v0.38.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/term v0.40.0 // indirect
golang.org/x/text v0.34.0 // indirect
gopkg.in/fsnotify.v1 v1.4.7 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
+12 -12
View File
@@ -65,8 +65,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do=
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:po7NpZ/QiTKzBKyrsEAxwnTamCoh8uDk/egRpQ7siIc=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@@ -95,8 +95,8 @@ github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo=
github.com/gdamore/tcell/v2 v2.13.5 h1:YvWYCSr6gr2Ovs84dXbZLjDuOfQchhj8buOEqY52rpA=
github.com/gdamore/tcell/v2 v2.13.5/go.mod h1:+Wfe208WDdB7INEtCsNrAN6O2m+wsTPk1RAovjaILlo=
github.com/gdamore/tcell/v2 v2.13.8 h1:Mys/Kl5wfC/GcC5Cx4C2BIQH9dbnhnkPgS9/wF3RlfU=
github.com/gdamore/tcell/v2 v2.13.8/go.mod h1:+Wfe208WDdB7INEtCsNrAN6O2m+wsTPk1RAovjaILlo=
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
@@ -189,8 +189,8 @@ github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c h1:tC2Paiis
github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c/go.mod h1:F2fEBk0ddf6ixrBrJjY7phfQ3hL9rXG0uSjvwYe50bE=
github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd h1:ViKj6qth8FgcIWizn9KiACWwPemWSymx62OPN0tHT+Q=
github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd/go.mod h1:lRhCiBr6XjQrvcQVa+UYsy/99d3wMXn/a0nSQlhnhlA=
github.com/jesseduffield/gocui v0.3.1-0.20260103133810-b7e030324985 h1:qdjGSiNnlGtoi+nzyERQJvee50JpJjeQ6sEhP7jCfMo=
github.com/jesseduffield/gocui v0.3.1-0.20260103133810-b7e030324985/go.mod h1:lQCd2TvvNXVKFBowy4A7xxZbUp+1KEiGs4j0Q5Zt9gQ=
github.com/jesseduffield/gocui v0.3.1-0.20260308162933-5e45e57b5564 h1:aB/Ytu+OCEpjft/BehqbH8/PTdgLREqbCvjK1JXctoo=
github.com/jesseduffield/gocui v0.3.1-0.20260308162933-5e45e57b5564/go.mod h1:lQCd2TvvNXVKFBowy4A7xxZbUp+1KEiGs4j0Q5Zt9gQ=
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5/go.mod h1:qxN4mHOAyeIDLP7IK7defgPClM/z1Kze8VVQiaEjzsQ=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
@@ -458,13 +458,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -475,8 +475,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+1
View File
@@ -199,6 +199,7 @@ func (self *ChangeTodoActionsInstruction) run(common *common.Common) error {
return utils.TodoChange{
Hash: c.Hash,
NewAction: c.NewAction,
Flag: c.Flag,
}
})
+1
View File
@@ -14,6 +14,7 @@ import (
type ChangeTodoAction struct {
Hash string
NewAction todo.TodoCommand
Flag string
}
func handleInteractiveRebase(common *common.Common, f func(path string) error) error {
+1 -1
View File
@@ -154,7 +154,7 @@ func (self *BisectCommands) IsDone() (bool, []string, error) {
candidates := []string{}
cmdArgs := NewGitCmd("rev-list").Arg(newHash).ToArgv()
err := self.cmd.New(cmdArgs).RunAndProcessLines(func(line string) (bool, error) {
err := self.cmd.New(cmdArgs).DontLog().RunAndProcessLines(func(line string) (bool, error) {
hash := strings.TrimSpace(line)
if status, ok := info.statusMap[hash]; ok {
+6
View File
@@ -317,6 +317,12 @@ func (self *BranchCommands) RotateAllBranchesLogIdx() {
self.allBranchesLogCmdIndex = (i + 1) % n
}
func (self *BranchCommands) RotateAllBranchesLogIdxBackward() {
n := len(self.allBranchesLogCandidates())
i := self.allBranchesLogCmdIndex
self.allBranchesLogCmdIndex = (i - 1 + n) % n
}
func (self *BranchCommands) GetAllBranchesLogIdxAndCount() (int, int) {
n := len(self.allBranchesLogCandidates())
i := self.allBranchesLogCmdIndex
+6 -4
View File
@@ -325,6 +325,7 @@ func (self *CommitLoader) getHydratedTodoCommits(hashPool *utils.StringPool, tod
hydratedCommits = append(hydratedCommits, rebasingCommit)
} else if commit := findFullCommit(rebasingCommit.Hash()); commit != nil {
commit.Action = rebasingCommit.Action
commit.ActionFlag = rebasingCommit.ActionFlag
commit.Status = rebasingCommit.Status
hydratedCommits = append(hydratedCommits, commit)
}
@@ -371,10 +372,11 @@ func (self *CommitLoader) getRebasingCommits(hashPool *utils.StringPool, addConf
continue
}
commits = utils.Prepend(commits, models.NewCommit(hashPool, models.NewCommitOpts{
Hash: t.Commit,
Name: t.Msg,
Status: models.StatusRebasing,
Action: t.Command,
Hash: t.Commit,
Name: t.Msg,
Status: models.StatusRebasing,
Action: t.Command,
ActionFlag: t.Flag,
}))
}
+4 -2
View File
@@ -139,7 +139,7 @@ func (self *RebaseCommands) MoveCommitsUp(commits []*models.Commit, startIdx int
}).Run()
}
func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx int, endIdx int, action todo.TodoCommand) error {
func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx int, endIdx int, action todo.TodoCommand, flag string) error {
baseIndex := endIdx + 1
if action == todo.Squash || action == todo.Fixup {
baseIndex++
@@ -151,6 +151,7 @@ func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx
return daemon.ChangeTodoAction{
Hash: commit.Hash(),
NewAction: action,
Flag: flag,
}, !commit.IsMerge()
})
@@ -334,11 +335,12 @@ func todoFromCommit(commit *models.Commit) utils.Todo {
}
// Sets the action for the given commits in the git-rebase-todo file
func (self *RebaseCommands) EditRebaseTodo(commits []*models.Commit, action todo.TodoCommand) error {
func (self *RebaseCommands) EditRebaseTodo(commits []*models.Commit, action todo.TodoCommand, flag string) error {
commitsWithAction := lo.Map(commits, func(commit *models.Commit, _ int) utils.TodoChange {
return utils.TodoChange{
Hash: commit.Hash(),
NewAction: action,
Flag: flag,
}
})
+1 -1
View File
@@ -85,6 +85,6 @@ func (self *RemoteCommands) GetRemoteURL(remoteName string) (string, error) {
Arg("--get-url", remoteName).
ToArgv()
url, err := self.cmd.New(cmdArgs).RunWithOutput()
url, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
return strings.TrimSpace(url), err
}
+21 -9
View File
@@ -233,10 +233,10 @@ func (self *WorkingTreeCommands) DiscardUnstagedFileChanges(file *models.File) e
return self.cmd.New(cmdArgs).Run()
}
// Escapes special characters in a filename for gitignore and exclude files
// Escapes special characters in a filename for gitignore and exclude files, and prepends `/`
func escapeFilename(filename string) string {
re := regexp.MustCompile(`^[!#]|[\[\]*]`)
return re.ReplaceAllString(filename, `\${0}`)
return "/" + re.ReplaceAllString(filename, `\${0}`)
}
// Ignore adds a file to the gitignore for the repo
@@ -246,18 +246,25 @@ func (self *WorkingTreeCommands) Ignore(filename string) error {
// Exclude adds a file to the .git/info/exclude for the repo
func (self *WorkingTreeCommands) Exclude(filename string) error {
excludeFile := filepath.Join(self.repoPaths.repoGitDirPath, "info", "exclude")
infoDir := filepath.Join(self.repoPaths.repoGitDirPath, "info")
if err := os.MkdirAll(infoDir, 0o755); err != nil {
return err
}
excludeFile := filepath.Join(infoDir, "exclude")
return self.os.AppendLineToFile(excludeFile, escapeFilename(filename))
}
// WorktreeFileDiff returns the diff of a file
func (self *WorkingTreeCommands) WorktreeFileDiff(file *models.File, plain bool, cached bool) string {
// for now we assume an error means the file was deleted
s, _ := self.WorktreeFileDiffCmdObj(file, plain, cached).RunWithOutput()
s, _ := self.WorktreeFileDiffCmdObj(file, plain, cached, nil).RunWithOutput()
return s
}
func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cached bool) *oscommands.CmdObj {
// WorktreeFileDiffCmdObj returns a command object for diffing a file or directory
// in the working tree. When pathOverrides is non-empty, those paths are used instead of
// the node's path (used to diff only filtered/visible files within a directory).
func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cached bool, pathOverrides []string) *oscommands.CmdObj {
colorArg := self.pagerConfig.GetColorArg()
if plain {
colorArg = "never"
@@ -270,6 +277,11 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain
useExtDiff := extDiffCmd != "" && !plain
useExtDiffGitConfig := self.pagerConfig.GetUseExternalDiffGitConfig() && !plain
paths := pathOverrides
if len(paths) == 0 {
paths = []string{node.GetPath()}
}
cmdArgs := NewGitCmd("diff").
ConfigIf(useExtDiff, "diff.external="+extDiffCmd).
ArgIfElse(useExtDiff || useExtDiffGitConfig, "--ext-diff", "--no-ext-diff").
@@ -282,7 +294,7 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain
ArgIf(noIndex, "--no-index").
Arg("--").
ArgIf(noIndex, "/dev/null").
Arg(node.GetPath()).
Arg(paths...).
ArgIf(prevPath != "", prevPath).
Dir(self.repoPaths.worktreePath).
ToArgv()
@@ -293,10 +305,10 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain
// ShowFileDiff get the diff of specified from and to. Typically this will be used for a single commit so it'll be 123abc^..123abc
// but when we're in diff mode it could be any 'from' to any 'to'. The reverse flag is also here thanks to diff mode.
func (self *WorkingTreeCommands) ShowFileDiff(from string, to string, reverse bool, fileName string, plain bool) (string, error) {
return self.ShowFileDiffCmdObj(from, to, reverse, fileName, plain).RunWithOutput()
return self.ShowFileDiffCmdObj(from, to, reverse, []string{fileName}, plain).RunWithOutput()
}
func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileName string, plain bool) *oscommands.CmdObj {
func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileNames []string, plain bool) *oscommands.CmdObj {
contextSize := self.UserConfig().Git.DiffContextSize
colorArg := self.pagerConfig.GetColorArg()
@@ -321,7 +333,7 @@ func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reve
ArgIf(reverse, "-R").
ArgIf(!plain && self.UserConfig().Git.IgnoreWhitespaceInDiffView, "--ignore-all-space").
Arg("--").
Arg(fileName).
Arg(fileNames...).
Dir(self.repoPaths.worktreePath).
ToArgv()
@@ -67,6 +67,8 @@ func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
// we can parallelize the calls to git rev-parse
GitDir: "",
}
} else if strings.HasPrefix(splitLine, "HEAD ") {
current.Head = strings.SplitN(splitLine, " ", 2)[1]
} else if strings.HasPrefix(splitLine, "branch ") {
branch := strings.SplitN(splitLine, " ", 2)[1]
current.Branch = strings.TrimPrefix(branch, "refs/heads/")
@@ -46,6 +46,7 @@ branch refs/heads/mybranch
IsPathMissing: false,
GitDir: "/path/to/repo/.git",
Branch: "mybranch",
Head: "d85cc9d281fa6ae1665c68365fc70e75e82a042d",
Name: "repo",
},
},
@@ -86,6 +87,7 @@ branch refs/heads/mybranch-worktree
IsPathMissing: false,
GitDir: "/path/to/repo/.git",
Branch: "mybranch",
Head: "d85cc9d281fa6ae1665c68365fc70e75e82a042d",
Name: "repo",
},
{
@@ -95,6 +97,7 @@ branch refs/heads/mybranch-worktree
IsPathMissing: false,
GitDir: "/path/to/repo/.git/worktrees/repo-worktree",
Branch: "mybranch-worktree",
Head: "775955775e79b8f5b4c4b56f82fbf657e2d5e4de",
Name: "repo-worktree",
},
},
@@ -124,6 +127,7 @@ branch refs/heads/missingbranch
IsPathMissing: true,
GitDir: "",
Branch: "missingbranch",
Head: "775955775e79b8f5b4c4b56f82fbf657e2d5e4de",
Name: "worktree",
},
},
@@ -164,6 +168,7 @@ branch refs/heads/mybranch-worktree
IsPathMissing: false,
GitDir: "/path/to/repo/.git/worktrees/repo-worktree",
Branch: "mybranch-worktree",
Head: "775955775e79b8f5b4c4b56f82fbf657e2d5e4de",
Name: "repo-worktree",
},
{
@@ -173,11 +178,62 @@ branch refs/heads/mybranch-worktree
IsPathMissing: false,
GitDir: "/path/to/repo/.git",
Branch: "mybranch",
Head: "d85cc9d281fa6ae1665c68365fc70e75e82a042d",
Name: "repo",
},
},
expectedErr: "",
},
{
testName: "Detached HEAD worktree",
repoPaths: &RepoPaths{
repoPath: "/path/to/repo",
worktreePath: "/path/to/repo",
},
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn) {
runner.ExpectGitArgs([]string{"worktree", "list", "--porcelain"},
`worktree /path/to/repo
HEAD d85cc9d281fa6ae1665c68365fc70e75e82a042d
branch refs/heads/mybranch
worktree /path/to/repo-worktree
HEAD 775955775e79b8f5b4c4b56f82fbf657e2d5e4de
detached
`,
nil)
gitArgsMainWorktree := append(append([]string{"-C", "/path/to/repo"}, getRevParseArgs()...), "--absolute-git-dir")
runner.ExpectGitArgs(gitArgsMainWorktree, "/path/to/repo/.git", nil)
gitArgsLinkedWorktree := append(append([]string{"-C", "/path/to/repo-worktree"}, getRevParseArgs()...), "--absolute-git-dir")
runner.ExpectGitArgs(gitArgsLinkedWorktree, "/path/to/repo/.git/worktrees/repo-worktree", nil)
_ = fs.MkdirAll("/path/to/repo/.git", 0o755)
_ = fs.MkdirAll("/path/to/repo-worktree", 0o755)
_ = fs.MkdirAll("/path/to/repo/.git/worktrees/repo-worktree", 0o755)
},
expectedWorktrees: []*models.Worktree{
{
IsMain: true,
IsCurrent: true,
Path: "/path/to/repo",
IsPathMissing: false,
GitDir: "/path/to/repo/.git",
Branch: "mybranch",
Head: "d85cc9d281fa6ae1665c68365fc70e75e82a042d",
Name: "repo",
},
{
IsMain: false,
IsCurrent: false,
Path: "/path/to/repo-worktree",
IsPathMissing: false,
GitDir: "/path/to/repo/.git/worktrees/repo-worktree",
Branch: "",
Head: "775955775e79b8f5b4c4b56f82fbf657e2d5e4de",
Name: "repo-worktree",
},
},
expectedErr: "",
},
}
for _, s := range scenarios {
+3
View File
@@ -60,6 +60,7 @@ type Commit struct {
Status CommitStatus
Action todo.TodoCommand
ActionFlag string // e.g. "-C" for fixup -C
Divergence Divergence // set to DivergenceNone unless we are showing the divergence view
}
@@ -68,6 +69,7 @@ type NewCommitOpts struct {
Name string
Status CommitStatus
Action todo.TodoCommand
ActionFlag string
Tags []string
ExtraInfo string
AuthorName string
@@ -83,6 +85,7 @@ func NewCommit(hashPool *utils.StringPool, opts NewCommitOpts) *Commit {
Name: opts.Name,
Status: opts.Status,
Action: opts.Action,
ActionFlag: opts.ActionFlag,
Tags: opts.Tags,
ExtraInfo: opts.ExtraInfo,
AuthorName: opts.AuthorName,
+3
View File
@@ -19,6 +19,9 @@ type Worktree struct {
// * the worktree is mid-rebase on the branch
// * the worktree is mid-bisect on the branch
Branch string
// The HEAD sha of the worktree. Always populated (even when Branch is set).
// Used for display when Branch is empty (detached HEAD state).
Head string
// based on the path, but uniquified. Not the same name that git uses in the worktrees/ folder (no good reason for this,
// I just prefer my naming convention better)
Name string
+4
View File
@@ -60,6 +60,10 @@ func getPreset(shell string, osConfig *OSConfig, guessDefaultEditor func() strin
nvimRemoteEditTemplate = `begin; if test -z "$NVIM"; nvim -- {{filename}}; else; nvim --server "$NVIM" --remote-send "q"; nvim --server "$NVIM" --remote-tab {{filename}}; end; end`
nvimRemoteEditAtLineTemplate = `begin; if test -z "$NVIM"; nvim +{{line}} -- {{filename}}; else; nvim --server "$NVIM" --remote-send "q"; nvim --server "$NVIM" --remote-tab {{filename}}; nvim --server "$NVIM" --remote-send ":{{line}}<CR>"; end; end`
nvimRemoteOpenDirInEditorTemplate = `begin; if test -z "$NVIM"; nvim -- {{dir}}; else; nvim --server "$NVIM" --remote-send "q"; nvim --server "$NVIM" --remote-tab {{dir}}; end; end`
} else if strings.HasSuffix(shell, "nu") || strings.HasSuffix(shell, "nushell") || os.Getenv("NU_VERSION") != "" {
nvimRemoteEditTemplate = `if ($env | get -i NVIM | is-empty) { nvim -- {{filename}} } else { nvim --server $env.NVIM --remote-send "q"; nvim --server $env.NVIM --remote-tab {{filename}} }`
nvimRemoteEditAtLineTemplate = `if ($env | get -i NVIM | is-empty) { nvim +{{line}} -- {{filename}} } else { nvim --server $env.NVIM --remote-send "q"; nvim --server $env.NVIM --remote-tab {{filename}}; nvim --server $env.NVIM --remote-send ":{{line}}<CR>" }`
nvimRemoteOpenDirInEditorTemplate = `if ($env | get -i NVIM | is-empty) { nvim -- {{dir}} } else { nvim --server $env.NVIM --remote-send "q"; nvim --server $env.NVIM --remote-tab {{dir}} }`
} else {
nvimRemoteEditTemplate = `[ -z "$NVIM" ] && (nvim -- {{filename}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{filename}})`
nvimRemoteEditAtLineTemplate = `[ -z "$NVIM" ] && (nvim +{{line}} -- {{filename}}) || (nvim --server "$NVIM" --remote-send "q" && nvim --server "$NVIM" --remote-tab {{filename}} && nvim --server "$NVIM" --remote-send ":{{line}}<CR>")`
+10 -6
View File
@@ -493,9 +493,10 @@ type KeybindingUniversalConfig struct {
}
type KeybindingStatusConfig struct {
CheckForUpdate string `yaml:"checkForUpdate"`
RecentRepos string `yaml:"recentRepos"`
AllBranchesLogGraph string `yaml:"allBranchesLogGraph"`
CheckForUpdate string `yaml:"checkForUpdate"`
RecentRepos string `yaml:"recentRepos"`
AllBranchesLogGraph string `yaml:"allBranchesLogGraph"`
AllBranchesLogGraphReverse string `yaml:"allBranchesLogGraphReverse"`
}
type KeybindingFilesConfig struct {
@@ -551,6 +552,7 @@ type KeybindingCommitsConfig struct {
RenameCommitWithEditor string `yaml:"renameCommitWithEditor"`
ViewResetOptions string `yaml:"viewResetOptions"`
MarkCommitAsFixup string `yaml:"markCommitAsFixup"`
SetFixupMessage string `yaml:"setFixupMessage"`
CreateFixupCommit string `yaml:"createFixupCommit"`
SquashAboveCommits string `yaml:"squashAboveCommits"`
MoveDownCommit string `yaml:"moveDownCommit"`
@@ -954,9 +956,10 @@ func GetDefaultConfig() *UserConfig {
OpenDiffTool: "<c-t>",
},
Status: KeybindingStatusConfig{
CheckForUpdate: "u",
RecentRepos: "<enter>",
AllBranchesLogGraph: "a",
CheckForUpdate: "u",
RecentRepos: "<enter>",
AllBranchesLogGraph: "a",
AllBranchesLogGraphReverse: "A",
},
Files: KeybindingFilesConfig{
CommitChanges: "c",
@@ -1008,6 +1011,7 @@ func GetDefaultConfig() *UserConfig {
RenameCommitWithEditor: "R",
ViewResetOptions: "g",
MarkCommitAsFixup: "f",
SetFixupMessage: "c",
CreateFixupCommit: "F",
SquashAboveCommits: "S",
MoveDownCommit: "<c-j>",
+16 -12
View File
@@ -52,7 +52,7 @@ func (self *BackgroundRoutineMgr) startBackgroundRoutines() {
}
if self.gui.Config.GetDebug() {
self.goEvery(time.Second*time.Duration(10), self.gui.stopChan, func() error {
self.goEvery(time.Second*time.Duration(10), self.gui.stopChan, func(_ bool) error {
formatBytes := func(b uint64) string {
const unit = 1000
if b < unit {
@@ -78,7 +78,7 @@ func (self *BackgroundRoutineMgr) startBackgroundRoutines() {
func (self *BackgroundRoutineMgr) startBackgroundFetch() {
self.gui.waitForIntro.Wait()
fetch := func() error {
fetch := func(firstTimeOrRetriggered bool) error {
// Do this on the UI thread so that we don't have to deal with synchronization around the
// access of the repo state.
self.gui.onUIThread(func() error {
@@ -89,14 +89,18 @@ func (self *BackgroundRoutineMgr) startBackgroundFetch() {
return nil
})
return self.gui.helpers.AppStatus.WithWaitingStatusImpl(self.gui.Tr.FetchingStatus, func(gocui.Task) error {
return self.backgroundFetch()
}, nil)
if self.gui.UserConfig().Gui.ShowBottomLine || firstTimeOrRetriggered {
return self.gui.helpers.AppStatus.WithWaitingStatusImpl(self.gui.Tr.FetchingStatus, func(gocui.Task) error {
return self.backgroundFetch()
}, nil)
}
return self.backgroundFetch()
}
// We want an immediate fetch at startup, and since goEvery starts by
// waiting for the interval, we need to trigger one manually first
_ = fetch()
_ = fetch(true)
userConfig := self.gui.UserConfig()
self.triggerFetch = self.goEvery(userConfig.Refresher.FetchIntervalDuration(), self.gui.stopChan, fetch)
@@ -106,25 +110,25 @@ func (self *BackgroundRoutineMgr) startBackgroundFilesRefresh() {
self.gui.waitForIntro.Wait()
userConfig := self.gui.UserConfig()
self.goEvery(userConfig.Refresher.RefreshIntervalDuration(), self.gui.stopChan, func() error {
self.goEvery(userConfig.Refresher.RefreshIntervalDuration(), self.gui.stopChan, func(_ bool) error {
self.gui.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES}})
return nil
})
}
// returns a channel that can be used to trigger the callback immediately
func (self *BackgroundRoutineMgr) goEvery(interval time.Duration, stop chan struct{}, function func() error) chan struct{} {
func (self *BackgroundRoutineMgr) goEvery(interval time.Duration, stop chan struct{}, function func(bool) error) chan struct{} {
done := make(chan struct{})
retrigger := make(chan struct{})
go utils.Safe(func() {
ticker := time.NewTicker(interval)
defer ticker.Stop()
doit := func() {
doit := func(retriggered bool) {
if self.pauseBackgroundRefreshes {
return
}
self.gui.c.OnWorker(func(gocui.Task) error {
_ = function()
_ = function(retriggered)
done <- struct{}{}
return nil
})
@@ -136,10 +140,10 @@ func (self *BackgroundRoutineMgr) goEvery(interval time.Duration, stop chan stru
for {
select {
case <-ticker.C:
doit()
doit(false)
case <-retrigger:
ticker.Reset(interval)
doit()
doit(true)
case <-stop:
return
}
+1 -10
View File
@@ -3,7 +3,6 @@ package context
import (
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
@@ -17,13 +16,12 @@ type CommitFilesContext struct {
*filetree.CommitFileTreeViewModel
*ListContextTrait
*DynamicTitleBuilder
*SearchTrait
}
var (
_ types.IListContext = (*CommitFilesContext)(nil)
_ types.DiffableContext = (*CommitFilesContext)(nil)
_ types.ISearchableContext = (*CommitFilesContext)(nil)
_ types.IFilterableContext = (*CommitFilesContext)(nil)
)
func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
@@ -48,7 +46,6 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
ctx := &CommitFilesContext{
CommitFileTreeViewModel: viewModel,
DynamicTitleBuilder: NewDynamicTitleBuilder(c.Tr.CommitFilesDynamicTitle),
SearchTrait: NewSearchTrait(c),
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(
NewBaseContext(NewBaseContextOpts{
@@ -68,8 +65,6 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
},
}
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(ctx.OnSearchSelect))
return ctx
}
@@ -92,10 +87,6 @@ func (self *CommitFilesContext) GetFromAndToForDiff() (string, string) {
return ref.ParentRefName(), ref.RefName()
}
func (self *CommitFilesContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition {
return nil
}
func (self *CommitFilesContext) ReInit(ref models.Ref, refRange *types.RefRange) {
self.SetRef(ref)
self.SetRefRange(refRange)
+14 -2
View File
@@ -24,6 +24,10 @@ type ListContextTrait struct {
// If renderOnlyVisibleLines is true, needRerenderVisibleLines indicates whether we need to
// rerender the visible lines e.g. because the scroll position changed
needRerenderVisibleLines bool
// true if we're inside the OnSearchSelect call; in that case we don't want to update the search
// result index.
inOnSearchSelect bool
}
func (self *ListContextTrait) IsListContext() {}
@@ -31,6 +35,10 @@ func (self *ListContextTrait) IsListContext() {}
func (self *ListContextTrait) FocusLine(scrollIntoView bool) {
self.Context.FocusLine(scrollIntoView)
// Need to capture this in a local variable because by the time the AfterLayout function runs,
// the field will have been reset to false already
inOnSearchSelect := self.inOnSearchSelect
// Doing this at the end of the layout function because we need the view to be
// resized before we focus the line, otherwise if we're in accordion mode
// the view could be squashed and won't know how to adjust the cursor/origin.
@@ -40,6 +48,9 @@ func (self *ListContextTrait) FocusLine(scrollIntoView bool) {
self.GetViewTrait().FocusPoint(
self.ModelIndexToViewIndex(self.list.GetSelectedLineIdx()), scrollIntoView)
if !inOnSearchSelect {
self.GetView().SetNearestSearchPosition()
}
selectRangeIndex, isSelectingRange := self.list.GetRangeStartIdx()
if isSelectingRange {
@@ -117,10 +128,11 @@ func (self *ListContextTrait) HandleRender() {
self.setFooter()
}
func (self *ListContextTrait) OnSearchSelect(selectedLineIdx int) error {
func (self *ListContextTrait) OnSearchSelect(selectedLineIdx int) {
self.GetList().SetSelection(self.ViewIndexToModelIndex(selectedLineIdx))
self.inOnSearchSelect = true
self.HandleFocus(types.OnFocusOpts{})
return nil
self.inOnSearchSelect = false
}
func (self *ListContextTrait) IsItemVisible(item types.HasUrn) bool {
+2 -1
View File
@@ -134,7 +134,8 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
},
}
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(ctx.OnSearchSelect))
ctx.GetView().SetRenderSearchStatus(ctx.SearchTrait.RenderSearchStatus)
ctx.GetView().SetOnSelectItem(ctx.OnSearchSelect)
return ctx
}
+2 -1
View File
@@ -31,7 +31,8 @@ func NewMainContext(
SearchTrait: NewSearchTrait(c),
}
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(int) error { return nil }))
ctx.GetView().SetRenderSearchStatus(ctx.SearchTrait.RenderSearchStatus)
ctx.GetView().SetOnSelectItem(func(int) {})
return ctx
}
+16 -8
View File
@@ -16,6 +16,10 @@ type PatchExplorerContext struct {
getIncludedLineIndices func() []int
c *ContextCommon
mutex deadlock.Mutex
// true if we're inside the OnSelectItem callback; in that case we don't want to update the
// search result index.
inOnSelectItemCallback bool
}
var (
@@ -49,14 +53,14 @@ func NewPatchExplorerContext(
SearchTrait: NewSearchTrait(c),
}
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(
func(selectedLineIdx int) error {
ctx.GetMutex().Lock()
defer ctx.GetMutex().Unlock()
ctx.NavigateTo(selectedLineIdx)
return nil
}),
)
ctx.GetView().SetRenderSearchStatus(ctx.SearchTrait.RenderSearchStatus)
ctx.GetView().SetOnSelectItem(func(selectedLineIdx int) {
ctx.GetMutex().Lock()
defer ctx.GetMutex().Unlock()
ctx.inOnSelectItemCallback = true
ctx.NavigateTo(selectedLineIdx)
ctx.inOnSelectItemCallback = false
})
ctx.SetHandleRenderFunc(ctx.OnViewWidthChanged)
@@ -113,6 +117,10 @@ func (self *PatchExplorerContext) FocusSelection() {
// As far as the view is concerned, we are always selecting a range
view.SetRangeSelectStart(startIdx)
view.SetCursorY(endIdx - newOriginY)
if !self.inOnSelectItemCallback {
view.SetNearestSearchPosition()
}
}
func (self *PatchExplorerContext) GetContentToRender() string {
-14
View File
@@ -36,20 +36,6 @@ func (self *SearchTrait) ClearSearchString() {
// used for type switch
func (self *SearchTrait) IsSearchableContext() {}
func (self *SearchTrait) onSelectItemWrapper(innerFunc func(int) error) func(int, int, int) error {
return func(selectedLineIdx int, index int, total int) error {
self.RenderSearchStatus(index, total)
if total != 0 {
if err := innerFunc(selectedLineIdx); err != nil {
return err
}
}
return nil
}
}
func (self *SearchTrait) RenderSearchStatus(index int, total int) {
keybindingConfig := self.c.UserConfig().Keybinding
+2 -1
View File
@@ -134,7 +134,8 @@ func NewSubCommitsContext(
},
}
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(ctx.OnSearchSelect))
ctx.GetView().SetRenderSearchStatus(ctx.SearchTrait.RenderSearchStatus)
ctx.GetView().SetOnSelectItem(ctx.OnSearchSelect)
return ctx
}
+1 -10
View File
@@ -1,7 +1,6 @@
package context
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
@@ -13,12 +12,11 @@ import (
type WorkingTreeContext struct {
*filetree.FileTreeViewModel
*ListContextTrait
*SearchTrait
}
var (
_ types.IListContext = (*WorkingTreeContext)(nil)
_ types.ISearchableContext = (*WorkingTreeContext)(nil)
_ types.IFilterableContext = (*WorkingTreeContext)(nil)
)
func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
@@ -38,7 +36,6 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
}
ctx := &WorkingTreeContext{
SearchTrait: NewSearchTrait(c),
FileTreeViewModel: viewModel,
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
@@ -56,11 +53,5 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
},
}
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(ctx.OnSearchSelect))
return ctx
}
func (self *WorkingTreeContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition {
return nil
}
@@ -1,7 +1,6 @@
package controllers
import (
"errors"
"fmt"
"strings"
@@ -130,14 +129,6 @@ func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
GetDisabledReason: self.require(self.canSelectCommitsOfCurrentBranch),
Description: self.c.Tr.SelectCommitsOfCurrentBranch,
},
// Putting this at the bottom of the list so that it has the lowest priority,
// meaning that if the user has configured another keybinding to the same key
// then that will take precedence.
{
// Hardcoding this key because it's not configurable
Key: opts.GetKey("c"),
Handler: self.handleOldCherryPickKey,
},
}
return bindings
@@ -382,16 +373,6 @@ func (self *BasicCommitsController) canCopyCommits(selectedCommits []*models.Com
return nil
}
func (self *BasicCommitsController) handleOldCherryPickKey() error {
msg := utils.ResolvePlaceholderString(self.c.Tr.OldCherryPickKeyWarning,
map[string]string{
"copy": keybindings.Label(self.c.UserConfig().Keybinding.Commits.CherryPickCopy),
"paste": keybindings.Label(self.c.UserConfig().Keybinding.Commits.PasteCommits),
})
return errors.New(msg)
}
func (self *BasicCommitsController) openDiffTool(commit *models.Commit) error {
to := commit.RefName()
from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(commit.ParentRefName())
+50 -13
View File
@@ -62,8 +62,8 @@ func (self *CommitFilesController) GetKeybindings(opts types.KeybindingsOpts) []
{
Key: opts.GetKey(opts.Config.Universal.Remove),
Handler: self.withItems(self.discard),
GetDisabledReason: self.require(self.itemsSelected()),
Description: self.c.Tr.Remove,
GetDisabledReason: self.require(self.itemsSelected(self.canDiscardFileChanges)),
Description: self.c.Tr.Discard,
Tooltip: self.c.Tr.DiscardOldFileChangeTooltip,
DisplayOnScreen: true,
},
@@ -152,7 +152,8 @@ func (self *CommitFilesController) GetOnRenderToMain() func() {
from, to := self.context().GetFromAndToForDiff()
from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from)
cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, node.GetPath(), false)
paths := self.pathsForDiff(node)
cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, paths, false)
task := types.NewRunPtyTask(cmdObj.GetCmd())
self.c.RenderToMainViews(types.RefreshMainOpts{
@@ -171,7 +172,7 @@ func (self *CommitFilesController) copyDiffToClipboard(path string, toastMessage
from, to := self.context().GetFromAndToForDiff()
from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from)
cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, path, true)
cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, []string{path}, true)
diff, err := cmdObj.RunWithOutput()
if err != nil {
return err
@@ -301,18 +302,13 @@ func (self *CommitFilesController) checkout(node *filetree.CommitFileNode) error
}
func (self *CommitFilesController) discard(selectedNodes []*filetree.CommitFileNode) error {
parentContext := self.c.Context().Current().GetParentContext()
if parentContext == nil || parentContext.GetKey() != context.LOCAL_COMMITS_CONTEXT_KEY {
return errors.New(self.c.Tr.CanOnlyDiscardFromLocalCommits)
}
if ok, err := self.c.Helpers().PatchBuilding.ValidateNormalWorkingTreeState(); !ok {
return err
}
prompt := lo.Ternary(self.c.Git().Patch.PatchBuilder.Active(),
self.c.Tr.DiscardFileChangesPromptResetPatch,
self.c.Tr.DiscardFileChangesPrompt)
self.c.Confirm(types.ConfirmOpts{
Title: self.c.Tr.DiscardFileChangesTitle,
Prompt: self.c.Tr.DiscardFileChangesPrompt,
Prompt: prompt,
HandleConfirm: func() error {
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error {
var filePaths []string
@@ -347,6 +343,32 @@ func (self *CommitFilesController) discard(selectedNodes []*filetree.CommitFileN
return nil
}
func (self *CommitFilesController) canDiscardFileChanges(nodes []*filetree.CommitFileNode) *types.DisabledReason {
parentContext := self.c.Context().Current().GetParentContext()
if parentContext == nil || parentContext.GetKey() != context.LOCAL_COMMITS_CONTEXT_KEY {
return &types.DisabledReason{
Text: self.c.Tr.CanOnlyDiscardFromLocalCommits,
ShowErrorInPanel: true,
}
}
if self.c.Contexts().LocalCommits.AreMultipleItemsSelected() {
return &types.DisabledReason{
Text: self.c.Tr.CannotDiscardFromMultipleCommits,
ShowErrorInPanel: true,
}
}
if self.c.Git().Status.WorkingTreeState().Any() {
return &types.DisabledReason{
Text: self.c.Tr.CantPatchWhileRebasingError,
ShowErrorInPanel: true,
}
}
return nil
}
func (self *CommitFilesController) open(node *filetree.CommitFileNode) error {
return self.c.Helpers().Files.OpenFile(node.GetPath())
}
@@ -550,6 +572,21 @@ func (self *CommitFilesController) GetOnClickFocusedMainView() func(mainViewName
}
}
// pathsForDiff returns the file paths to use for a diff command. When a text
// filter is active and the node is a directory, only the visible (filtered)
// file paths are returned so the diff reflects what the user sees.
func (self *CommitFilesController) pathsForDiff(node *filetree.CommitFileNode) []string {
if !node.IsFile() && self.context().IsFiltering() {
var paths []string
_ = node.ForEachFile(func(file *models.CommitFile) error {
paths = append(paths, file.Path)
return nil
})
return paths
}
return []string{node.GetPath()}
}
// NOTE: these functions are identical to those in files_controller.go (except for types) and
// could also be cleaned up with some generics
func normalisedSelectedCommitFileNodes(selectedNodes []*filetree.CommitFileNode) []*filetree.CommitFileNode {
+13 -55
View File
@@ -7,25 +7,10 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
// This controller lets you change the context size for diffs. The 'context' in 'context size' refers to the conventional meaning of the word 'context' in a diff, as opposed to lazygit's own idea of a 'context'.
var CONTEXT_KEYS_SHOWING_DIFFS = []types.ContextKey{
context.FILES_CONTEXT_KEY,
context.COMMIT_FILES_CONTEXT_KEY,
context.STASH_CONTEXT_KEY,
context.LOCAL_COMMITS_CONTEXT_KEY,
context.SUB_COMMITS_CONTEXT_KEY,
context.STAGING_MAIN_CONTEXT_KEY,
context.STAGING_SECONDARY_CONTEXT_KEY,
context.PATCH_BUILDING_MAIN_CONTEXT_KEY,
context.PATCH_BUILDING_SECONDARY_CONTEXT_KEY,
context.NORMAL_MAIN_CONTEXT_KEY,
context.NORMAL_SECONDARY_CONTEXT_KEY,
}
type ContextLinesController struct {
baseController
c *ControllerCommon
@@ -66,39 +51,31 @@ func (self *ContextLinesController) Context() types.Context {
}
func (self *ContextLinesController) Increase() error {
if self.isShowingDiff() {
if err := self.checkCanChangeContext(); err != nil {
return err
}
if self.c.UserConfig().Git.DiffContextSize < math.MaxUint64 {
self.c.UserConfig().Git.DiffContextSize++
}
return self.applyChange()
if err := self.checkCanChangeContext(); err != nil {
return err
}
return nil
if self.c.UserConfig().Git.DiffContextSize < math.MaxUint64 {
self.c.UserConfig().Git.DiffContextSize++
}
return self.applyChange()
}
func (self *ContextLinesController) Decrease() error {
if self.isShowingDiff() {
if err := self.checkCanChangeContext(); err != nil {
return err
}
if self.c.UserConfig().Git.DiffContextSize > 0 {
self.c.UserConfig().Git.DiffContextSize--
}
return self.applyChange()
if err := self.checkCanChangeContext(); err != nil {
return err
}
return nil
if self.c.UserConfig().Git.DiffContextSize > 0 {
self.c.UserConfig().Git.DiffContextSize--
}
return self.applyChange()
}
func (self *ContextLinesController) applyChange() error {
self.c.Toast(fmt.Sprintf(self.c.Tr.DiffContextSizeChanged, self.c.UserConfig().Git.DiffContextSize))
currentContext := self.currentSidePanel()
currentContext := self.c.Context().CurrentSide()
switch currentContext.GetKey() {
// we make an exception for our staging and patch building contexts because they actually need to refresh their state afterwards.
case context.PATCH_BUILDING_MAIN_CONTEXT_KEY:
@@ -118,22 +95,3 @@ func (self *ContextLinesController) checkCanChangeContext() error {
return nil
}
func (self *ContextLinesController) isShowingDiff() bool {
return lo.Contains(
CONTEXT_KEYS_SHOWING_DIFFS,
self.currentSidePanel().GetKey(),
)
}
func (self *ContextLinesController) currentSidePanel() types.Context {
currentContext := self.c.Context().CurrentStatic()
if currentContext.GetKey() == context.NORMAL_MAIN_CONTEXT_KEY ||
currentContext.GetKey() == context.NORMAL_SECONDARY_CONTEXT_KEY {
if sidePanelContext := self.c.Context().NextInStack(currentContext); sidePanelContext != nil {
return sidePanelContext
}
}
return currentContext
}
@@ -123,13 +123,6 @@ func (self *CustomPatchOptionsMenuAction) getPatchCommitIndex() int {
return -1
}
func (self *CustomPatchOptionsMenuAction) validateNormalWorkingTreeState() (bool, error) {
if self.c.Git().Status.WorkingTreeState().Any() {
return false, errors.New(self.c.Tr.CantPatchWhileRebasingError)
}
return true, nil
}
func (self *CustomPatchOptionsMenuAction) returnFocusFromPatchExplorerIfNecessary() {
if self.c.Context().Current().GetKey() == self.c.Contexts().CustomPatchBuilder.GetKey() {
self.c.Helpers().PatchBuilding.Escape()
@@ -137,10 +130,6 @@ func (self *CustomPatchOptionsMenuAction) returnFocusFromPatchExplorerIfNecessar
}
func (self *CustomPatchOptionsMenuAction) handleDeletePatchFromCommit() error {
if ok, err := self.validateNormalWorkingTreeState(); !ok {
return err
}
self.returnFocusFromPatchExplorerIfNecessary()
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error {
@@ -152,10 +141,6 @@ func (self *CustomPatchOptionsMenuAction) handleDeletePatchFromCommit() error {
}
func (self *CustomPatchOptionsMenuAction) handleMovePatchToSelectedCommit() error {
if ok, err := self.validateNormalWorkingTreeState(); !ok {
return err
}
self.returnFocusFromPatchExplorerIfNecessary()
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error {
@@ -167,10 +152,6 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchToSelectedCommit() erro
}
func (self *CustomPatchOptionsMenuAction) handleMovePatchIntoWorkingTree() error {
if ok, err := self.validateNormalWorkingTreeState(); !ok {
return err
}
self.returnFocusFromPatchExplorerIfNecessary()
mustStash := self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules()
@@ -189,10 +170,6 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchIntoWorkingTree() error
}
func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommit() error {
if ok, err := self.validateNormalWorkingTreeState(); !ok {
return err
}
self.returnFocusFromPatchExplorerIfNecessary()
commitIndex := self.getPatchCommitIndex()
@@ -224,10 +201,6 @@ func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommit() error {
}
func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommitBefore() error {
if ok, err := self.validateNormalWorkingTreeState(); !ok {
return err
}
self.returnFocusFromPatchExplorerIfNecessary()
commitIndex := self.getPatchCommitIndex()
+104 -23
View File
@@ -294,7 +294,8 @@ func (self *FilesController) GetOnRenderToMain() func() {
split := self.c.UserConfig().Gui.SplitDiff == "always" || (node.GetHasUnstagedChanges() && node.GetHasStagedChanges())
mainShowsStaged := !split && node.GetHasStagedChanges()
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(node, false, mainShowsStaged)
pathOverrides := self.pathOverridesForDiff(node)
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(node, false, mainShowsStaged, pathOverrides)
title := self.c.Tr.UnstagedChanges
if mainShowsStaged {
title = self.c.Tr.StagedChanges
@@ -309,7 +310,7 @@ func (self *FilesController) GetOnRenderToMain() func() {
}
if split {
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(node, false, true)
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(node, false, true, pathOverrides)
title := self.c.Tr.StagedChanges
if mainShowsStaged {
@@ -434,7 +435,19 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
}
}
// When filtering, expand directory nodes to individual visible file paths
// so that only filtered files are staged/unstaged.
toPaths := func(nodes []*filetree.FileNode) []string {
if self.context().IsFiltering() {
var paths []string
for _, node := range nodes {
_ = node.ForEachFile(func(file *models.File) error {
paths = append(paths, file.Path)
return nil
})
}
return paths
}
return lo.Map(nodes, func(node *filetree.FileNode, _ int) string {
return node.GetPath()
})
@@ -449,7 +462,7 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
if len(unstagedSelectedNodes) > 0 {
var extraArgs []string
if self.context().GetFilter() == filetree.DisplayTracked {
if self.context().GetStatusFilter() == filetree.DisplayTracked {
extraArgs = []string{"-u"}
}
@@ -469,22 +482,29 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
return err
}
// need to partition the paths into tracked and untracked (where we assume directories are tracked). Then we'll run the commands separately.
trackedNodes, untrackedNodes := utils.Partition(selectedNodes, func(node *filetree.FileNode) bool {
// We treat all directories as tracked. I'm not actually sure why we do this but
// it's been the existing behaviour for a while and nobody has complained
return !node.IsFile() || node.GetIsTracked()
})
if len(untrackedNodes) > 0 {
if err := self.c.Git().WorkingTree.UnstageUntrackedFiles(toPaths(untrackedNodes)); err != nil {
if self.context().IsFiltering() {
// When filtering, only unstage visible files
if err := self.unstageFilteredFiles(selectedNodes); err != nil {
return err
}
}
} else {
// need to partition the paths into tracked and untracked (where we assume directories are tracked). Then we'll run the commands separately.
trackedNodes, untrackedNodes := utils.Partition(selectedNodes, func(node *filetree.FileNode) bool {
// We treat all directories as tracked. I'm not actually sure why we do this but
// it's been the existing behaviour for a while and nobody has complained
return !node.IsFile() || node.GetIsTracked()
})
if len(trackedNodes) > 0 {
if err := self.c.Git().WorkingTree.UnstageTrackedFiles(toPaths(trackedNodes)); err != nil {
return err
if len(untrackedNodes) > 0 {
if err := self.c.Git().WorkingTree.UnstageUntrackedFiles(toPaths(untrackedNodes)); err != nil {
return err
}
}
if len(trackedNodes) > 0 {
if err := self.c.Git().WorkingTree.UnstageTrackedFiles(toPaths(trackedNodes)); err != nil {
return err
}
}
}
}
@@ -503,6 +523,48 @@ func (self *FilesController) press(nodes []*filetree.FileNode) error {
return nil
}
// pathOverridesForDiff returns file paths to override the node's path in diff
// commands when a text filter is active and the node is a directory. This
// ensures the diff only shows filtered/visible files.
func (self *FilesController) pathOverridesForDiff(node *filetree.FileNode) []string {
if !node.IsFile() && self.context().IsFiltering() {
var paths []string
_ = node.ForEachFile(func(file *models.File) error {
paths = append(paths, file.Path)
return nil
})
return paths
}
return nil
}
// unstageFilteredFiles unstages only the visible (filtered) files from the
// given nodes, correctly partitioning by tracked/untracked.
func (self *FilesController) unstageFilteredFiles(nodes []*filetree.FileNode) error {
var trackedPaths, untrackedPaths []string
for _, node := range nodes {
_ = node.ForEachFile(func(file *models.File) error {
if file.Tracked || file.HasStagedChanges {
trackedPaths = append(trackedPaths, file.Path)
} else {
untrackedPaths = append(untrackedPaths, file.Path)
}
return nil
})
}
if len(untrackedPaths) > 0 {
if err := self.c.Git().WorkingTree.UnstageUntrackedFiles(untrackedPaths); err != nil {
return err
}
}
if len(trackedPaths) > 0 {
if err := self.c.Git().WorkingTree.UnstageTrackedFiles(trackedPaths); err != nil {
return err
}
}
return nil
}
func (self *FilesController) Context() types.Context {
return self.context()
}
@@ -648,9 +710,21 @@ func (self *FilesController) toggleStagedAllWithLock() error {
return err
}
onlyTrackedFiles := self.context().GetFilter() == filetree.DisplayTracked
if err := self.c.Git().WorkingTree.StageAll(onlyTrackedFiles); err != nil {
return err
if self.context().IsFiltering() {
// When filtering, only stage visible files
var paths []string
_ = root.ForEachFile(func(file *models.File) error {
paths = append(paths, file.Path)
return nil
})
if err := self.c.Git().WorkingTree.StageFiles(paths, nil); err != nil {
return err
}
} else {
onlyTrackedFiles := self.context().GetStatusFilter() == filetree.DisplayTracked
if err := self.c.Git().WorkingTree.StageAll(onlyTrackedFiles); err != nil {
return err
}
}
} else {
self.c.LogAction(self.c.Tr.Actions.UnstageAllFiles)
@@ -659,8 +733,15 @@ func (self *FilesController) toggleStagedAllWithLock() error {
return err
}
if err := self.c.Git().WorkingTree.UnstageAll(); err != nil {
return err
if self.context().IsFiltering() {
// When filtering, only unstage visible files
if err := self.unstageFilteredFiles([]*filetree.FileNode{root}); err != nil {
return err
}
} else {
if err := self.c.Git().WorkingTree.UnstageAll(); err != nil {
return err
}
}
}
@@ -836,7 +917,7 @@ func (self *FilesController) isResolvingConflicts() bool {
}
func (self *FilesController) handleStatusFilterPressed() error {
currentFilter := self.context().GetFilter()
currentFilter := self.context().GetStatusFilter()
return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.FilteringMenuTitle,
Items: []*types.MenuItem{
@@ -904,7 +985,7 @@ func (self *FilesController) filteringLabel(filter filetree.FileTreeDisplayFilte
}
func (self *FilesController) setStatusFiltering(filter filetree.FileTreeDisplayFilter) error {
previousFilter := self.context().GetFilter()
previousFilter := self.context().GetStatusFilter()
self.context().FileTreeViewModel.SetStatusFilter(filter)
self.c.Contexts().Files.GetView().Subtitle = self.filteringLabel(filter)
@@ -102,11 +102,13 @@ func getMessageHeight(wrap bool, editable bool, message string, width int, tabWi
return len(wrappedLines)
}
func (self *ConfirmationHelper) getPopupPanelDimensionsForContentHeight(panelWidth, contentHeight int, parentPopupContext types.Context) (int, int, int, int) {
return self.getPopupPanelDimensionsAux(panelWidth, contentHeight, parentPopupContext)
func (self *ConfirmationHelper) getPopupPanelDimensionsForContentHeight(contentWidth, contentHeight int, parentPopupContext types.Context) (int, int, int, int) {
return self.getPopupPanelDimensionsAux(contentWidth, contentHeight, parentPopupContext)
}
func (self *ConfirmationHelper) getPopupPanelDimensionsAux(panelWidth int, panelHeight int, parentPopupContext types.Context) (int, int, int, int) {
func (self *ConfirmationHelper) getPopupPanelDimensionsAux(contentWidth int, contentHeight int, parentPopupContext types.Context) (int, int, int, int) {
panelWidth := contentWidth + 2 // plus 2 for the frame
panelHeight := contentHeight + 2
width, height := self.c.GocuiGui().Size()
if panelHeight > height*3/4 {
panelHeight = height * 3 / 4
@@ -117,18 +119,23 @@ func (self *ConfirmationHelper) getPopupPanelDimensionsAux(panelWidth int, panel
x0, y0, _, _ := parentPopupContext.GetView().Dimensions()
x0 += 2
y0 += 1
return x0, y0, x0 + panelWidth, y0 + panelHeight + 1
return x0, y0, x0 + panelWidth - 1, y0 + panelHeight - 1
}
return width/2 - panelWidth/2,
height/2 - panelHeight/2 - panelHeight%2 - 1,
width/2 + panelWidth/2,
height/2 + panelHeight/2
height/2 - panelHeight/2 - panelHeight%2,
// Currently, X1/Y1 of a gocui view is one less than you would expect based on its
// width/height, so we need to subtract 1 here. See
// https://github.com/jesseduffield/lazygit/commit/f6f2a52dee8bba3ebd7e3b34b4b7c7d3e3795f3e
width/2 + panelWidth/2 - 1,
height/2 + panelHeight/2 - 1
}
func (self *ConfirmationHelper) getPopupPanelWidth() int {
// Returns the outer width of the view, including its frame. To decide how to wrap text, subtract 2.
// Also, note that X1-X0 of the view is one less than this.
func (self *ConfirmationHelper) getPopupPanelWidth(maxWidth int) int {
width, _ := self.c.GocuiGui().Size()
// we want a minimum width up to a point, then we do it based on ratio.
panelWidth := 4 * width / 7
// we want a minimum width up to a point, then we do it based on ratio, but only up to the given max width
panelWidth := min(4*width/7, maxWidth)
minWidth := 80
if panelWidth < minWidth {
panelWidth = min(width-2, minWidth)
@@ -328,10 +335,10 @@ func (self *ConfirmationHelper) resizeMenu(parentPopupContext types.Context) {
// resize the window
itemCount := self.c.Contexts().Menu.UnfilteredLen()
offset := 3
panelWidth := self.getPopupPanelWidth()
panelWidth := self.getPopupPanelWidth(90)
contentWidth := panelWidth - 2 // minus 2 for the frame
promptLinesCount := self.layoutMenuPrompt(contentWidth)
x0, y0, x1, y1 := self.getPopupPanelDimensionsForContentHeight(panelWidth, itemCount+offset+promptLinesCount, parentPopupContext)
x0, y0, x1, y1 := self.getPopupPanelDimensionsForContentHeight(contentWidth, itemCount+offset+promptLinesCount, parentPopupContext)
menuBottom := y1 - offset
_, _ = self.c.GocuiGui().SetView(self.c.Views().Menu.Name(), x0, y0, x1, menuBottom, 0)
@@ -375,12 +382,12 @@ func (self *ConfirmationHelper) layoutMenuPrompt(contentWidth int) int {
}
func (self *ConfirmationHelper) resizeConfirmationPanel(parentPopupContext types.Context) {
panelWidth := self.getPopupPanelWidth()
panelWidth := self.getPopupPanelWidth(80)
contentWidth := panelWidth - 2 // minus 2 for the frame
confirmationView := self.c.Views().Confirmation
prompt := confirmationView.Buffer()
panelHeight := getMessageHeight(true, false, prompt, contentWidth, confirmationView.TabWidth)
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext)
contentHeight := getMessageHeight(true, false, prompt, contentWidth, confirmationView.TabWidth)
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(contentWidth, contentHeight, parentPopupContext)
_, _ = self.c.GocuiGui().SetView(confirmationView.Name(), x0, y0, x1, y1, 0)
}
@@ -389,12 +396,12 @@ func (self *ConfirmationHelper) resizePromptPanel(parentPopupContext types.Conte
if self.c.Views().Suggestions.Visible {
suggestionsViewHeight = 11
}
panelWidth := self.getPopupPanelWidth()
panelWidth := self.getPopupPanelWidth(80)
contentWidth := panelWidth - 2 // minus 2 for the frame
promptView := self.c.Views().Prompt
prompt := promptView.TextArea.GetContent()
panelHeight := getMessageHeight(false, true, prompt, contentWidth, promptView.TabWidth) + suggestionsViewHeight
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext)
contentHeight := getMessageHeight(false, true, prompt, contentWidth, promptView.TabWidth) + suggestionsViewHeight
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(contentWidth, contentHeight, parentPopupContext)
promptViewBottom := y1 - suggestionsViewHeight
_, _ = self.c.GocuiGui().SetView(promptView.Name(), x0, y0, x1, promptViewBottom, 0)
@@ -403,15 +410,24 @@ func (self *ConfirmationHelper) resizePromptPanel(parentPopupContext types.Conte
}
func (self *ConfirmationHelper) ResizeCommitMessagePanels(parentPopupContext types.Context) {
panelWidth := self.getPopupPanelWidth()
maxWidth := 100
if self.c.UserConfig().Git.Commit.AutoWrapCommitMessage {
// Adding some extra space to make it very obvious that we're wrapping the commit message
// for real, not just soft-wrapping for display at the window width.
maxWidth = self.c.UserConfig().Git.Commit.AutoWrapWidth + 25
}
panelWidth := self.getPopupPanelWidth(maxWidth)
contentWidth := panelWidth - 2 // minus 2 for the frame
content := self.c.Views().CommitDescription.TextArea.GetContent()
summaryViewHeight := 3
panelHeight := getMessageHeight(false, true, content, panelWidth, self.c.Views().CommitDescription.TabWidth)
// The width we pass to getMessageHeight is irrelevant because we don't wrap the text to the
// view width. If we did, we'd have to subtract 2 for the view frame.
contentHeight := getMessageHeight(false, true, content, contentWidth, self.c.Views().CommitDescription.TabWidth)
minHeight := 7
if panelHeight < minHeight {
panelHeight = minHeight
if contentHeight < minHeight {
contentHeight = minHeight
}
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext)
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(contentWidth, contentHeight, parentPopupContext)
_, _ = self.c.GocuiGui().SetView(self.c.Views().CommitMessage.Name(), x0, y0, x1, y0+summaryViewHeight-1, 0)
_, _ = self.c.GocuiGui().SetView(self.c.Views().CommitDescription.Name(), x0, y0+summaryViewHeight, x1, y1+summaryViewHeight, 0)
+70 -9
View File
@@ -110,20 +110,24 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
return errors.New(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
}
if len(hashGroups[NOT_MERGED]) > 1 {
// If there are multiple commits that could be the base commit, list
foundCommits := getCommitsForHashes(commits, hashGroups[NOT_MERGED])
// If there are multiple commits that could be the base commit, remove all
// those that are fixups for the last one.
foundCommits = removeFixupCommits(foundCommits)
if len(foundCommits) > 1 {
// If there are still multiple commits that could be the base commit, list
// them in the error message. But only the candidates from the current
// branch, not including any that are already merged.
subjects := self.getHashesAndSubjects(commits, hashGroups[NOT_MERGED])
subjects := getHashesAndSubjects(foundCommits)
message := lo.Ternary(hasStagedChanges,
self.c.Tr.MultipleBaseCommitsFoundStaged,
self.c.Tr.MultipleBaseCommitsFoundUnstaged)
return fmt.Errorf("%s\n\n%s", message, subjects)
}
// At this point we know that the NOT_MERGED bucket has exactly one commit,
// and that's the one we want to select.
_, index, _ := self.findCommit(commits, hashGroups[NOT_MERGED][0])
// Now we know that foundCommits has exactly one commit, so find its index
_, index, _ := self.findCommit(commits, foundCommits[0].Hash())
return self.c.ConfirmIf(warnAboutAddedLines, types.ConfirmOpts{
Title: self.c.Tr.FindBaseCommitForFixup,
@@ -137,29 +141,59 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
}
self.c.Contexts().LocalCommits.SetSelection(index)
self.c.Contexts().LocalCommits.FocusLine(true)
self.c.Context().Push(self.c.Contexts().LocalCommits, types.OnFocusOpts{})
return nil
},
})
}
func (self *FixupHelper) getHashesAndSubjects(commits []*models.Commit, hashes []string) string {
func getCommitsForHashes(commits []*models.Commit, hashes []string) []*models.Commit {
// This is called only for the NOT_MERGED commits, and we know that all of them are contained in
// the commits slice.
commitsSet := set.NewFromSlice(hashes)
subjects := make([]string, 0, len(hashes))
result := make([]*models.Commit, 0, len(hashes))
for _, c := range commits {
if commitsSet.Includes(c.Hash()) {
subjects = append(subjects, fmt.Sprintf("%s %s", c.ShortRefName(), c.Name))
result = append(result, c)
commitsSet.Remove(c.Hash())
if commitsSet.Len() == 0 {
break
}
}
}
return result
}
func getHashesAndSubjects(commits []*models.Commit) string {
subjects := lo.Map(commits, func(c *models.Commit, _ int) string {
return fmt.Sprintf("%s %s", c.ShortRefName(), c.Name)
})
return strings.Join(subjects, "\n")
}
func removeFixupCommits(commits []*models.Commit) []*models.Commit {
if len(commits) <= 1 {
return commits
}
// If the last found commit is itself a fixup, don't eliminate anything.
baseSubject, lastIsFixup := IsFixupCommit(commits[len(commits)-1].Name)
if lastIsFixup {
return commits
}
// need to go backwards because we are mutating the slice as we go
for i := len(commits) - 2; i >= 0; i-- {
subject, isFixup := IsFixupCommit(commits[i].Name)
if isFixup && subject == baseSubject {
commits = utils.Remove(commits, i)
}
}
return commits
}
func (self *FixupHelper) getDiff() (string, bool, error) {
args := []string{"-U0", "--ignore-submodules=all", "HEAD", "--"}
@@ -349,3 +383,30 @@ func (self *FixupHelper) findCommit(commits []*models.Commit, hash string) (*mod
return commit.Hash() == hash
})
}
// Check whether the given subject line is the subject of a fixup commit, and
// returns (trimmedSubject, true) if so (where trimmedSubject is the subject
// with all fixup prefixes removed), or (subject, false) if not.
func IsFixupCommit(subject string) (string, bool) {
prefixes := []string{"fixup! ", "squash! ", "amend! "}
trimPrefix := func(s string) (string, bool) {
for _, prefix := range prefixes {
if trimmedSubject, ok := strings.CutPrefix(s, prefix); ok {
return trimmedSubject, true
}
}
return s, false
}
if subject, wasTrimmed := trimPrefix(subject); wasTrimmed {
for {
// handle repeated prefixes like "fixup! amend! fixup! Subject"
if subject, wasTrimmed = trimPrefix(subject); !wasTrimmed {
break
}
}
return subject, true
}
return subject, false
}
@@ -3,6 +3,9 @@ package helpers
import (
"testing"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
"github.com/stretchr/testify/assert"
)
@@ -155,3 +158,184 @@ index 9ce8efb33..0632e41b0 100644
})
}
}
func TestFixupHelper_IsFixupCommit(t *testing.T) {
scenarios := []struct {
subject string
expectedTrimmedSubject string
expectedIsFixup bool
}{
{
subject: "Bla",
expectedTrimmedSubject: "Bla",
expectedIsFixup: false,
},
{
subject: "fixup Bla",
expectedTrimmedSubject: "fixup Bla",
expectedIsFixup: false,
},
{
subject: "fixup! Bla",
expectedTrimmedSubject: "Bla",
expectedIsFixup: true,
},
{
subject: "fixup! fixup! Bla",
expectedTrimmedSubject: "Bla",
expectedIsFixup: true,
},
{
subject: "amend! squash! Bla",
expectedTrimmedSubject: "Bla",
expectedIsFixup: true,
},
{
subject: "fixup!",
expectedTrimmedSubject: "fixup!",
expectedIsFixup: false,
},
}
for _, s := range scenarios {
t.Run(s.subject, func(t *testing.T) {
trimmedSubject, isFixupCommit := IsFixupCommit(s.subject)
assert.Equal(t, s.expectedTrimmedSubject, trimmedSubject)
assert.Equal(t, s.expectedIsFixup, isFixupCommit)
})
}
}
func TestFixupHelper_removeFixupCommits(t *testing.T) {
hashPool := &utils.StringPool{}
type commitDesc struct {
Hash string
Name string
}
scenarios := []struct {
name string
commits []commitDesc
expectedResult []commitDesc
}{
{
name: "empty list",
commits: []commitDesc{},
expectedResult: []commitDesc{},
},
{
name: "single commit",
commits: []commitDesc{
{"abc123", "Some feature"},
},
expectedResult: []commitDesc{
{"abc123", "Some feature"},
},
},
{
name: "two unrelated commits",
commits: []commitDesc{
{"abc123", "First feature"},
{"def456", "Second feature"},
},
expectedResult: []commitDesc{
{"abc123", "First feature"},
{"def456", "Second feature"},
},
},
{
name: "fixup commit for last commit",
commits: []commitDesc{
{"abc123", "fixup! Some feature"},
{"def456", "Some feature"},
},
expectedResult: []commitDesc{
{"def456", "Some feature"},
},
},
{
name: "amend and squash commits for last commit",
commits: []commitDesc{
{"abc123", "squash! Some feature"},
{"def456", "amend! Some feature"},
{"ghi789", "Some feature"},
},
expectedResult: []commitDesc{
{"ghi789", "Some feature"},
},
},
{
name: "fixup commit for different commit",
commits: []commitDesc{
{"abc123", "fixup! Other feature"},
{"def456", "Some feature"},
},
expectedResult: []commitDesc{
{"abc123", "fixup! Other feature"},
{"def456", "Some feature"},
},
},
{
name: "last commit is a fixup itself",
commits: []commitDesc{
{"abc123", "fixup! Some feature"},
{"def456", "fixup! Some feature"},
},
expectedResult: []commitDesc{
{"abc123", "fixup! Some feature"},
{"def456", "fixup! Some feature"},
},
},
{
name: "nested fixup commit",
commits: []commitDesc{
{"abc123", "fixup! fixup! Some feature"},
{"def456", "amend! squash! fixup! Some feature"},
{"ghi789", "Some feature"},
},
expectedResult: []commitDesc{
{"ghi789", "Some feature"},
},
},
{
name: "fixup commits mixed with unrelated commits",
commits: []commitDesc{
{Hash: "abc123", Name: "fixup! Base commit"},
{Hash: "def456", Name: "Unrelated commit"},
{Hash: "ghi789", Name: "fixup! Base commit"},
{Hash: "jkl012", Name: "Base commit"},
},
expectedResult: []commitDesc{
{Hash: "def456", Name: "Unrelated commit"},
{Hash: "jkl012", Name: "Base commit"},
},
},
{
name: "only fixup commits for last commit removed, others preserved",
commits: []commitDesc{
{Hash: "abc123", Name: "fixup! First feature"},
{Hash: "def456", Name: "fixup! Second feature"},
{Hash: "ghi789", Name: "Second feature"},
{Hash: "jkl012", Name: "First feature"},
},
expectedResult: []commitDesc{
{Hash: "def456", Name: "fixup! Second feature"},
{Hash: "ghi789", Name: "Second feature"},
{Hash: "jkl012", Name: "First feature"},
},
},
}
makeCommitFromDesc := func(desc commitDesc, _ int) *models.Commit {
return models.NewCommit(hashPool, models.NewCommitOpts{Hash: desc.Hash, Name: desc.Name})
}
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
commits := lo.Map(s.commits, makeCommitFromDesc)
result := removeFixupCommits(commits)
expectedCommits := lo.Map(s.expectedResult, makeCommitFromDesc)
assert.Equal(t, expectedCommits, result)
})
}
}
@@ -1,7 +1,6 @@
package helpers
import (
"errors"
"fmt"
"github.com/jesseduffield/lazygit/pkg/commands/patch"
@@ -22,13 +21,6 @@ func NewPatchBuildingHelper(
}
}
func (self *PatchBuildingHelper) ValidateNormalWorkingTreeState() (bool, error) {
if self.c.Git().Status.WorkingTreeState().Any() {
return false, errors.New(self.c.Tr.CantPatchWhileRebasingError)
}
return true, nil
}
func (self *PatchBuildingHelper) ShowHunkStagingHint() {
if !self.c.AppState.DidShowHunkStagingHint && self.c.UserConfig().Gui.UseHunkModeInStagingView {
self.c.AppState.DidShowHunkStagingHint = true
@@ -584,11 +584,11 @@ func (self *RefreshHelper) refreshStateFiles() error {
// only taking over the filter if it hasn't already been set by the user.
if conflictFileCount > 0 && prevConflictFileCount == 0 {
if fileTreeViewModel.GetFilter() == filetree.DisplayAll {
if fileTreeViewModel.GetStatusFilter() == filetree.DisplayAll {
fileTreeViewModel.SetStatusFilter(filetree.DisplayConflicted)
self.c.Contexts().Files.GetView().Subtitle = self.c.Tr.FilterLabelConflictingFiles
}
} else if conflictFileCount == 0 && fileTreeViewModel.GetFilter() == filetree.DisplayConflicted {
} else if conflictFileCount == 0 && fileTreeViewModel.GetStatusFilter() == filetree.DisplayConflicted {
fileTreeViewModel.SetStatusFilter(filetree.DisplayAll)
self.c.Contexts().Files.GetView().Subtitle = ""
}
+7 -10
View File
@@ -33,6 +33,8 @@ func NewSearchHelper(
func (self *SearchHelper) OpenFilterPrompt(context types.IFilterableContext) error {
state := self.searchState()
state.PrevSearchIndex = -1
state.Context = context
self.searchPrefixView().SetContent(context.FilterPrefix(self.c.Tr))
@@ -108,20 +110,15 @@ func (self *SearchHelper) Confirm() error {
return self.CancelPrompt()
}
var err error
switch state.SearchType() {
case types.SearchTypeFilter:
self.ConfirmFilter()
case types.SearchTypeSearch:
err = self.ConfirmSearch()
self.ConfirmSearch()
case types.SearchTypeNone:
self.c.Context().Pop()
}
if err != nil {
return err
}
return self.c.ResetKeybindings()
}
@@ -144,13 +141,13 @@ func (self *SearchHelper) ConfirmFilter() {
self.c.Context().Pop()
}
func (self *SearchHelper) ConfirmSearch() error {
func (self *SearchHelper) ConfirmSearch() {
state := self.searchState()
context, ok := state.Context.(types.ISearchableContext)
if !ok {
self.c.Log.Warnf("Context %s is searchable", state.Context.GetKey())
return nil
return
}
searchString := self.promptContent()
@@ -161,7 +158,7 @@ func (self *SearchHelper) ConfirmSearch() error {
self.c.Context().Pop()
return context.GetView().Search(searchString, modelSearchResults(context))
context.GetView().Search(searchString, modelSearchResults(context))
}
func modelSearchResults(context types.ISearchableContext) []gocui.SearchPosition {
@@ -243,7 +240,7 @@ func (self *SearchHelper) ReApplyFilter(context types.Context) {
filterableContext, ok := context.(types.IFilterableContext)
if ok {
state := self.searchState()
if context == state.Context {
if context == state.Context && self.c.Context().Current().GetKey() == self.c.Contexts().Search.GetKey() {
filterableContext.SetSelection(0)
filterableContext.GetView().SetOriginY(0)
}
+10
View File
@@ -104,6 +104,7 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error {
// doing this check so that if we're holding the up key at the start of the list
// we're not constantly re-rendering the main view.
cursorMoved := before != after
originYBefore := self.context.GetView().OriginY()
if cursorMoved {
switch change {
case -1:
@@ -116,6 +117,15 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error {
}
if cursorMoved || rangeBefore != rangeAfter {
if originYBefore != self.context.GetView().OriginY() {
// Since we already scrolled the view above, the normal mechanism that
// ListContextTrait.FocusLine uses for deciding whether rerendering is needed won't
// work. It is based on checking whether the origin was changed by the call to
// FocusPoint in that function, but since we scrolled the view directly above, the
// origin has already been updated. So we must tell it explicitly to rerender.
self.context.SetNeedRerenderVisibleLines()
}
self.context.HandleFocus(types.OnFocusOpts{ScrollSelectionIntoView: true})
} else {
// If the selection did not change (because, for example, we are at the top of the list and
+84 -39
View File
@@ -82,6 +82,15 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
Tooltip: self.c.Tr.FixupTooltip,
DisplayOnScreen: true,
},
{
Key: opts.GetKey(opts.Config.Commits.SetFixupMessage),
Handler: self.withItem(self.setFixupMessage),
GetDisabledReason: self.require(
self.singleItemSelected(self.canSetFixupMessage),
),
Description: self.c.Tr.SetFixupMessage,
Tooltip: self.c.Tr.SetFixupMessageTooltip,
},
{
Key: opts.GetKey(opts.Config.Commits.RenameCommit),
Handler: self.withItem(self.reword),
@@ -321,20 +330,71 @@ func (self *LocalCommitsController) fixup(selectedCommits []*models.Commit, star
return self.updateTodos(todo.Fixup, selectedCommits)
}
self.c.Confirm(types.ConfirmOpts{
Title: self.c.Tr.Fixup,
Prompt: self.c.Tr.SureFixupThisCommit,
HandleConfirm: func() error {
return self.c.WithWaitingStatus(self.c.Tr.FixingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.FixupCommit)
return self.interactiveRebase(todo.Fixup, startIdx, endIdx)
})
return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.Fixup,
Items: []*types.MenuItem{
{
Label: self.c.Tr.Fixup,
Key: 'f',
OnPress: func() error {
return self.c.WithWaitingStatus(self.c.Tr.FixingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.FixupCommit)
return self.interactiveRebase(todo.Fixup, startIdx, endIdx)
})
},
Tooltip: self.c.Tr.FixupTooltip,
},
{
Label: self.c.Tr.FixupKeepMessage,
Key: 'c',
OnPress: func() error {
return self.c.WithWaitingStatus(self.c.Tr.FixingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.FixupCommitKeepMessage)
return self.interactiveRebaseWithFlag(todo.Fixup, startIdx, endIdx, "-C")
})
},
Tooltip: self.c.Tr.FixupKeepMessageTooltip,
},
},
})
}
func (self *LocalCommitsController) canSetFixupMessage(commit *models.Commit) *types.DisabledReason {
if !self.isRebasing() {
return &types.DisabledReason{Text: self.c.Tr.NotMidRebase}
}
if commit.Action != todo.Fixup {
return &types.DisabledReason{Text: self.c.Tr.MustSelectFixupCommit}
}
return nil
}
func (self *LocalCommitsController) setFixupMessage(commit *models.Commit) error {
return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.SetFixupMessage,
Items: []*types.MenuItem{
{
Label: self.c.Tr.FixupDiscardMessage,
Key: 'f',
OnPress: func() error {
return self.updateTodosWithFlag(todo.Fixup, []*models.Commit{commit}, "")
},
Tooltip: self.c.Tr.FixupDiscardMessageTooltip,
},
{
Label: self.c.Tr.FixupKeepMessage,
Key: 'c',
OnPress: func() error {
return self.updateTodosWithFlag(todo.Fixup, []*models.Commit{commit}, "-C")
},
Tooltip: self.c.Tr.FixupKeepMessageTooltip,
},
},
})
}
func (self *LocalCommitsController) reword(commit *models.Commit) error {
commitIdx := self.context().GetSelectedLineIdx()
if self.c.Git().Config.NeedsGpgSubprocessForCommit() && !self.isHeadCommit(commitIdx) {
@@ -505,7 +565,7 @@ func (self *LocalCommitsController) edit(selectedCommits []*models.Commit, start
commits := self.c.Model().Commits
if !commits[endIdx].IsMerge() {
selectionRangeAndMode := self.getSelectionRangeAndMode()
err := self.c.Git().Rebase.InteractiveRebase(commits, startIdx, endIdx, todo.Edit)
err := self.c.Git().Rebase.InteractiveRebase(commits, startIdx, endIdx, todo.Edit, "")
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions(
err,
types.RefreshOptions{
@@ -611,13 +671,17 @@ func (self *LocalCommitsController) pick(selectedCommits []*models.Commit) error
}
func (self *LocalCommitsController) interactiveRebase(action todo.TodoCommand, startIdx int, endIdx int) error {
return self.interactiveRebaseWithFlag(action, startIdx, endIdx, "")
}
func (self *LocalCommitsController) interactiveRebaseWithFlag(action todo.TodoCommand, startIdx int, endIdx int, flag string) error {
// When performing an action that will remove the selected commits, we need to select the
// next commit down (which will end up at the start index after the action is performed)
if action == todo.Drop || action == todo.Fixup || action == todo.Squash {
self.context().SetSelection(startIdx)
}
err := self.c.Git().Rebase.InteractiveRebase(self.c.Model().Commits, startIdx, endIdx, action)
err := self.c.Git().Rebase.InteractiveRebase(self.c.Model().Commits, startIdx, endIdx, action, flag)
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err)
}
@@ -626,7 +690,11 @@ func (self *LocalCommitsController) interactiveRebase(action todo.TodoCommand, s
// commit meaning you are trying to edit the todo file rather than actually
// begin a rebase. It then updates the todo file with that action
func (self *LocalCommitsController) updateTodos(action todo.TodoCommand, selectedCommits []*models.Commit) error {
if err := self.c.Git().Rebase.EditRebaseTodo(selectedCommits, action); err != nil {
return self.updateTodosWithFlag(action, selectedCommits, "")
}
func (self *LocalCommitsController) updateTodosWithFlag(action todo.TodoCommand, selectedCommits []*models.Commit, flag string) error {
if err := self.c.Git().Rebase.EditRebaseTodo(selectedCommits, action, flag); err != nil {
return err
}
@@ -670,6 +738,7 @@ func (self *LocalCommitsController) moveDown(selectedCommits []*models.Commit, s
return err
}
self.context().MoveSelection(1)
self.context().HandleFocus(types.OnFocusOpts{ScrollSelectionIntoView: true})
self.c.Refresh(types.RefreshOptions{
Mode: types.SYNC, Scope: []types.RefreshableView{types.REBASE_COMMITS},
@@ -682,6 +751,7 @@ func (self *LocalCommitsController) moveDown(selectedCommits []*models.Commit, s
err := self.c.Git().Rebase.MoveCommitsDown(self.c.Model().Commits, startIdx, endIdx)
if err == nil {
self.context().MoveSelection(1)
self.context().HandleFocus(types.OnFocusOpts{ScrollSelectionIntoView: true})
}
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions(
err, types.RefreshOptions{Mode: types.SYNC})
@@ -694,6 +764,7 @@ func (self *LocalCommitsController) moveUp(selectedCommits []*models.Commit, sta
return err
}
self.context().MoveSelection(-1)
self.context().HandleFocus(types.OnFocusOpts{ScrollSelectionIntoView: true})
self.c.Refresh(types.RefreshOptions{
Mode: types.SYNC, Scope: []types.RefreshableView{types.REBASE_COMMITS},
@@ -706,6 +777,7 @@ func (self *LocalCommitsController) moveUp(selectedCommits []*models.Commit, sta
err := self.c.Git().Rebase.MoveCommitsUp(self.c.Model().Commits, startIdx, endIdx)
if err == nil {
self.context().MoveSelection(-1)
self.context().HandleFocus(types.OnFocusOpts{ScrollSelectionIntoView: true})
}
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions(
err, types.RefreshOptions{Mode: types.SYNC})
@@ -1096,7 +1168,7 @@ func countSquashableCommitsAbove(commits []*models.Commit, selectedIdx int, reba
// For each commit _above_ the selection, ...
for i, commit := range commits[0:selectedIdx] {
// ... see if it is a fixup commit, and get the base subject it applies to
if baseSubject, isFixup := isFixupCommit(commit.Name); isFixup {
if baseSubject, isFixup := helpers.IsFixupCommit(commit.Name); isFixup {
// Then, for each commit after the fixup, up to and including the
// rebase start commit, see if we find the base commit
for _, baseCommit := range commits[i+1 : rebaseStartIdx+1] {
@@ -1109,33 +1181,6 @@ func countSquashableCommitsAbove(commits []*models.Commit, selectedIdx int, reba
return result
}
// Check whether the given subject line is the subject of a fixup commit, and
// returns (trimmedSubject, true) if so (where trimmedSubject is the subject
// with all fixup prefixes removed), or (subject, false) if not.
func isFixupCommit(subject string) (string, bool) {
prefixes := []string{"fixup! ", "squash! ", "amend! "}
trimPrefix := func(s string) (string, bool) {
for _, prefix := range prefixes {
if trimmedSubject, ok := strings.CutPrefix(s, prefix); ok {
return trimmedSubject, true
}
}
return s, false
}
if subject, wasTrimmed := trimPrefix(subject); wasTrimmed {
for {
// handle repeated prefixes like "fixup! amend! fixup! Subject"
if subject, wasTrimmed = trimPrefix(subject); !wasTrimmed {
break
}
}
return subject, true
}
return subject, false
}
func (self *LocalCommitsController) createTag(commit *models.Commit) error {
return self.c.Helpers().Tags.OpenCreateTagPrompt(commit.Hash(), func() {})
}
@@ -93,49 +93,3 @@ func Test_countSquashableCommitsAbove(t *testing.T) {
})
}
}
func Test_isFixupCommit(t *testing.T) {
scenarios := []struct {
subject string
expectedTrimmedSubject string
expectedIsFixup bool
}{
{
subject: "Bla",
expectedTrimmedSubject: "Bla",
expectedIsFixup: false,
},
{
subject: "fixup Bla",
expectedTrimmedSubject: "fixup Bla",
expectedIsFixup: false,
},
{
subject: "fixup! Bla",
expectedTrimmedSubject: "Bla",
expectedIsFixup: true,
},
{
subject: "fixup! fixup! Bla",
expectedTrimmedSubject: "Bla",
expectedIsFixup: true,
},
{
subject: "amend! squash! Bla",
expectedTrimmedSubject: "Bla",
expectedIsFixup: true,
},
{
subject: "fixup!",
expectedTrimmedSubject: "fixup!",
expectedIsFixup: false,
},
}
for _, s := range scenarios {
t.Run(s.subject, func(t *testing.T) {
trimmedSubject, isFixupCommit := isFixupCommit(s.subject)
assert.Equal(t, s.expectedTrimmedSubject, trimmedSubject)
assert.Equal(t, s.expectedIsFixup, isFixupCommit)
})
}
}
@@ -1,7 +1,10 @@
package controllers
import (
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
@@ -42,6 +45,14 @@ func (self *PatchBuildingController) GetKeybindings(opts types.KeybindingsOpts)
Description: self.c.Tr.ToggleSelectionForPatch,
DisplayOnScreen: true,
},
{
Key: opts.GetKey(opts.Config.Universal.Remove),
Handler: self.discardSelection,
GetDisabledReason: self.getDisabledReasonForDiscard,
Description: self.c.Tr.RemoveSelectionFromPatch,
Tooltip: self.c.Tr.RemoveSelectionFromPatchTooltip,
DisplayOnScreen: true,
},
{
Key: opts.GetKey(opts.Config.Universal.Return),
Handler: self.Escape,
@@ -168,6 +179,70 @@ func (self *PatchBuildingController) toggleSelection() error {
return nil
}
func (self *PatchBuildingController) getDisabledReasonForDiscard() *types.DisabledReason {
if !self.c.Git().Patch.PatchBuilder.CanRebase {
return &types.DisabledReason{Text: self.c.Tr.CanOnlyDiscardFromLocalCommits, ShowErrorInPanel: true}
}
if self.c.Git().Status.WorkingTreeState().Any() {
return &types.DisabledReason{Text: self.c.Tr.CantPatchWhileRebasingError, ShowErrorInPanel: true}
}
if self.c.UserConfig().Git.DiffContextSize == 0 {
text := fmt.Sprintf(self.c.Tr.Actions.NotEnoughContextToRemoveLines,
keybindings.Label(self.c.UserConfig().Keybinding.Universal.IncreaseContextInDiffView))
return &types.DisabledReason{Text: text, ShowErrorInPanel: true}
}
return nil
}
func (self *PatchBuildingController) discardSelection() error {
prompt := lo.Ternary(self.c.Git().Patch.PatchBuilder.IsEmpty(),
self.c.Tr.DiscardLinesFromCommitPrompt,
self.c.Tr.DiscardLinesFromCommitPromptWithReset)
self.c.Confirm(types.ConfirmOpts{
Title: self.c.Tr.DiscardLinesFromCommitTitle,
Prompt: prompt,
HandleConfirm: func() error {
return self.discardSelectionFromCommit()
},
})
return nil
}
func (self *PatchBuildingController) discardSelectionFromCommit() error {
// Reset the current patch if there is one.
if !self.c.Git().Patch.PatchBuilder.IsEmpty() {
self.c.Git().Patch.PatchBuilder.Reset()
}
if err := self.toggleSelection(); err != nil {
return err
}
if self.c.Git().Patch.PatchBuilder.IsEmpty() {
return nil
}
return self.c.WithWaitingStatusSync(self.c.Tr.RebasingStatus, func() error {
commitIndex := self.getPatchCommitIndex()
self.c.LogAction(self.c.Tr.Actions.RemovePatchFromCommit)
err := self.c.Git().Patch.DeletePatchesFromCommit(self.c.Model().Commits, commitIndex)
self.c.Helpers().PatchBuilding.Escape()
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions(
err, types.RefreshOptions{Mode: types.SYNC})
})
}
func (self *PatchBuildingController) getPatchCommitIndex() int {
for index, commit := range self.c.Model().Commits {
if commit.Hash() == self.c.Git().Patch.PatchBuilder.To {
return index
}
}
return -1
}
func (self *PatchBuildingController) Escape() error {
context := self.c.Contexts().CustomPatchBuilder
state := context.GetState()
@@ -5,20 +5,10 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
// This controller lets you change the similarity threshold for detecting renames.
var CONTEXT_KEYS_SHOWING_RENAMES = []types.ContextKey{
context.FILES_CONTEXT_KEY,
context.SUB_COMMITS_CONTEXT_KEY,
context.LOCAL_COMMITS_CONTEXT_KEY,
context.STASH_CONTEXT_KEY,
context.NORMAL_MAIN_CONTEXT_KEY,
context.NORMAL_SECONDARY_CONTEXT_KEY,
}
type RenameSimilarityThresholdController struct {
baseController
c *ControllerCommon
@@ -61,29 +51,27 @@ func (self *RenameSimilarityThresholdController) Context() types.Context {
func (self *RenameSimilarityThresholdController) Increase() error {
old_size := self.c.UserConfig().Git.RenameSimilarityThreshold
if self.isShowingRenames() && old_size < 100 {
if old_size < 100 {
self.c.UserConfig().Git.RenameSimilarityThreshold = min(100, old_size+5)
return self.applyChange()
}
return nil
return self.applyChange()
}
func (self *RenameSimilarityThresholdController) Decrease() error {
old_size := self.c.UserConfig().Git.RenameSimilarityThreshold
if self.isShowingRenames() && old_size > 5 {
if old_size > 5 {
self.c.UserConfig().Git.RenameSimilarityThreshold = max(5, old_size-5)
return self.applyChange()
}
return nil
return self.applyChange()
}
func (self *RenameSimilarityThresholdController) applyChange() error {
self.c.Toast(fmt.Sprintf(self.c.Tr.RenameSimilarityThresholdChanged, self.c.UserConfig().Git.RenameSimilarityThreshold))
currentContext := self.currentSidePanel()
currentContext := self.c.Context().CurrentSide()
switch currentContext.GetKey() {
// we make an exception for our files context, because it actually need to refresh its state afterwards.
case context.FILES_CONTEXT_KEY:
@@ -93,22 +81,3 @@ func (self *RenameSimilarityThresholdController) applyChange() error {
}
return nil
}
func (self *RenameSimilarityThresholdController) isShowingRenames() bool {
return lo.Contains(
CONTEXT_KEYS_SHOWING_RENAMES,
self.currentSidePanel().GetKey(),
)
}
func (self *RenameSimilarityThresholdController) currentSidePanel() types.Context {
currentContext := self.c.Context().CurrentStatic()
if currentContext.GetKey() == context.NORMAL_MAIN_CONTEXT_KEY ||
currentContext.GetKey() == context.NORMAL_SECONDARY_CONTEXT_KEY {
if sidePanelContext := self.c.Context().NextInStack(currentContext); sidePanelContext != nil {
return sidePanelContext
}
}
return currentContext
}
@@ -41,6 +41,11 @@ func (self *ScreenModeActions) rerenderViewsWithScreenModeDependentContent() {
self.rerenderView(context.GetView())
}
}
// Rerender the main view; for views that display a diff this is necessary in case a custom
// pager depends on the width of the view. For other views it isn't needed, but we don't bother
// making a distinction here, as rerendering the main view unnecessarily is not a big deal.
self.c.Context().CurrentSide().HandleRenderToMain()
}
func (self *ScreenModeActions) rerenderView(view *gocui.View) {
+17
View File
@@ -63,6 +63,11 @@ func (self *StatusController) GetKeybindings(opts types.KeybindingsOpts) []*type
Handler: func() error { self.switchToOrRotateAllBranchesLogs(); return nil },
Description: self.c.Tr.AllBranchesLogGraph,
},
{
Key: opts.GetKey(opts.Config.Status.AllBranchesLogGraphReverse),
Handler: func() error { self.switchToOrRotateAllBranchesLogsBackward(); return nil },
Description: self.c.Tr.AllBranchesLogGraphReverse,
},
}
return bindings
@@ -206,6 +211,18 @@ func (self *StatusController) switchToOrRotateAllBranchesLogs() {
self.showAllBranchLogs()
}
// Switches to the all branches view, or, if already on that view,
// rotates to the previous command in the list, and then renders it.
func (self *StatusController) switchToOrRotateAllBranchesLogsBackward() {
// A bit of a hack to ensure we only rotate to the previous branch log command
// if we currently are looking at a branch log. Otherwise, we should just show
// the current index (if we are coming from the dashboard).
if self.c.Views().Main.Title != self.c.Tr.StatusTitle {
self.c.Git().Branch.RotateAllBranchesLogIdxBackward()
}
self.showAllBranchLogs()
}
func (self *StatusController) showDashboard() {
versionStr := "master"
version, err := types.ParseVersionNumber(self.c.GetConfig().GetVersion())
+1 -1
View File
@@ -125,7 +125,7 @@ func (self *SubmodulesController) GetOnRenderToMain() func() {
if file == nil {
task = types.NewRenderStringTask(prefix)
} else {
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(file, false, !file.HasUnstagedChanges && file.HasStagedChanges)
cmdObj := self.c.Git().WorkingTree.WorktreeFileDiffCmdObj(file, false, !file.HasUnstagedChanges && file.HasStagedChanges, nil)
task = types.NewRunCommandTaskWithPrefix(cmdObj.GetCmd(), prefix)
}
}
@@ -80,12 +80,12 @@ func (self *SwitchToDiffFilesController) enter() error {
}
}
commitFilesContext.ClearFilter()
commitFilesContext.ReInit(ref, refsRange)
commitFilesContext.SetSelection(0)
commitFilesContext.SetCanRebase(canRebase)
commitFilesContext.SetParentContext(self.context)
commitFilesContext.SetWindowName(self.context.GetWindowName())
commitFilesContext.ClearSearchString()
commitFilesContext.GetView().TitlePrefix = self.context.GetView().TitlePrefix
self.c.Refresh(types.RefreshOptions{
+6 -1
View File
@@ -10,6 +10,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
)
type WorktreesController struct {
@@ -95,7 +96,11 @@ func (self *WorktreesController) GetOnRenderToMain() func() {
var builder strings.Builder
w := tabwriter.NewWriter(&builder, 0, 0, 2, ' ', 0)
_, _ = fmt.Fprintf(w, "%s:\t%s%s\n", self.c.Tr.Name, style.FgGreen.Sprint(worktree.Name), main)
_, _ = fmt.Fprintf(w, "%s:\t%s\n", self.c.Tr.Branch, style.FgYellow.Sprint(worktree.Branch))
branch := style.FgYellow.Sprint(worktree.Branch)
if worktree.Branch == "" && worktree.Head != "" {
branch = style.FgYellow.Sprintf("HEAD detached at %s", utils.ShortHash(worktree.Head))
}
_, _ = fmt.Fprintf(w, "%s:\t%s\n", self.c.Tr.Branch, branch)
_, _ = fmt.Fprintf(w, "%s:\t%s%s\n", self.c.Tr.Path, style.FgCyan.Sprint(worktree.Path), missing)
_ = w.Flush()
+25 -2
View File
@@ -15,6 +15,8 @@ type ICommitFileTree interface {
GetAllItems() []*CommitFileNode
GetAllFiles() []*models.CommitFile
GetRoot() *CommitFileNode
SetTextFilter(filter string, useFuzzySearch bool)
GetTextFilter() string
}
type CommitFileTree struct {
@@ -23,6 +25,8 @@ type CommitFileTree struct {
showTree bool
common *common.Common
collapsedPaths *CollapsedPaths
textFilter string
useFuzzySearch bool
}
func (self *CommitFileTree) CollapseAll() {
@@ -93,15 +97,34 @@ func (self *CommitFileTree) GetAllFiles() []*models.CommitFile {
return self.getFiles()
}
func (self *CommitFileTree) getFilesForDisplay() []*models.CommitFile {
files := self.getFiles()
if self.textFilter != "" {
files = filterCommitFilesByText(files, self.textFilter, self.useFuzzySearch)
}
return files
}
func (self *CommitFileTree) SetTree() {
filesForDisplay := self.getFilesForDisplay()
showRootItem := self.common.UserConfig().Gui.ShowRootItemInFileTree
if self.showTree {
self.tree = BuildTreeFromCommitFiles(self.getFiles(), showRootItem)
self.tree = BuildTreeFromCommitFiles(filesForDisplay, showRootItem)
} else {
self.tree = BuildFlatTreeFromCommitFiles(self.getFiles(), showRootItem)
self.tree = BuildFlatTreeFromCommitFiles(filesForDisplay, showRootItem)
}
}
func (self *CommitFileTree) SetTextFilter(filter string, useFuzzySearch bool) {
self.textFilter = filter
self.useFuzzySearch = useFuzzySearch
self.SetTree()
}
func (self *CommitFileTree) GetTextFilter() string {
return self.textFilter
}
func (self *CommitFileTree) IsCollapsed(path string) bool {
return self.collapsedPaths.IsCollapsed(path)
}
@@ -8,6 +8,8 @@ import (
"github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)
@@ -39,6 +41,8 @@ type CommitFileTreeViewModel struct {
// we set this to true when you're viewing the files within the checked-out branch's commits.
// If you're viewing the files of some random other branch we can't do any rebase stuff.
canRebase bool
searchHistory *utils.HistoryBuffer[string]
}
var _ ICommitFileTreeViewModel = &CommitFileTreeViewModel{}
@@ -52,6 +56,7 @@ func NewCommitFileTreeViewModel(getFiles func() []*models.CommitFile, common *co
ref: nil,
refRange: nil,
canRebase: false,
searchHistory: utils.NewHistoryBuffer[string](1000),
}
}
@@ -203,3 +208,51 @@ func (self *CommitFileTreeViewModel) SelectPath(filepath string, showRootItem bo
self.SetSelection(index)
}
}
// IFilterableContext methods
func (self *CommitFileTreeViewModel) SetFilter(filter string, useFuzzySearch bool) {
self.ICommitFileTree.SetTextFilter(filter, useFuzzySearch)
}
func (self *CommitFileTreeViewModel) GetFilter() string {
return self.ICommitFileTree.GetTextFilter()
}
func (self *CommitFileTreeViewModel) ClearFilter() {
selectedNode := self.GetSelected()
var selectedPath string
if selectedNode != nil {
selectedPath = selectedNode.GetInternalPath()
}
self.ICommitFileTree.SetTextFilter("", false)
if selectedPath != "" {
self.ExpandToPath(selectedPath)
if idx, found := self.GetIndexForPath(selectedPath); found {
self.SetSelection(idx)
return
}
}
self.ClampSelection()
}
func (self *CommitFileTreeViewModel) ReApplyFilter(useFuzzySearch bool) {
self.ICommitFileTree.SetTextFilter(self.ICommitFileTree.GetTextFilter(), useFuzzySearch)
}
func (self *CommitFileTreeViewModel) IsFiltering() bool {
return self.ICommitFileTree.GetTextFilter() != ""
}
// used for type switch
func (self *CommitFileTreeViewModel) IsFilterableContext() {}
func (self *CommitFileTreeViewModel) FilterPrefix(tr *i18n.TranslationSet) string {
return tr.FilterPrefix
}
func (self *CommitFileTreeViewModel) GetSearchHistory() *utils.HistoryBuffer[string] {
return self.searchHistory
}
+48
View File
@@ -0,0 +1,48 @@
package filetree
import (
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/sahilm/fuzzy"
"github.com/samber/lo"
)
type filePathSource struct {
files []*models.File
}
func (s *filePathSource) String(i int) string {
return s.files[i].Path
}
func (s *filePathSource) Len() int {
return len(s.files)
}
func filterFilesByText(files []*models.File, filter string, useFuzzySearch bool) []*models.File {
source := &filePathSource{files: files}
matches := utils.FindFrom(filter, source, useFuzzySearch)
return lo.Map(matches, func(match fuzzy.Match, _ int) *models.File {
return files[match.Index]
})
}
type commitFilePathSource struct {
files []*models.CommitFile
}
func (s *commitFilePathSource) String(i int) string {
return s.files[i].Path
}
func (s *commitFilePathSource) Len() int {
return len(s.files)
}
func filterCommitFilesByText(files []*models.CommitFile, filter string, useFuzzySearch bool) []*models.CommitFile {
source := &commitFilePathSource{files: files}
matches := utils.FindFrom(filter, source, useFuzzySearch)
return lo.Map(matches, func(match fuzzy.Match, _ int) *models.CommitFile {
return files[match.Index]
})
}
+29 -8
View File
@@ -46,8 +46,10 @@ type IFileTree interface {
GetFile(path string) *models.File
GetAllItems() []*FileNode
GetAllFiles() []*models.File
GetFilter() FileTreeDisplayFilter
GetStatusFilter() FileTreeDisplayFilter
GetRoot() *FileNode
SetTextFilter(filter string, useFuzzySearch bool)
GetTextFilter() string
}
type FileTree struct {
@@ -57,6 +59,8 @@ type FileTree struct {
common *common.Common
filter FileTreeDisplayFilter
collapsedPaths *CollapsedPaths
textFilter string
useFuzzySearch bool
}
var _ IFileTree = &FileTree{}
@@ -80,24 +84,31 @@ func (self *FileTree) ExpandToPath(path string) {
}
func (self *FileTree) getFilesForDisplay() []*models.File {
var files []*models.File
switch self.filter {
case DisplayAll:
return self.getFiles()
files = self.getFiles()
case DisplayStaged:
return self.FilterFiles(func(file *models.File) bool { return file.HasStagedChanges })
files = self.FilterFiles(func(file *models.File) bool { return file.HasStagedChanges })
case DisplayUnstaged:
return self.FilterFiles(func(file *models.File) bool { return file.HasUnstagedChanges })
files = self.FilterFiles(func(file *models.File) bool { return file.HasUnstagedChanges })
case DisplayTracked:
// untracked but staged files are technically not tracked by git
// but including such files in the filtered mode helps see what files are getting committed
return self.FilterFiles(func(file *models.File) bool { return file.Tracked || file.HasStagedChanges })
files = self.FilterFiles(func(file *models.File) bool { return file.Tracked || file.HasStagedChanges })
case DisplayUntracked:
return self.FilterFiles(func(file *models.File) bool { return !(file.Tracked || file.HasStagedChanges) })
files = self.FilterFiles(func(file *models.File) bool { return !(file.Tracked || file.HasStagedChanges) })
case DisplayConflicted:
return self.FilterFiles(func(file *models.File) bool { return file.HasMergeConflicts })
files = self.FilterFiles(func(file *models.File) bool { return file.HasMergeConflicts })
default:
panic(fmt.Sprintf("Unexpected files display filter: %d", self.filter))
}
if self.textFilter != "" {
files = filterFilesByText(files, self.textFilter, self.useFuzzySearch)
}
return files
}
func (self *FileTree) ForceShowUntracked() bool {
@@ -210,6 +221,16 @@ func (self *FileTree) CollapsedPaths() *CollapsedPaths {
return self.collapsedPaths
}
func (self *FileTree) GetFilter() FileTreeDisplayFilter {
func (self *FileTree) GetStatusFilter() FileTreeDisplayFilter {
return self.filter
}
func (self *FileTree) SetTextFilter(filter string, useFuzzySearch bool) {
self.textFilter = filter
self.useFuzzySearch = useFuzzySearch
self.SetTree()
}
func (self *FileTree) GetTextFilter() string {
return self.textFilter
}
+53 -2
View File
@@ -8,6 +8,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)
@@ -24,6 +25,7 @@ type FileTreeViewModel struct {
sync.RWMutex
types.IListCursor
IFileTree
searchHistory *utils.HistoryBuffer[string]
}
var _ IFileTreeViewModel = &FileTreeViewModel{}
@@ -32,8 +34,9 @@ func NewFileTreeViewModel(getFiles func() []*models.File, common *common.Common,
fileTree := NewFileTree(getFiles, common, showTree)
listCursor := traits.NewListCursor(fileTree.Len)
return &FileTreeViewModel{
IFileTree: fileTree,
IListCursor: listCursor,
IFileTree: fileTree,
IListCursor: listCursor,
searchHistory: utils.NewHistoryBuffer[string](1000),
}
}
@@ -220,3 +223,51 @@ func (self *FileTreeViewModel) ExpandAll() {
self.SetSelectedLineIdx(index)
}
}
// IFilterableContext methods
func (self *FileTreeViewModel) SetFilter(filter string, useFuzzySearch bool) {
self.IFileTree.SetTextFilter(filter, useFuzzySearch)
}
func (self *FileTreeViewModel) GetFilter() string {
return self.IFileTree.GetTextFilter()
}
func (self *FileTreeViewModel) ClearFilter() {
selectedNode := self.GetSelected()
var selectedPath string
if selectedNode != nil {
selectedPath = selectedNode.GetInternalPath()
}
self.IFileTree.SetTextFilter("", false)
if selectedPath != "" {
self.ExpandToPath(selectedPath)
if idx, found := self.GetIndexForPath(selectedPath); found {
self.SetSelection(idx)
return
}
}
self.ClampSelection()
}
func (self *FileTreeViewModel) ReApplyFilter(useFuzzySearch bool) {
self.IFileTree.SetTextFilter(self.IFileTree.GetTextFilter(), useFuzzySearch)
}
func (self *FileTreeViewModel) IsFiltering() bool {
return self.IFileTree.GetTextFilter() != ""
}
// used for type switch
func (self *FileTreeViewModel) IsFilterableContext() {}
func (self *FileTreeViewModel) FilterPrefix(tr *i18n.TranslationSet) string {
return tr.FilterPrefix
}
func (self *FileTreeViewModel) GetSearchHistory() *utils.HistoryBuffer[string] {
return self.searchHistory
}
+20 -1
View File
@@ -377,7 +377,7 @@ func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, contextKey types.Context
gui.g.SetOpenHyperlinkFunc(func(url string, viewname string) error {
if strings.HasPrefix(url, "lazygit-edit:") {
re := regexp.MustCompile(`^lazygit-edit://(.+?)(?::(\d+))?$`)
re := regexp.MustCompile(`^lazygit-edit://(.+?)(?::(\d*))?$`)
matches := re.FindStringSubmatch(url)
if matches == nil {
return fmt.Errorf(gui.Tr.InvalidLazygitEditURL, url)
@@ -842,6 +842,25 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error {
g.ErrorHandler = gui.PopupHandler.ErrorHandler
gui.g.ShouldHandleMouseEvent = func(view *gocui.View, key gocui.Key) bool {
if gui.helpers.Confirmation.IsPopupPanelFocused() && gui.currentViewName() != view.Name() &&
!gocui.IsMouseScrollKey(key) {
// we ignore click events on views that aren't popup panels, when a popup panel is focused.
// Unless both the current view and the clicked-on view are either commit message or commit
// description, or a prompt and the suggestions view, because we want to allow switching
// between those two views by clicking.
isCommitMessageOrSuggestionsView := func(viewName string) bool {
return viewName == "commitMessage" || viewName == "commitDescription" ||
viewName == "prompt" || viewName == "suggestions"
}
if !isCommitMessageOrSuggestionsView(gui.currentViewName()) || !isCommitMessageOrSuggestionsView(view.Name()) {
return false
}
}
return true
}
// if the deadlock package wants to report a deadlock, we first need to
// close the gui so that we can actually read what it prints.
deadlock.Opts.LogBuf = utils.NewOnceWriter(os.Stderr, func() {
-22
View File
@@ -499,29 +499,7 @@ func (gui *Gui) SetKeybinding(binding *types.Binding) error {
return gui.g.SetKeybinding(binding.ViewName, binding.Key, binding.Modifier, gui.wrappedHandler(handler))
}
// warning: mutates the binding
func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error {
baseHandler := binding.Handler
newHandler := func(opts gocui.ViewMouseBindingOpts) error {
if gui.helpers.Confirmation.IsPopupPanelFocused() && gui.currentViewName() != binding.ViewName &&
!gocui.IsMouseScrollKey(opts.Key) {
// we ignore click events on views that aren't popup panels, when a popup panel is focused.
// Unless both the current view and the clicked-on view are either commit message or commit
// description, or a prompt and the suggestions view, because we want to allow switching
// between those two views by clicking.
isCommitMessageOrSuggestionsView := func(viewName string) bool {
return viewName == "commitMessage" || viewName == "commitDescription" ||
viewName == "prompt" || viewName == "suggestions"
}
if !isCommitMessageOrSuggestionsView(gui.currentViewName()) || !isCommitMessageOrSuggestionsView(binding.ViewName) {
return nil
}
}
return baseHandler(opts)
}
binding.Handler = newHandler
return gui.g.SetViewClickBinding(binding)
}
+2
View File
@@ -61,6 +61,8 @@ func (gui *Gui) createMenu(opts types.CreateMenuOptions) error {
gui.State.Contexts.Menu.SetKeybindingsTakePrecedence(!opts.KeepConflictingKeybindings)
gui.State.Contexts.Menu.SetSelection(0)
gui.Views.Menu.SetOriginY(0)
gui.Views.Menu.Title = opts.Title
gui.Views.Menu.FgColor = theme.GocuiDefaultTextColor
+30 -6
View File
@@ -57,7 +57,6 @@ func getBranchDisplayStrings(
showCommitHash := fullDescription || userConfig.Gui.ShowBranchCommitHash
branchStatus := BranchStatus(b, itemOperation, tr, now, userConfig)
divergence := divergenceStr(b, itemOperation, tr, userConfig)
worktreeIcon := lo.Ternary(icons.IsIconEnabled(), icons.LINKED_WORKTREE_ICON, fmt.Sprintf("(%s)", tr.LcWorktree))
// Recency is always three characters, plus one for the space
availableWidth := viewWidth - 4
@@ -72,17 +71,42 @@ func getBranchDisplayStrings(
}
paddingNeededForDivergence := availableWidth
if checkedOutByWorkTree {
availableWidth -= utils.StringWidth(worktreeIcon) + 1
displayName := b.Name
if b.DisplayName != "" {
displayName = b.DisplayName
}
if len(branchStatus) > 0 {
availableWidth -= utils.StringWidth(utils.Decolorise(branchStatus)) + 1
}
displayName := b.Name
if b.DisplayName != "" {
displayName = b.DisplayName
worktreeIcon := ""
if checkedOutByWorkTree {
if wt, ok := git_commands.WorktreeForBranch(b, worktrees); ok && wt.Name != b.Name {
if icons.IsIconEnabled() {
worktreeIcon = fmt.Sprintf("(%s %s)", icons.LINKED_WORKTREE_ICON, wt.Name)
} else {
worktreeIcon = fmt.Sprintf("(%s %s)", tr.LcWorktree, wt.Name)
}
// If the worktree name doesn't fit in the available width, omit it
remaining := availableWidth - utils.StringWidth(worktreeIcon) - 1
if remaining < utils.StringWidth(displayName) {
if icons.IsIconEnabled() {
worktreeIcon = icons.LINKED_WORKTREE_ICON
} else {
worktreeIcon = fmt.Sprintf("(%s)", tr.LcWorktree)
}
}
} else {
if icons.IsIconEnabled() {
worktreeIcon = icons.LINKED_WORKTREE_ICON
} else {
worktreeIcon = fmt.Sprintf("(%s)", tr.LcWorktree)
}
}
availableWidth -= utils.StringWidth(worktreeIcon) + 1
}
nameTextStyle := GetBranchTextStyle(b.Name)
+4 -4
View File
@@ -62,7 +62,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
useIcons: false,
checkedOutByWorktree: true,
showDivergenceCfg: "none",
expected: []string{"1m", "branch_name (worktree)"},
expected: []string{"1m", "branch_name (worktree other-worktree)"},
},
{
branch: &models.Branch{Name: "branch_name", Recency: "1m"},
@@ -72,7 +72,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
useIcons: true,
checkedOutByWorktree: true,
showDivergenceCfg: "none",
expected: []string{"1m", "󰘬", "branch_name 󰌹"},
expected: []string{"1m", "󰘬", "branch_name (󰌹 other-worktree)"},
},
{
branch: &models.Branch{
@@ -104,7 +104,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
useIcons: false,
checkedOutByWorktree: true,
showDivergenceCfg: "none",
expected: []string{"1m", "branch_name (worktree) ↓5↑3"},
expected: []string{"1m", "branch_name (worktree other-worktree) ↓5↑3"},
},
{
branch: &models.Branch{
@@ -347,7 +347,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
worktrees := []*models.Worktree{}
if s.checkedOutByWorktree {
worktrees = append(worktrees, &models.Worktree{Branch: s.branch.Name})
worktrees = append(worktrees, &models.Worktree{Branch: s.branch.Name, Name: "other-worktree"})
}
t.Run(fmt.Sprintf("getBranchDisplayStrings_%d", i), func(t *testing.T) {
+6 -1
View File
@@ -385,7 +385,12 @@ func displayCommit(
actionString := ""
if commit.Action != models.ActionNone {
actionString = actionColorMap(commit.Action, commit.Status).Sprint(commit.Action.String())
actionStr := commit.Action.String()
// Only show the flag for fixup commands (where -C changes the meaning)
if commit.ActionFlag != "" && commit.Action == todo.Fixup {
actionStr += " " + commit.ActionFlag
}
actionString = actionColorMap(commit.Action, commit.Status).Sprint(actionStr)
}
tagString := ""
+15 -3
View File
@@ -6,6 +6,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/theme"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)
@@ -40,12 +41,23 @@ func GetWorktreeDisplayString(tr *i18n.TranslationSet, worktree *models.Worktree
}
name := worktree.Name
if worktree.IsMain {
name += " " + tr.MainWorktree
}
if worktree.IsPathMissing && !icons.IsIconEnabled() {
name += " " + tr.MissingWorktree
}
res = append(res, textStyle.Sprint(name))
var branch string
if worktree.Branch != "" {
branch = style.FgCyan.Sprint(worktree.Branch)
} else if worktree.Head != "" {
branch = style.FgYellow.Sprint("HEAD detached at " + utils.ShortHash(worktree.Head))
}
res = append(res, branch+mainWorktreeLabel(tr, worktree))
return res
}
func mainWorktreeLabel(tr *i18n.TranslationSet, worktree *models.Worktree) string {
if worktree.IsMain {
return style.FgDefault.Sprint(" " + tr.MainWorktree)
}
return ""
}
+111
View File
@@ -0,0 +1,111 @@
package presentation
import (
"testing"
"github.com/gookit/color"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/stretchr/testify/assert"
"github.com/xo/terminfo"
)
func Test_GetWorktreeDisplayString(t *testing.T) {
tr := &i18n.TranslationSet{
MainWorktree: "(main worktree)",
MissingWorktree: "(missing)",
}
scenarios := []struct {
testName string
worktree *models.Worktree
expected []string
}{
{
testName: "Current worktree on a branch",
worktree: &models.Worktree{
Name: "my-worktree",
Branch: "my-branch",
IsCurrent: true,
},
expected: []string{" *", "my-worktree", "my-branch"},
},
{
testName: "Non-current worktree on a branch",
worktree: &models.Worktree{
Name: "my-worktree",
Branch: "feature-branch",
},
expected: []string{"", "my-worktree", "feature-branch"},
},
{
testName: "Main worktree on a branch",
worktree: &models.Worktree{
Name: "repo",
Branch: "main",
IsMain: true,
},
expected: []string{"", "repo", "main (main worktree)"},
},
{
testName: "Detached HEAD worktree",
worktree: &models.Worktree{
Name: "my-worktree",
Head: "d85cc9d281fa6ae1665c68365fc70e75e82a042d",
},
expected: []string{"", "my-worktree", "HEAD detached at d85cc9d2"},
},
{
testName: "Detached HEAD on main worktree",
worktree: &models.Worktree{
Name: "repo",
IsMain: true,
Head: "d85cc9d281fa6ae1665c68365fc70e75e82a042d",
},
expected: []string{"", "repo", "HEAD detached at d85cc9d2 (main worktree)"},
},
{
testName: "Worktree with branch takes precedence over head",
worktree: &models.Worktree{
Name: "my-worktree",
Branch: "my-branch",
Head: "d85cc9d281fa6ae1665c68365fc70e75e82a042d",
},
expected: []string{"", "my-worktree", "my-branch"},
},
{
testName: "Missing worktree",
worktree: &models.Worktree{
Name: "my-worktree",
IsPathMissing: true,
Head: "d85cc9d281fa6ae1665c68365fc70e75e82a042d",
},
expected: []string{"", "my-worktree (missing)", "HEAD detached at d85cc9d2"},
},
{
testName: "Worktree with no branch and no head",
worktree: &models.Worktree{
Name: "my-worktree",
},
expected: []string{"", "my-worktree", ""},
},
{
testName: "Main worktree with no branch and no head",
worktree: &models.Worktree{
Name: "my-worktree",
IsMain: true,
},
expected: []string{"", "my-worktree", " (main worktree)"},
},
}
oldColorLevel := color.ForceSetColorLevel(terminfo.ColorLevelNone)
defer color.ForceSetColorLevel(oldColorLevel)
for _, s := range scenarios {
t.Run(s.testName, func(t *testing.T) {
result := GetWorktreeDisplayString(tr, s.worktree)
assert.Equal(t, s.expected, result)
})
}
}
-1
View File
@@ -102,7 +102,6 @@ func (gui *Gui) createAllViews() error {
for _, view := range []*gocui.View{gui.Views.Main, gui.Views.Secondary, gui.Views.Staging, gui.Views.StagingSecondary, gui.Views.PatchBuilding, gui.Views.PatchBuildingSecondary, gui.Views.MergeConflicts} {
view.Wrap = true
view.IgnoreCarriageReturns = true
view.UnderlineHyperLinksOnlyOnHover = true
view.AutoRenderHyperLinks = true
}
+39 -7
View File
@@ -164,7 +164,12 @@ type TranslationSet struct {
CannotSquashOrFixupMergeCommit string
Fixup string
FixupTooltip string
SureFixupThisCommit string
FixupKeepMessage string
FixupKeepMessageTooltip string
SetFixupMessage string
SetFixupMessageTooltip string
FixupDiscardMessage string
FixupDiscardMessageTooltip string
SureSquashThisCommit string
Squash string
PickCommitTooltip string
@@ -274,6 +279,7 @@ type TranslationSet struct {
ConfirmQuit string
SwitchRepo string
AllBranchesLogGraph string
AllBranchesLogGraphReverse string
UnsupportedGitService string
CopyPullRequestURL string
NoBranchOnRemote string
@@ -295,6 +301,8 @@ type TranslationSet struct {
ToggleSelectHunkTooltip string
HunkStagingHint string
ToggleSelectionForPatch string
RemoveSelectionFromPatch string
RemoveSelectionFromPatchTooltip string
EditHunk string
EditHunkTooltip string
ToggleStagingView string
@@ -316,6 +324,8 @@ type TranslationSet struct {
ViewRevertOptions string
NotMergingOrRebasing string
AlreadyRebasing string
NotMidRebase string
MustSelectFixupCommit string
RecentRepos string
MergeOptionsTitle string
RebaseOptionsTitle string
@@ -427,10 +437,12 @@ type TranslationSet struct {
CheckoutCommitFileTooltip string
CannotCheckoutWithModifiedFilesErr string
CanOnlyDiscardFromLocalCommits string
CannotDiscardFromMultipleCommits string
Remove string
DiscardOldFileChangeTooltip string
DiscardFileChangesTitle string
DiscardFileChangesPrompt string
DiscardFileChangesPromptResetPatch string
DisabledForGPG string
CreateRepo string
BareRepo string
@@ -679,6 +691,9 @@ type TranslationSet struct {
BranchUnknown string
DiscardChangeTitle string
DiscardChangePrompt string
DiscardLinesFromCommitTitle string
DiscardLinesFromCommitPrompt string
DiscardLinesFromCommitPromptWithReset string
CreateNewBranchFromCommit string
BuildingPatch string
ViewCommits string
@@ -897,7 +912,6 @@ type TranslationSet struct {
SelectedItemIsNotABranch string
SelectedItemDoesNotHaveFiles string
MultiSelectNotSupportedForSubmodules string
OldCherryPickKeyWarning string
CommandDoesNotSupportOpeningInEditor string
CustomCommands string
NoApplicableCommandsInThisContext string
@@ -966,6 +980,7 @@ type Actions struct {
CheckoutFile string
SquashCommitDown string
FixupCommit string
FixupCommitKeepMessage string
RewordCommit string
DropCommit string
EditCommit string
@@ -1000,6 +1015,7 @@ type Actions struct {
ResolveConflictByDeletingFile string
NotEnoughContextToStage string
NotEnoughContextToDiscard string
NotEnoughContextToRemoveLines string
NotEnoughContextForCustomPatch string
IgnoreExcludeFile string
IgnoreFileErr string
@@ -1260,7 +1276,12 @@ func EnglishTranslationSet() *TranslationSet {
CannotSquashOrFixupFirstCommit: "There's no commit below to squash into",
CannotSquashOrFixupMergeCommit: "Cannot squash or fixup a merge commit",
Fixup: "Fixup",
SureFixupThisCommit: "Are you sure you want to 'fixup' the selected commit(s) into the commit below?",
FixupKeepMessage: "Fixup and use this commit's message",
FixupKeepMessageTooltip: "Squash the selected commit into the commit below, using this commit's message, discarding the message of the commit below.",
SetFixupMessage: "Set fixup message",
SetFixupMessageTooltip: "Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message.",
FixupDiscardMessage: "Fixup and discard this commit's message",
FixupDiscardMessageTooltip: "Squash the selected commit into the commit below, discarding this commit's message.",
SureSquashThisCommit: "Are you sure you want to squash the selected commit(s) into the commit below?",
Squash: "Squash",
PickCommitTooltip: "Mark the selected commit to be picked (when mid-rebase). This means that the commit will be retained upon continuing the rebase.",
@@ -1369,6 +1390,7 @@ func EnglishTranslationSet() *TranslationSet {
ConfirmQuit: `Are you sure you want to quit?`,
SwitchRepo: `Switch to a recent repo`,
AllBranchesLogGraph: `Show/cycle all branch logs`,
AllBranchesLogGraphReverse: `Show/cycle all branch logs (reverse)`,
UnsupportedGitService: `Unsupported git service`,
CreatePullRequest: `Create pull request`,
CopyPullRequestURL: `Copy pull request URL to clipboard`,
@@ -1393,6 +1415,8 @@ func EnglishTranslationSet() *TranslationSet {
ToggleSelectHunkTooltip: "Toggle line-by-line vs. hunk selection mode.",
HunkStagingHint: englishHunkStagingHint,
ToggleSelectionForPatch: `Toggle lines in patch`,
RemoveSelectionFromPatch: `Remove lines from commit`,
RemoveSelectionFromPatchTooltip: "Remove the selected lines from this commit. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes these lines.",
EditHunk: `Edit hunk`,
EditHunkTooltip: "Edit selected hunk in external editor.",
ToggleStagingView: "Switch view",
@@ -1412,6 +1436,8 @@ func EnglishTranslationSet() *TranslationSet {
ViewRevertOptions: "View revert options",
NotMergingOrRebasing: "You are currently neither rebasing nor merging",
AlreadyRebasing: "Can't perform this action during a rebase",
NotMidRebase: "This action only works during an interactive rebase",
MustSelectFixupCommit: "This action only works on fixup commits",
RecentRepos: "Recent repositories",
MergeOptionsTitle: "Merge options",
RebaseOptionsTitle: "Rebase options",
@@ -1528,10 +1554,12 @@ func EnglishTranslationSet() *TranslationSet {
CheckoutCommitFileTooltip: "Checkout file. This replaces the file in your working tree with the version from the selected commit.",
CannotCheckoutWithModifiedFilesErr: "You have local modifications for the file(s) you are trying to check out. You need to stash or discard these first.",
CanOnlyDiscardFromLocalCommits: "Changes can only be discarded from local commits",
CannotDiscardFromMultipleCommits: "Changes cannot be discarded from a multiselection of commits",
Remove: "Remove",
DiscardOldFileChangeTooltip: "Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file.",
DiscardFileChangesTitle: "Discard file changes",
DiscardFileChangesPrompt: "Are you sure you want to remove changes to the selected file(s) from this commit?\n\nThis action will start a rebase, reverting these file changes. Be aware that if subsequent commits depend on these changes, you may need to resolve conflicts.\nNote: This will also reset any active custom patches.",
DiscardFileChangesPrompt: "Are you sure you want to discard changes to the selected file(s) from this commit?\n\nThis action will start a rebase, reverting these file changes. Be aware that if subsequent commits depend on these changes, you may need to resolve conflicts.",
DiscardFileChangesPromptResetPatch: "Are you sure you want to discard changes to the selected file(s) from this commit?\n\nThis action will start a rebase, reverting these file changes. Be aware that if subsequent commits depend on these changes, you may need to resolve conflicts.\n\nNote: This will reset the active custom patch!",
DisabledForGPG: "Feature not available for users using GPG.\n\nIf you are using a passphrase agent (e.g. gpg-agent) so that you don't have to type your passphrase when signing, you can enable this feature by adding\n\ngit:\n overrideGpg: true\n\nto your lazygit config file.",
CreateRepo: "Not in a git repository. Create a new git repository? (y/N): ",
BareRepo: "You've attempted to open Lazygit in a bare repo but Lazygit does not yet support bare repos. Open most recent repo? (y/n) ",
@@ -1756,7 +1784,7 @@ func EnglishTranslationSet() *TranslationSet {
ShowingGitDiff: "Showing output for:",
ShowingDiffForRange: "Showing diff for range",
CommitDiff: "Commit diff",
CopyCommitHashToClipboard: "Copy commit hash to clipboard",
CopyCommitHashToClipboard: "Copy abbreviated commit hash to clipboard",
CommitHash: "Commit hash",
CommitURL: "Commit URL",
PasteCommitMessageFromClipboard: "Paste commit message from clipboard",
@@ -1780,6 +1808,9 @@ func EnglishTranslationSet() *TranslationSet {
BranchUnknown: "Branch unknown",
DiscardChangeTitle: "Discard change",
DiscardChangePrompt: "Are you sure you want to discard this change (git reset)? It is irreversible.\nTo disable this dialogue set the config key of 'gui.skipDiscardChangeWarning' to true",
DiscardLinesFromCommitTitle: "Discard lines from commit",
DiscardLinesFromCommitPrompt: "Are you sure you want to discard the selected lines from this commit?",
DiscardLinesFromCommitPromptWithReset: "Are you sure you want to discard the selected lines from this commit?\n\nNote: This will reset the active custom patch!",
CreateNewBranchFromCommit: "Create new branch off of commit",
BuildingPatch: "Building patch",
ViewCommits: "View commits",
@@ -1959,7 +1990,7 @@ func EnglishTranslationSet() *TranslationSet {
CantDeleteMainWorktree: "You cannot remove the main worktree!",
NoWorktreesThisRepo: "No worktrees",
MissingWorktree: "(missing)",
MainWorktree: "(main)",
MainWorktree: "(main worktree)",
NewWorktree: "New worktree",
NewWorktreePath: "New worktree path",
NewWorktreeBase: "New worktree base ref",
@@ -1993,7 +2024,6 @@ func EnglishTranslationSet() *TranslationSet {
SelectedItemIsNotABranch: "Selected item is not a branch",
SelectedItemDoesNotHaveFiles: "Selected item does not have files to view",
MultiSelectNotSupportedForSubmodules: "Multiselection not supported for submodules",
OldCherryPickKeyWarning: "The 'c' key is no longer the default key for copying commits to cherry pick. Please use `{{.copy}}` instead (and `{{.paste}}` to paste). The reason for this change is that the 'v' key for selecting a range of lines when staging is now also used for selecting a range of lines in any list view, meaning that we needed to find a new key for pasting commits, and if we're going to now use `{{.paste}}` for pasting commits, we may as well use `{{.copy}}` for copying them. If you want to configure the keybindings to get the old behaviour, set the following in your config:\n\nkeybinding:\n universal:\n toggleRangeSelect: <something other than v>\n commits:\n cherryPickCopy: 'c'\n pasteCommits: 'v'",
CommandDoesNotSupportOpeningInEditor: "This command doesn't support switching to the editor",
CustomCommands: "Custom commands",
NoApplicableCommandsInThisContext: "(No applicable commands in this context)",
@@ -2025,6 +2055,7 @@ func EnglishTranslationSet() *TranslationSet {
CheckoutFile: "Checkout file",
SquashCommitDown: "Squash commit down",
FixupCommit: "Fixup commit",
FixupCommitKeepMessage: "Fixup commit (keep message)",
RewordCommit: "Reword commit",
DropCommit: "Drop commit",
EditCommit: "Edit commit",
@@ -2061,6 +2092,7 @@ func EnglishTranslationSet() *TranslationSet {
ResolveConflictByDeletingFile: "Resolve by deleting file",
NotEnoughContextToStage: "Staging or unstaging changes is not possible with a diff context size of 0. Increase the context using '%s'.",
NotEnoughContextToDiscard: "Discarding changes is not possible with a diff context size of 0. Increase the context using '%s'.",
NotEnoughContextToRemoveLines: "Removing lines from a commit is not possible with a diff context size of 0. Increase the context using '%s'.",
NotEnoughContextForCustomPatch: "Creating custom patches is not possible with a diff context size of 0. Increase the context using '%s'.",
IgnoreExcludeFile: "Ignore or exclude file",
IgnoreFileErr: "Cannot ignore .gitignore",
+2 -5
View File
@@ -44,6 +44,7 @@
"ToggleStagedAll": "すべてステージ",
"ToggleStagedAllTooltip": "ワーキングツリー内のすべてのファイルのステージ/アンステージを切り替えます。",
"ToggleTreeView": "ファイルツリービューを切り替え",
"ToggleTreeViewTooltip": "ファイル表示をフラット表示とツリー表示で切り替えます。フラット表示はすべてのファイルパスを一覧で表示し、ツリー表示はディレクトリごとにファイルをグループ化します。\n\nデフォルトは設定ファイル内の 'gui.showFileTree' キーで変更できます。",
"OpenDiffTool": "外部差分ツールを開く(git difftool)",
"OpenMergeTool": "外部マージツールを開く",
"Refresh": "更新",
@@ -132,6 +133,7 @@
"NewBranchFromStashTooltip": "選択したスタッシュエントリから新しいブランチを作成します。これは、スタッシュエントリが作成されたコミットをgitがチェックアウトし、そのコミットから新しいブランチを作成した後、スタッシュエントリを追加のコミットとして新しいブランチに適用することで機能します。",
"MoveCommitsToNewBranch": "コミットを新しいブランチに移動",
"MoveCommitsToNewBranchFromBaseItem": "ベースブランチから新規ブランチ (%s)",
"CannotMoveCommitsBehindUpstream": "アップストリームブランチに遅れているブランチからコミットを移動することはできません",
"CannotMoveCommitsNoUnpushedCommits": "新しいブランチに移動するプッシュされていないコミットはありません",
"NoBranchesThisRepo": "このリポジトリにはブランチがありません",
"CommitWithoutMessageErr": "コミットメッセージなしでコミットすることはできません",
@@ -144,7 +146,6 @@
"CannotSquashOrFixupMergeCommit": "マージコミットをスカッシュまたはフィックスアップすることはできません",
"Fixup": "フィックスアップ",
"FixupTooltip": "選択したコミットをその下のコミットにマージします。フィックスアップはスカッシュと似ていますが、選択したコミットのメッセージは破棄され、下のコミットのメッセージのみが保持されます。",
"SureFixupThisCommit": "選択したコミットを下のコミットに'フィックスアップ'してもよろしいですか?",
"SureSquashThisCommit": "選択したコミットを下のコミットにスカッシュしてもよろしいですか?",
"Squash": "スカッシュ",
"PickCommitTooltip": "選択したコミットをピックするようにマークします(リベース中)。これは、リベースを続行すると、コミットが保持されることを意味します。",
@@ -389,7 +390,6 @@
"Remove": "削除",
"DiscardOldFileChangeTooltip": "このコミットのこのファイルへの変更を破棄します。これはバックグラウンドで対話的なリベースを実行するため、後のコミットでもこのファイルが変更されている場合、マージコンフリクトが発生する可能性があります。",
"DiscardFileChangesTitle": "ファイルの変更を破棄",
"DiscardFileChangesPrompt": "このコミットから選択したファイルの変更を削除してよろしいですか?\n\nこのアクションはリベースを開始し、これらのファイル変更を元に戻します。後続のコミットがこれらの変更に依存している場合、コンフリクトを解決する必要があるかもしれないことに注意してください。\n注意:これにより、アクティブなカスタムパッチもリセットされます。",
"DisabledForGPG": "GPGを使用しているユーザーには利用できない機能です。\n\nパスフレーズエージェント(gpg-agentなど)を使用して署名時にパスフレーズを入力しなくても済むようにしている場合は、lazygitの設定ファイルに\n\ngit:\n overrideGpg: true\n\nを追加することでこの機能を有効にできます。",
"CreateRepo": "Gitリポジトリがありません。新しいgitリポジトリを作成しますか? (y/N): ",
"BareRepo": "ベアリポジトリでLazygitを開こうとしましたが、Lazygitはまだベアリポジトリをサポートしていません。最近のリポジトリを開いてよろしいですか? (y/n) ",
@@ -596,7 +596,6 @@
"ShowingGitDiff": "出力を表示:",
"ShowingDiffForRange": "範囲の差分を表示",
"CommitDiff": "コミットの差分",
"CopyCommitHashToClipboard": "コミットハッシュをクリップボードにコピー",
"CommitHash": "コミットハッシュ",
"CommitURL": "コミットURL",
"PasteCommitMessageFromClipboard": "クリップボードからコミットメッセージを貼り付け",
@@ -780,7 +779,6 @@
"CantDeleteMainWorktree": "メインのワークツリーは削除できません!",
"NoWorktreesThisRepo": "ワークツリーがありません",
"MissingWorktree": "(見つかりません)",
"MainWorktree": "(メイン)",
"NewWorktree": "新しいワークツリー",
"NewWorktreePath": "新しいワークツリーのパス",
"NewWorktreeBase": "新しいワークツリーのベース参照",
@@ -814,7 +812,6 @@
"SelectedItemIsNotABranch": "選択された項目はブランチではありません",
"SelectedItemDoesNotHaveFiles": "選択された項目には表示するファイルがありません",
"MultiSelectNotSupportedForSubmodules": "サブモジュールでは複数選択はサポートされていません",
"OldCherryPickKeyWarning": "'c'キーは現在、コミットのコピー(チェリーピック)のデフォルトキーではなくなりました。代わりに`{{.copy}}`キーを使用してコピーし、`{{.paste}}`キーでペーストしてください。\n\nこの変更理由は以下の通りです:\n- 以前は'v'キーがステージング時の行選択にのみ使用されていましたが、現在はすべてのリストビューで範囲選択に使われています\n- そのため、コミットペースト用の新しいキーが必要になり、`{{.paste}}`をペーストに使うなら、`{{.copy}}`をコピーに使う方が直感的です\n\n以前の動作に戻したい場合は、設定ファイルに以下を追加してください:\n\nkeybinding:\n universal:\n toggleRangeSelect: <v以外の何か>\n commits:\n cherryPickCopy: 'c'\n pasteCommits: 'v'",
"CommandDoesNotSupportOpeningInEditor": "このコマンドはエディタへの切り替えをサポートしていません",
"CustomCommands": "カスタムコマンド",
"NoApplicableCommandsInThisContext": "(このコンテキストでは適用可能なコマンドはありません)",
-3
View File
@@ -77,7 +77,6 @@
"CloseCancel": "닫기/취소",
"Confirm": "확인",
"Quit": "종료",
"SureFixupThisCommit": "Are you sure you want to 'fixup' this commit? It will be merged into the commit below",
"SureSquashThisCommit": "Are you sure you want to squash this commit into the commit below?",
"Squash": "스쿼시",
"PickCommitTooltip": "Pick commit (when mid-rebase)",
@@ -179,7 +178,6 @@
"CheckoutCommitFileTooltip": "Checkout file",
"DiscardOldFileChangeTooltip": "Discard this commit's changes to this file",
"DiscardFileChangesTitle": "파일 변경 사항 버리기",
"DiscardFileChangesPrompt": "Are you sure you want to discard this commit's changes to this file? If this file was created in this commit, it will be deleted",
"Discard": "View 'discard changes' options",
"Cancel": "취소",
"DiscardAllChanges": "모든 변경사항 버리기",
@@ -244,7 +242,6 @@
"ViewDiffingOptions": "Diff 메뉴 열기",
"OpenCommandLogMenu": "명령어 로그 메뉴 열기",
"CommitDiff": "커밋의 iff",
"CopyCommitHashToClipboard": "커밋 해시를 클립보드에 복사",
"CommitHash": "커밋 해시",
"CommitURL": "커밋 URL",
"CommitMessage": "커밋 메시지",
-3
View File
@@ -49,7 +49,6 @@
"Close": "Sluiten",
"CloseCancel": "Sluiten",
"Confirm": "Bevestig",
"SureFixupThisCommit": "Weet je zeker dat je fixup wil uitvoeren op deze commit? De commit hieronder zol worden squashed in deze",
"SureSquashThisCommit": "Weet je zeker dat je deze commit wil samenvoegen met de commit hieronder?",
"PickCommitTooltip": "Kies commit (wanneer midden in rebase)",
"Reword": "Hernoem commit",
@@ -152,7 +151,6 @@
"CheckoutCommitFileTooltip": "Bestand uitchecken",
"DiscardOldFileChangeTooltip": "Uitsluit deze commit zijn veranderingen aan dit bestand",
"DiscardFileChangesTitle": "Uitsluit bestand zijn veranderingen",
"DiscardFileChangesPrompt": "Weet je zeker dat je de wijzigingen van deze commit in dit bestand wilt weggooien? Als dit bestand is gecreëerd in deze commit dan zal dit bestand worden verwijdert",
"AutoStashPrompt": "Je moet je veranderingen stashen en poppen om ze over te brengen. Dit automatisch doen? (enter/esc)",
"Discard": "Bekijk 'veranderingen ongedaan maken' opties",
"Cancel": "Annuleren",
@@ -242,7 +240,6 @@
"SwapDiff": "Keer diff richting om",
"ViewDiffingOptions": "Open diff menu",
"ShowingGitDiff": "Laat output zien voor:",
"CopyCommitHashToClipboard": "Kopieer commit hash naar klembord",
"CopyBranchNameToClipboard": "Kopieer branch name naar klembord",
"CopyPathToClipboard": "Kopieer de bestandsnaam naar het klembord",
"CommitPrefixPatternError": "Fout in commitPrefix patroon",
-5
View File
@@ -100,7 +100,6 @@
"CannotSquashOrFixupFirstCommit": "Nie ma commita poniżej do scalenia",
"Fixup": "Poprawka",
"FixupTooltip": "Włącz wybrany commit do commita poniżej. Podobnie do fixup, ale wiadomość wybranego commita zostanie odrzucona.",
"SureFixupThisCommit": "Czy na pewno chcesz 'poprawić' wybrane commit(y) do commita poniżej?",
"SureSquashThisCommit": "Czy na pewno chcesz scalić wybrane commit(y) do commita poniżej?",
"Squash": "Scal",
"PickCommitTooltip": "Oznacz wybrany commit do wybrania (podczas rebazowania). Oznacza to, że commit zostanie zachowany po kontynuacji rebazowania.",
@@ -300,7 +299,6 @@
"Remove": "Usuń",
"DiscardOldFileChangeTooltip": "Odrzuć zmiany w tym pliku z tego commita. Uruchamia interaktywny rebase w tle, więc możesz otrzymać konflikt scalania, jeśli późniejszy commit również zmienia ten plik.",
"DiscardFileChangesTitle": "Odrzuć zmiany w pliku",
"DiscardFileChangesPrompt": "Czy na pewno chcesz usunąć zmiany w wybranym pliku/ach z tego commita?\n\nTa akcja uruchomi rebase, cofając te zmiany w pliku. Pamiętaj, że jeśli późniejsze commity zależą od tych zmian, możesz potrzebować rozwiązać konflikty.\nUwaga: Spowoduje to również zresetowanie wszelkich aktywnych niestandardowych łatek.",
"BareRepo": "Próbujesz otworzyć Lazygit w gołym repozytorium, ale Lazygit jeszcze nie obsługuje gołych repozytoriów. Otworzyć najnowsze repozytorium? (t/n) ",
"InitialBranch": "Nazwa gałęzi? (pozostaw puste dla domyślnej gita): ",
"NoRecentRepositories": "Musisz otworzyć lazygit w repozytorium git. Brak ważnych ostatnich repozytoriów. Wyjście.",
@@ -477,7 +475,6 @@
"OpenCommandLogMenuTooltip": "Pokaż opcje dla dziennika poleceń, np. pokazywanie/ukrywanie dziennika poleceń i skupienie na dzienniku poleceń.",
"ShowingGitDiff": "Pokazuje wynik dla:",
"CommitDiff": "Różnice commita",
"CopyCommitHashToClipboard": "Kopiuj hash commita do schowka",
"CommitHash": "hash commita",
"CommitURL": "URL commita",
"CommitMessage": "Wiadomość commita",
@@ -638,7 +635,6 @@
"CantDeleteMainWorktree": "Nie możesz usunąć głównego drzewa pracy!",
"NoWorktreesThisRepo": "Brak drzew pracy",
"MissingWorktree": "(brakujące)",
"MainWorktree": "(główne)",
"NewWorktree": "Nowe drzewo pracy",
"NewWorktreePath": "Nowa ścieżka drzewa pracy",
"NewWorktreeBase": "Nowa bazowa ref drzewa pracy",
@@ -668,7 +664,6 @@
"NoItemSelected": "Nie wybrano elementu",
"SelectedItemIsNotABranch": "Wybrany element nie jest branch'em",
"SelectedItemDoesNotHaveFiles": "Wybrany element nie ma plików do wyświetlenia",
"OldCherryPickKeyWarning": "Klawisz 'c' nie jest już domyślnym klawiszem do kopiowania commitów do cherry pick. Proszę użyj `{{.copy}}` zamiast tego (i `{{.paste}}` aby wkleić). Powodem tej zmiany jest to, że klawisz 'v' do wybierania zakresu linii podczas stagingu jest teraz używany również do wybierania zakresu linii w każdym widoku listy, co oznacza, że musieliśmy znaleźć nowy klawisz do wklejania commitów, i jeśli zamierzamy teraz używać `{{.paste}}` do wklejania commitów, możemy równie dobrze użyć `{{.copy}}` do ich kopiowania. Jeśli chcesz skonfigurować klawisze, aby uzyskać stare zachowanie, ustaw następujące w swojej konfiguracji:\n\nkeybinding:\n universal:\n toggleRangeSelect: <coś innego niż v>\n commits:\n cherryPickCopy: 'c'\n pasteCommits: 'v'",
"Actions": {
"CheckoutCommit": "Przełącz commit",
"CheckoutTag": "Przełącz tag",
-2
View File
@@ -137,7 +137,6 @@
"CannotSquashOrFixupMergeCommit": "Não é possível squash ou corrigir um commit de merge",
"Fixup": "Fixup",
"FixupTooltip": "Faça o commit selecionado no commit abaixo dele. Semelhante para o squash, mas a mensagem do commit selecionado será descartada.",
"SureFixupThisCommit": "Tem certeza que deseja 'corrigir' o(s) commit(s) selecionado(s) no commit abaixo?",
"SureSquashThisCommit": "Tem certeza que deseja esmagar o(s) commit(s) selecionado(s) no commit abaixo?",
"Squash": "Squash",
"PickCommitTooltip": "Marque o commit selecionado para ser escolhido (quando meados da base). Isso significa que o commit será mantido ao continuar o rebase.",
@@ -368,7 +367,6 @@
"Remove": "Remover",
"DiscardOldFileChangeTooltip": "Descartar as alterações desse commit para este arquivo. Isso executa uma rebase interativa em segundo plano, então você pode ter um conflito de merge se um commit posterior também alterar este arquivo.",
"DiscardFileChangesTitle": "Descartar alterações de arquivo",
"DiscardFileChangesPrompt": "Você tem certeza de que deseja remover as alterações do(s) arquivo(s) selecionado(s) deste commit?",
"BareRepo": "Você tentou abrir Lazygit em um repositório puro, mas Lazygit ainda não suporta repositórios vazios. Abrir os repositórios mais recentes? (y/n) ",
"InitialBranch": "Nome da branch? (deixe vazio para o padrão do git): ",
"NoRecentRepositories": "É necessário abrir lazygit em um repositório git. Nenhum repositório recente válido. Saindo do sistema.",
+1 -3
View File
@@ -18,6 +18,7 @@
"CredentialsPassword": "Пароль",
"CredentialsPassphrase": "Введите пароль для SSH ключа",
"CredentialsPIN": "Введите PIN-код для SSH ключа",
"CredentialsToken": "Введите токен для SSH-ключа",
"PassUnameWrong": "Неверный пароль, кодовая фраза и/или имя пользователя",
"Commit": "Сохранить изменения",
"AmendLastCommit": "Правка последнего коммита",
@@ -63,7 +64,6 @@
"Quit": "Выйти",
"CannotSquashOrFixupFirstCommit": "Ниже нет коммита, который можно было бы объединить",
"Fixup": "Объединить несколько коммитов в один отбросив сообщение коммита (Fixup) ",
"SureFixupThisCommit": "Вы уверены, что хотите объединить несколько коммитов, отбросив сообщение коммита? Он будет объединён с коммитом ниже",
"SureSquashThisCommit": "Вы уверены, что хотите объединить несколько коммитов в нижний коммит?",
"Squash": "Объединить коммиты (Squash)",
"PickCommitTooltip": "Выбрать коммит (в середине перебазирования)",
@@ -226,7 +226,6 @@
"CanOnlyDiscardFromLocalCommits": "Изменения можно отменить только из локальных коммитов.",
"DiscardOldFileChangeTooltip": "Отменить изменения коммита в этом файле",
"DiscardFileChangesTitle": "Отменить изменения файла",
"DiscardFileChangesPrompt": "Вы уверены, что хотите удалить изменения в выбранных файлах из этого коммита?\n\nЭто действие запустит перебазирование и отменит изменения в этих файлах. Обратите внимание, что если последующие коммиты зависят от этих изменений, вам, возможно, придется разрешить конфликты.\nПримечание: это также сбросит все активные пользовательские патчи.",
"BareRepo": "Вы пытались открыть Lazygit в пустом репозитории, но Lazygit ещё не поддерживает пустые репозитории. Открыть последний репозиторий? (y/n)",
"InitialBranch": "Название ветки? (оставьте пустым для git по умолчанию):",
"NoRecentRepositories": "Необходимо открыть lazygit в git репозитории. Нет валидных последних репозиториев. Выход.",
@@ -343,7 +342,6 @@
"OpenCommandLogMenu": "Открыть меню журнала команд",
"ShowingGitDiff": "Показывает вывод для:",
"CommitDiff": "Разница коммита",
"CopyCommitHashToClipboard": "Скопировать hash коммита в буфер обмена",
"CommitHash": "hash коммита",
"CommitURL": "URL коммита",
"CommitMessage": "Полное сообщение коммита",
+4 -8
View File
@@ -152,7 +152,6 @@
"CannotSquashOrFixupMergeCommit": "无法对合并提交进行压缩或修正",
"Fixup": "修正 (fixup)",
"FixupTooltip": "将选定的提交合并到其下面的提交中。与压缩类似,但所选提交的消息将被丢弃。",
"SureFixupThisCommit": "您确定要“修正”此提交吗?它将合并到下面的提交中",
"SureSquashThisCommit": "您确定要将这个提交压缩到下面的提交中吗?",
"Squash": "压缩(Squash)",
"PickCommitTooltip": "标记选中的提交为 picked(变基过程中)。这意味该提交将在后续的变基中保留。",
@@ -249,7 +248,7 @@
"RefreshFiles": "刷新文件",
"FocusMainView": "聚焦主视图",
"Merge": "合并到当前检出的分支",
"MergeBranchTooltip": "Merge selected branch into currently checked out branch.",
"MergeBranchTooltip": "查看将选中项合并到当前分支的选项(正常合并,压缩合并)",
"RegularMergeFastForward": "常规合并(快进)",
"RegularMergeFastForwardTooltip": "将 '{{.checkedOutBranch}}' 快进到 '{{.selectedBranch}}',不创建合并提交。",
"CannotFastForwardMerge": "无法将 '{{.checkedOutBranch}}' 快进到 '{{.selectedBranch}}'",
@@ -413,11 +412,11 @@
"ViewItemFiles": "查看提交的文件",
"CommitFilesTitle": "提交文件",
"CheckoutCommitFileTooltip": "检出文件",
"CannotCheckoutWithModifiedFilesErr": "您已有对您试图签出的文件作出的本地修改。您需要先保存或丢弃这些文件。",
"CanOnlyDiscardFromLocalCommits": "只能从本地提交中丢弃更改",
"Remove": "删除",
"DiscardOldFileChangeTooltip": "放弃对此文件的提交变更",
"DiscardFileChangesTitle": "放弃文件变更",
"DiscardFileChangesPrompt": "您确定要舍弃此提交对该文件的变更吗?如果此文件是在此提交中创建的,它将被删除",
"DisabledForGPG": "使用GPG的用户无法使用此功能。\n\n如果您正在使用密码代理(如gpg-agent)以避免每次签名时输入密码,可以通过在lazygit配置文件中添加\n\ngit:\n overrideGpg: true\n\n来启用此功能。",
"CreateRepo": "不在 git 仓库中。创建一个新的 git 仓库吗?(y/N): ",
"BareRepo": "您已经尝试在空仓库中打开Lazygit,但是Lazygit还不支持空仓库。打开最近的仓库吗?(y / n) ",
@@ -482,7 +481,7 @@
"StashTooltip": "贮藏所有变更.若要使用其他贮藏变体,请使用查看贮藏选项快捷键",
"StashAllChanges": "将所有变更加入贮藏",
"StashStagedChanges": "贮藏已暂存变更",
"StashAllChangesKeepIndex": "将已暂存的变更加入贮藏",
"StashAllChangesKeepIndex": "贮藏所有更改并保留暂存区",
"StashUnstagedChanges": "贮藏未暂存变更",
"StashIncludeUntrackedChanges": "贮藏所有变更,包括未跟踪的文件",
"StashOptions": "贮藏选项",
@@ -642,7 +641,6 @@
"ShowingGitDiff": "显示输出:",
"ShowingDiffForRange": "显示范围差异",
"CommitDiff": "比较提交差异",
"CopyCommitHashToClipboard": "复制提交哈希到剪贴板",
"CommitHash": "提交的 hash",
"CommitURL": "提交URL",
"PasteCommitMessageFromClipboard": "粘贴提交信息自剪贴板",
@@ -846,7 +844,6 @@
"CantDeleteMainWorktree": "您不能移除主工作树!",
"NoWorktreesThisRepo": "没有工作区",
"MissingWorktree": "(缺失)",
"MainWorktree": "(主要)",
"NewWorktree": "新建工作树",
"NewWorktreePath": "新建工作树路径",
"NewWorktreeBase": "新建工作树基于ref",
@@ -882,7 +879,6 @@
"SelectedItemIsNotABranch": "选中的条目不是一个分支",
"SelectedItemDoesNotHaveFiles": "选中的条目中没有",
"MultiSelectNotSupportedForSubmodules": "子模块不支持多选操作",
"OldCherryPickKeyWarning": "The 'c' key is no longer the default key for copying commits to cherry pick. Please use `{{.copy}}` instead (and `{{.paste}}` to paste). The reason for this change is that the 'v' key for selecting a range of lines when staging is now also used for selecting a range of lines in any list view, meaning that we needed to find a new key for pasting commits, and if we're going to now use `{{.paste}}` for pasting commits, we may as well use `{{.copy}}` for copying them. If you want to configure the keybindings to get the old behaviour, set the following in your config:\n\nkeybinding:\n universal:\n toggleRangeSelect: <something other than v>\n commits:\n cherryPickCopy: 'c'\n pasteCommits: 'v'",
"CommandDoesNotSupportOpeningInEditor": "该命令不支持切换到编辑器",
"CustomCommands": "自定义命令",
"NoApplicableCommandsInThisContext": "(当前上下文无可用命令)",
@@ -951,7 +947,7 @@
"Pull": "拉取(Pull)",
"OpenFile": "打开文件",
"StashAllChanges": "贮藏所有变更",
"StashAllChangesKeepIndex": "贮藏所有更改并保持索引",
"StashAllChangesKeepIndex": "贮藏所有更改并保留暂存区",
"StashStagedChanges": "贮藏暂存的变更",
"StashUnstagedChanges": "贮藏所有未暂存更改",
"StashIncludeUntrackedChanges": "贮藏所有更改包括未跟踪的文件",
-4
View File
@@ -83,7 +83,6 @@
"Quit": "結束",
"CannotSquashOrFixupFirstCommit": "沒有可以壓縮的提交",
"Fixup": "修復 (Fixup)",
"SureFixupThisCommit": "是否對此提交進行 '修復' ? 其將被合併於以下之提交中",
"SureSquashThisCommit": "是否要把這個提交壓縮到下面的提交中?",
"Squash": "壓縮 (Squash)",
"PickCommitTooltip": "挑選提交 (於變基過程中)",
@@ -259,7 +258,6 @@
"CommitFilesTitle": "提交檔案",
"CheckoutCommitFileTooltip": "檢出檔案",
"DiscardFileChangesTitle": "捨棄檔案更改",
"DiscardFileChangesPrompt": "是否捨棄此提交?如果這個檔案是在此提交中創建的,它將被刪除",
"BareRepo": "你嘗試在裸版本庫中開啟 Lazygit,但 Lazygit 尚未支援裸版本庫。是否開啟最新版本庫? (y/n) ",
"InitialBranch": "分支名稱?(留空使用 git 的預設值):",
"NoRecentRepositories": "必須在 git 版本庫中開啟 lazygit。沒有有效的最近版本庫。退出。",
@@ -398,7 +396,6 @@
"OpenCommandLogMenu": "開啟命令記錄選單",
"ShowingGitDiff": "顯示輸出:",
"CommitDiff": "提交差異",
"CopyCommitHashToClipboard": "複製提交 hash 到剪貼簿",
"CommitHash": "提交 hash",
"CommitURL": "提交 URL",
"CommitMessage": "提交訊息",
@@ -540,7 +537,6 @@
"CantDeleteMainWorktree": "無法刪除主要工作目錄!",
"NoWorktreesThisRepo": "無工作目錄",
"MissingWorktree": "(失蹤)",
"MainWorktree": "(主要)",
"NewWorktreePath": "工作目錄路徑",
"NewWorktreeBase": "工作目錄來源",
"NewBranchName": "分支名稱",
@@ -57,7 +57,7 @@ var DiscardOldFileChanges = NewIntegrationTest(NewIntegrationTestArgs{
t.ExpectPopup().Confirmation().
Title(Equals("Discard file changes")).
Content(Equals("Are you sure you want to remove changes to the selected file(s) from this commit?\n\nThis action will start a rebase, reverting these file changes. Be aware that if subsequent commits depend on these changes, you may need to resolve conflicts.\nNote: This will also reset any active custom patches.")).
Content(Equals("Are you sure you want to discard changes to the selected file(s) from this commit?\n\nThis action will start a rebase, reverting these file changes. Be aware that if subsequent commits depend on these changes, you may need to resolve conflicts.")).
Confirm()
t.Views().CommitFiles().
@@ -99,7 +99,7 @@ var DiscardOldFileChanges = NewIntegrationTest(NewIntegrationTestArgs{
t.ExpectPopup().Confirmation().
Title(Equals("Discard file changes")).
Content(Equals("Are you sure you want to remove changes to the selected file(s) from this commit?\n\nThis action will start a rebase, reverting these file changes. Be aware that if subsequent commits depend on these changes, you may need to resolve conflicts.\nNote: This will also reset any active custom patches.")).
Content(Equals("Are you sure you want to discard changes to the selected file(s) from this commit?\n\nThis action will start a rebase, reverting these file changes. Be aware that if subsequent commits depend on these changes, you may need to resolve conflicts.")).
Confirm()
t.Views().CommitFiles().
@@ -157,7 +157,7 @@ var DiscardOldFileChanges = NewIntegrationTest(NewIntegrationTestArgs{
t.ExpectPopup().Confirmation().
Title(Equals("Discard file changes")).
Content(Equals("Are you sure you want to remove changes to the selected file(s) from this commit?\n\nThis action will start a rebase, reverting these file changes. Be aware that if subsequent commits depend on these changes, you may need to resolve conflicts.\nNote: This will also reset any active custom patches.")).
Content(Equals("Are you sure you want to discard changes to the selected file(s) from this commit?\n\nThis action will start a rebase, reverting these file changes. Be aware that if subsequent commits depend on these changes, you may need to resolve conflicts.\n\nNote: This will reset the active custom patch!")).
Confirm()
// "Building patch" will still be in this view if the patch isn't reset properly
@@ -45,7 +45,7 @@ var DiscardSubmoduleChanges = NewIntegrationTest(NewIntegrationTestArgs{
t.ExpectPopup().Confirmation().
Title(Equals("Discard file changes")).
Content(Contains("Are you sure you want to remove changes to the selected file(s) from this commit?")).
Content(Contains("Are you sure you want to discard changes to the selected file(s) from this commit?")).
Confirm()
t.Shell().RunCommand([]string{"git", "submodule", "update"})
@@ -0,0 +1,46 @@
package commit
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var FindBaseCommitForFixupDisregardFixupsForSameBaseCommit = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Finds the base commit to create a fixup for, disregarding fixup commits for the same base commit",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.
EmptyCommit("1st commit").
NewBranch("mybranch").
CreateFileAndAdd("file1", "1\n2\n3\n").
Commit("2nd commit").
UpdateFileAndAdd("file1", "1\n2\n3a\n").
Commit("fixup! 2nd commit").
EmptyCommit("3rd commit").
UpdateFileAndAdd("file1", "1a\n2\n3b\n")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Lines(
Contains("3rd commit").IsSelected(),
Contains("fixup! 2nd commit"),
Contains("2nd commit"),
Contains("1st commit"),
)
t.Views().Files().
Focus().
Press(keys.Files.FindBaseCommitForFixup)
t.Views().Commits().
IsFocused().
Lines(
Contains("3rd commit"),
Contains("fixup! 2nd commit"),
Contains("2nd commit").IsSelected(),
Contains("1st commit"),
)
},
})

Some files were not shown because too many files have changed in this diff Show More