Compare commits

..

1 Commits

Author SHA1 Message Date
Jesse Duffield
3a191b913f Add release notes popup after update
We're using glamour for rendering the markdown, and I'm interested in using it in other places
too
2024-01-13 19:26:26 +11:00
985 changed files with 95761 additions and 21486 deletions

View File

@@ -1,4 +0,0 @@
root = true
[*.go]
indent_style = tab

View File

@@ -16,7 +16,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
go-version: 1.20.x
- name: Run goreleaser
uses: goreleaser/goreleaser-action@v4
with:

View File

@@ -1,7 +1,7 @@
name: Continuous Integration
env:
GO_VERSION: 1.21
GO_VERSION: 1.20
on:
push:
@@ -32,7 +32,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
go-version: 1.20.x
- name: Test code
# we're passing -short so that we skip the integration tests, which will be run in parallel below
run: |
@@ -89,7 +89,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
go-version: 1.20.x
- name: Print git version
run: git --version
- name: Test code
@@ -115,7 +115,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
go-version: 1.20.x
- name: Build linux binary
run: |
GOOS=linux go build
@@ -142,7 +142,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
go-version: 1.20.x
- name: Check Vendor Directory
# ensure our vendor directory matches up with our go modules
run: |
@@ -168,7 +168,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
go-version: 1.20.x
- name: Lint
uses: golangci/golangci-lint-action@v3.7.0
with:

View File

@@ -30,5 +30,5 @@ linters-settings:
max-func-lines: 0
run:
go: '1.21'
go: '1.20'
timeout: 10m

6
.vscode/launch.json vendored
View File

@@ -13,6 +13,9 @@
],
"hideSystemGoroutines": true,
"console": "integratedTerminal",
"presentation": {
"hidden": true
}
},
{
"name": "Tail Lazygit logs",
@@ -25,6 +28,9 @@
"--use-config-file=${workspaceFolder}/.vscode/debugger_config.yml"
],
"console": "integratedTerminal",
"presentation": {
"hidden": true
}
},
{
"name": "Attach to a running Lazygit",

View File

@@ -2,7 +2,7 @@
# docker build -t lazygit .
# docker run -it lazygit:latest /bin/sh
FROM golang:1.21 as build
FROM golang:1.20 as build
WORKDIR /go/src/github.com/jesseduffield/lazygit/
COPY go.mod go.sum ./
RUN go mod download

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@ Default path for the config file:
- Linux: `~/.config/lazygit/config.yml`
- MacOS: `~/Library/Application\ Support/lazygit/config.yml`
- Windows: `%LOCALAPPDATA%\lazygit\config.yml` (default location, but it will also be found in `%APPDATA%\lazygit\config.yml`
- Windows: `%APPDATA%\lazygit\config.yml`
For old installations (slightly embarrassing: I didn't realise at the time that you didn't need to supply a vendor name to the path so I just used my name):
@@ -57,6 +57,8 @@ gui:
- blue
selectedLineBgColor:
- blue # set to `default` to have no background colour
selectedRangeBgColor:
- blue
cherryPickedCommitBgColor:
- cyan
cherryPickedCommitFgColor:
@@ -79,22 +81,18 @@ gui:
showCommandLog: true
showIcons: false # deprecated: use nerdFontsVersion instead
nerdFontsVersion: "" # nerd fonts version to use ("2" or "3"); empty means don't show nerd font icons
showFileIcons: true # for hiding file icons in the file views
commandLogSize: 8
splitDiff: 'auto' # one of 'auto' | 'always'
skipRewordInEditorWarning: false # for skipping the confirmation before launching the reword editor
border: 'rounded' # one of 'single' | 'double' | 'rounded' | 'hidden'
animateExplosion: true # shows an explosion animation when nuking the working tree
portraitMode: 'auto' # one of 'auto' | 'never' | 'always'
filterMode: 'substring' # one of 'substring' | 'fuzzy'; see 'Filtering' section below
git:
paging:
colorArg: always
useConfig: false
commit:
signOff: false
autoWrapCommitMessage: true # automatic WYSIWYG wrapping of the commit message as you type
autoWrapWidth: 72 # if autoWrapCommitMessage is true, the width to wrap to
merging:
# only applicable to unix users
manualCommit: false
@@ -104,14 +102,10 @@ git:
# one of date-order, author-date-order, topo-order or default.
# topo-order makes it easier to read the git log graph, but commits may not
# appear chronologically. See https://git-scm.com/docs/git-log#_commit_ordering
#
# Deprecated: Configure this with `Log menu -> Commit sort order` (<c-l> in the commits window by default).
order: 'topo-order'
# one of always, never, when-maximised
# this determines whether the git graph is rendered in the commits panel
#
# Deprecated: Configure this with `Log menu -> Show git graph` (<c-l> in the commits window by default).
showGraph: 'always'
showGraph: 'when-maximised'
# displays the whole git graph by default in the commits panel (equivalent to passing the `--all` argument to `git log`)
showWholeGraph: false
skipHookPrefix: WIP
@@ -126,7 +120,6 @@ git:
overrideGpg: false # prevents lazygit from spawning a separate process when using GPG
disableForcePushing: false
parseEmoji: false
truncateCopiedCommitHashesTo: 12 # When copying commit hashes to the clipboard, truncate them to this length. Set to 40 to disable truncation.
os:
copyToClipboardCmd: '' # See 'Custom Command for Copying to Clipboard' section
editPreset: '' # see 'Configuring File Editing' section
@@ -208,9 +201,6 @@ keybinding:
toggleWhitespaceInDiffView: '<c-w>'
increaseContextInDiffView: '}'
decreaseContextInDiffView: '{'
toggleRangeSelect: 'v'
rangeSelectUp: '<s-up>'
rangeSelectDown: '<s-down>'
status:
checkForUpdate: 'u'
recentRepos: '<enter>'
@@ -256,11 +246,11 @@ keybinding:
moveDownCommit: '<c-j>' # move commit down one
moveUpCommit: '<c-k>' # move commit up one
amendToCommit: 'A'
amendAttributeMenu: 'a'
pickCommit: 'p' # pick commit (when mid-rebase)
revertCommit: 't'
cherryPickCopy: 'C'
pasteCommits: 'V'
cherryPickCopy: 'c'
cherryPickCopyRange: 'C'
pasteCommits: 'v'
tagCommit: 'T'
checkoutCommit: '<space>'
resetCherryPick: '<c-R>'
@@ -273,18 +263,14 @@ keybinding:
commitFiles:
checkoutCommitFile: 'c'
main:
toggleDragSelect: 'v'
toggleDragSelect-alt: 'V'
toggleSelectHunk: 'a'
pickBothHunks: 'b'
submodules:
init: 'i'
update: 'u'
bulkMenu: 'b'
commitMessage:
commitMenu: '<c-o>'
amendAttribute:
addCoAuthor: 'c'
resetAuthor: 'a'
setAuthor: 'A'
```
## Platform Defaults
@@ -376,12 +362,6 @@ That's the behavior when `gui.scrollOffBehavior` is set to "margin" (the default
This setting applies both to all list views (e.g. commits and branches etc), and to the staging view.
## Filtering
We have two ways to filter things, substring matching (the default) and fuzzy searching. With substring matching, the text you enter gets searched for verbatim (usually case-insensitive, except when your filter string contains uppercase letters, in which case we search case-sensitively). You can search for multiple non-contiguous substrings by separating them with spaces; for example, "int test" will match "integration-testing". All substrings have to match, but not necessarily in the given order.
Fuzzy searching is smarter in that it allows every letter of the filter string to match anywhere in the text (only in order though), assigning a weight to the quality of the match and sorting by that order. This has the advantage that it allows typing "clt" to match "commit_loader_test" (letters at the beginning of subwords get more weight); but it has the disadvantage that it tends to return lots of irrelevant results, especially with short filter strings.
## Color Attributes
For color attributes you can choose an array of attributes (with max one color attribute)
@@ -409,13 +389,15 @@ The available attributes are:
## Highlighting the selected line
If you don't like the default behaviour of highlighting the selected line with a blue background, you can use the `selectedLineBgColor` key to customise the behaviour. If you just want to embolden the selected line (this was the original default), you can do the following:
If you don't like the default behaviour of highlighting the selected line with a blue background, you can use the `selectedLineBgColor` and `selectedRangeBgColor` keys to customise the behaviour. If you just want to embolden the selected line (this was the original default), you can do the following:
```yaml
gui:
theme:
selectedLineBgColor:
- default
selectedRangeBgColor:
- default
```
You can also use the reverse attribute like so:
@@ -425,6 +407,8 @@ gui:
theme:
selectedLineBgColor:
- reverse
selectedRangeBgColor:
- reverse
```
## Custom Author Color

View File

@@ -27,19 +27,6 @@ creates a commit with the appropriate subject line.
Don't confuse this with the lowercase "f" command ("Fixup commit"); that one
squashes the selected commit into its parent, this is not what we want here.
## Creating amend commits
There's a special type of fixup commit that uses "amend!" instead of "fixup!" in
the commit message subject; in addition to fixing up the original commit with
changes it allows you to also (or only) change the commit message of the
original commit. The menu that appears when pressing shift-F has options for
both of these; they bring up a commit message panel similar to when you reword a
commit, but then create the "amend!" commit containing the new message. Note
that in that panel you only type the new message as you want it to be
eventually; lazygit then takes care of formatting the "amend!" commit
appropriately for you (with the subject of your new message moving into the body
of the "amend!" commit).
## Squashing fixup commits
When you're ready to merge the branch and want to squash all these fixup commits

View File

@@ -3,9 +3,8 @@
* [Configuration](./Config.md).
* [Custom Commands](./Custom_Command_Keybindings.md)
* [Custom Pagers](./Custom_Pagers.md)
* [Dev docs](./dev)
* [Keybindings](./keybindings)
* [Undo/Redo](./Undoing.md)
* [Range Select](./Range_Select.md)
* [Searching/Filtering](./Searching.md)
* [Stacked Branches](./Stacked_Branches.md)
* [Dev docs](./dev)

View File

@@ -1,14 +0,0 @@
# Range Select
Some actions can be performed on a range of contiguous items. For example:
* staging multiple files at once
* squashing multiple commits at once
* copying (for cherry-pick) multiple commits at once
There are two ways to select a range of items:
1. Sticky range select: Press 'v' to toggle range select, then expand the selection using the up/down arrow key. To reset the selection, press 'v' again.
2. Non-sticky range select: Press shift+up or shift+down to expand the selection. To reset the selection, press up/down without shift.
The sticky option will be more familiar to vim users, and the second option will feel more natural to users who aren't used to doing things in a modal way.
In order to perform an action on a range of items, simply press the normal key for that action. If the action only works on individual items, it will raise an error. This is a new feature and the plan is to incrementally support range select for more and more actions. If there is an action you would like to support range select which currently does not, please raise an issue in the repo.

View File

@@ -58,7 +58,6 @@
* `pkg/gui/gui_common.go`: defines gui-specific methods that all controllers and helpers have access to
* `pkg/i18n/english.go`: defines the set of i18n strings and their English values
* `pkg/gui/controllers/helpers/refresh_helper.go`: manages refreshing of models. The refresh helper is typically invoked at the end of an action to re-load affected models from git (e.g. re-load branches after doing a git pull)
* `pkg/gui/controllers/quit_actions.go`: contains code that runs when you hit 'escape' on a view (assuming the view doesn't define its own escape handler)
* `vendor/github.com/jesseduffield/gocui/gui.go`: defines the gocui gui struct
* `vendor/github.com/jesseduffield/gocui/view.go`: defines the gocui view struct
@@ -76,8 +75,6 @@ In terms of dependencies, controllers sit at the highest level, so they can refe
* **Tab**: Each tab in a window (e.g. Files, Worktrees, Submodules) actually has a corresponding view which we bring to the front upon changing tabs.
* **Model**: Representation of a git object e.g. commits, branches, files.
* **ViewModel**: Used by a context to maintain state related to the view.
* **Keybinding**: A keybinding associates a _key_ with an _action_. For example if you press the 'down' arrow, the action performed will be your cursor moving down a list by one.
* **Action**: An action is the thing that happens when you press a key. Often an action will invoke a git command, but not always: for example, navigation actions don't involve git.
* **Common structs**: Most structs have a field named `c` which contains a 'common' struct: a struct containing a bag of dependencies that most structs of the same layer require. For example if you want to access a helper from a controller you can do so with `self.c.Helpers.MyHelper`.
## Event loop and threads

View File

@@ -6,359 +6,357 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
## Global keybindings
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-r> `` | Switch to a recent repo | |
| `` <pgup> (fn+up/shift+k) `` | Scroll up main window | |
| `` <pgdown> (fn+down/shift+j) `` | Scroll down main window | |
| `` @ `` | View command log options | View options for the command log e.g. show/hide the command log and focus the command log. |
| `` P `` | Push | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` p `` | Pull | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` } `` | Increase diff context size | Increase the amount of the context shown around changes in the diff view. |
| `` { `` | Decrease diff context size | Decrease the amount of the context shown around changes in the diff view. |
| `` : `` | Execute custom command | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
| `` <c-p> `` | View custom patch options | |
| `` m `` | View merge/rebase options | View options to abort/continue/skip the current merge/rebase. |
| `` R `` | Refresh | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
| `` + `` | Next screen mode (normal/half/fullscreen) | |
| `` _ `` | Prev screen mode | |
| `` ? `` | Open keybindings menu | |
| `` <c-s> `` | View filter options | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | Quit | |
| `` <esc> `` | Cancel | |
| `` <c-w> `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view. |
| `` z `` | Undo | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
| `` <c-z> `` | Redo | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
<pre>
<kbd>&lt;c-r&gt;</kbd>: Switch to a recent repo
<kbd>&lt;pgup&gt;</kbd>: Scroll up main panel (fn+up/shift+k)
<kbd>&lt;pgdown&gt;</kbd>: Scroll down main panel (fn+down/shift+j)
<kbd>@</kbd>: Open command log menu
<kbd>}</kbd>: Increase the size of the context shown around changes in the diff view
<kbd>{</kbd>: Decrease the size of the context shown around changes in the diff view
<kbd>:</kbd>: Execute custom command
<kbd>&lt;c-p&gt;</kbd>: View custom patch options
<kbd>m</kbd>: View merge/rebase options
<kbd>R</kbd>: Refresh
<kbd>+</kbd>: Next screen mode (normal/half/fullscreen)
<kbd>_</kbd>: Prev screen mode
<kbd>?</kbd>: Open menu
<kbd>&lt;c-s&gt;</kbd>: View filter-by-path options
<kbd>W</kbd>: Open diff menu
<kbd>&lt;c-e&gt;</kbd>: Open diff menu
<kbd>&lt;c-w&gt;</kbd>: Toggle whether or not whitespace changes are shown in the diff view
<kbd>z</kbd>: Undo
<kbd>&lt;c-z&gt;</kbd>: Redo
<kbd>P</kbd>: Push
<kbd>p</kbd>: Pull
</pre>
## List panel navigation
| Key | Action | Info |
|-----|--------|-------------|
| `` , `` | Previous page | |
| `` . `` | Next page | |
| `` < `` | Scroll to top | |
| `` > `` | Scroll to bottom | |
| `` v `` | Toggle range select | |
| `` <s-down> `` | Range select down | |
| `` <s-up> `` | Range select up | |
| `` / `` | Search the current view by text | |
| `` H `` | Scroll left | |
| `` L `` | Scroll right | |
| `` ] `` | Next tab | |
| `` [ `` | Previous tab | |
<pre>
<kbd>,</kbd>: Previous page
<kbd>.</kbd>: Next page
<kbd>&lt;</kbd>: Scroll to top
<kbd>&gt;</kbd>: Scroll to bottom
<kbd>/</kbd>: Search the current view by text
<kbd>H</kbd>: Scroll left
<kbd>L</kbd>: Scroll right
<kbd>]</kbd>: Next tab
<kbd>[</kbd>: Previous tab
</pre>
## Commit files
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy path 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. |
| `` o `` | Open file | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <space> `` | Toggle file included in patch | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` <enter> `` | Enter file / Toggle directory collapsed | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
| `` ` `` | Toggle file tree view | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` / `` | Search the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy the committed file name to the clipboard
<kbd>c</kbd>: Checkout file
<kbd>d</kbd>: Discard this commit's changes to this file
<kbd>o</kbd>: Open file
<kbd>e</kbd>: Edit file
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;space&gt;</kbd>: Toggle file included in patch
<kbd>a</kbd>: Toggle all files included in patch
<kbd>&lt;enter&gt;</kbd>: Enter file to add selected lines to the patch (or toggle directory collapsed)
<kbd>`</kbd>: Toggle file tree view
<kbd>/</kbd>: Search the current view by text
</pre>
## Commit summary
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Confirm | |
| `` <esc> `` | Close | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Confirm
<kbd>&lt;esc&gt;</kbd>: Close
</pre>
## Commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit SHA 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 fixup, but the selected commit's message will be discarded. |
| `` 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. |
| `` e `` | Edit (start interactive rebase) | Edit the selected commit. Use this to start an interactive rebase from the selected commit. When already mid-rebase, this will mark the selected commit for editing, which means that upon continuing the rebase, the rebase will pause at the selected commit to allow you to make changes. |
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
| `` p `` | Pick | Mark the selected commit to be picked (when mid-rebase). This means that the commit will be retained upon continuing the rebase. |
| `` F `` | Create fixup commit | Create 'fixup!' commit for the selected commit. Later on, you can press `S` on this same commit to apply all above fixup commits. |
| `` S `` | Apply fixup commits | Squash all 'fixup!' commits, either above the selected commit, or all in current branch (autosquash). |
| `` <c-j> `` | Move commit down one | |
| `` <c-k> `` | Move commit up one | |
| `` V `` | Paste (cherry-pick) | |
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
| `` A `` | Amend | Amend commit with staged changes. If the selected commit is the HEAD commit, this will perform `git commit --amend`. Otherwise the commit will be amended via a rebase. |
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
| `` T `` | Tag commit | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
| `` <c-l> `` | View log options | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
| `` <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 | |
| `` n `` | Create new branch off of commit | |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | Copy (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | View files | |
| `` w `` | View worktree options | |
| `` / `` | Search the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy commit SHA to clipboard
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>b</kbd>: View bisect options
<kbd>s</kbd>: Squash down
<kbd>f</kbd>: Fixup commit
<kbd>r</kbd>: Reword commit
<kbd>R</kbd>: Reword commit with editor
<kbd>d</kbd>: Delete commit
<kbd>e</kbd>: Edit commit
<kbd>p</kbd>: Pick commit (when mid-rebase)
<kbd>F</kbd>: Create fixup commit for this commit
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
<kbd>&lt;c-j&gt;</kbd>: Move commit down one
<kbd>&lt;c-k&gt;</kbd>: Move commit up one
<kbd>v</kbd>: Paste commits (cherry-pick)
<kbd>B</kbd>: Mark commit as base commit for rebase
<kbd>A</kbd>: Amend commit with staged changes
<kbd>a</kbd>: Set/Reset commit author
<kbd>t</kbd>: Revert commit
<kbd>T</kbd>: Tag commit
<kbd>&lt;c-l&gt;</kbd>: Open log menu
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Checkout commit
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: Open commit in browser
<kbd>n</kbd>: Create new branch off of commit
<kbd>g</kbd>: View reset options
<kbd>c</kbd>: Copy commit (cherry-pick)
<kbd>C</kbd>: Copy commit range (cherry-pick)
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: View selected item's files
<kbd>/</kbd>: Search the current view by text
</pre>
## Confirmation panel
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Confirm | |
| `` <esc> `` | Close/Cancel | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Confirm
<kbd>&lt;esc&gt;</kbd>: Close/Cancel
</pre>
## Files
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy path to clipboard | |
| `` <space> `` | Stage | Toggle staged for selected file. |
| `` <c-b> `` | Filter files by status | |
| `` y `` | Copy to clipboard | |
| `` c `` | Commit | Commit staged changes. |
| `` w `` | Commit changes without pre-commit hook | |
| `` A `` | Amend last commit | |
| `` C `` | Commit changes using git editor | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` e `` | Edit | Open file in external editor. |
| `` o `` | Open file | Open file in default application. |
| `` i `` | Ignore or exclude file | |
| `` r `` | Refresh files | |
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
| `` S `` | View stash options | View stash options (e.g. stash all, stash staged, stash unstaged). |
| `` a `` | Stage all | Toggle staged/unstaged for all files in working tree. |
| `` <enter> `` | Stage lines / Collapse directory | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
| `` d `` | Discard | View options for discarding changes to the selected file. |
| `` g `` | View upstream reset options | |
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
| `` ` `` | Toggle file tree view | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` M `` | Open external merge tool | Run `git mergetool`. |
| `` f `` | Fetch | Fetch changes from remote. |
| `` / `` | Search the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy the file name to the clipboard
<kbd>d</kbd>: View 'discard changes' options
<kbd>&lt;space&gt;</kbd>: Toggle staged
<kbd>&lt;c-b&gt;</kbd>: Filter files by status
<kbd>y</kbd>: Copy to clipboard
<kbd>c</kbd>: Commit changes
<kbd>w</kbd>: Commit changes without pre-commit hook
<kbd>A</kbd>: Amend last commit
<kbd>C</kbd>: Commit changes using git editor
<kbd>&lt;c-f&gt;</kbd>: Find base commit for fixup
<kbd>e</kbd>: Edit file
<kbd>o</kbd>: Open file
<kbd>i</kbd>: Ignore or exclude file
<kbd>r</kbd>: Refresh files
<kbd>s</kbd>: Stash all changes
<kbd>S</kbd>: View stash options
<kbd>a</kbd>: Stage/unstage all
<kbd>&lt;enter&gt;</kbd>: Stage individual hunks/lines for file, or collapse/expand for directory
<kbd>g</kbd>: View upstream reset options
<kbd>D</kbd>: View reset options
<kbd>`</kbd>: Toggle file tree view
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>M</kbd>: Open external merge tool (git mergetool)
<kbd>f</kbd>: Fetch
<kbd>/</kbd>: Search the current view by text
</pre>
## Local branches
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy branch name to clipboard | |
| `` i `` | Show git-flow options | |
| `` <space> `` | Checkout | Checkout selected item. |
| `` n `` | New branch | |
| `` o `` | Create pull request | |
| `` O `` | View create pull request options | |
| `` <c-y> `` | Copy pull request URL to clipboard | |
| `` c `` | Checkout by name | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
| `` F `` | Force checkout | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
| `` d `` | Delete | View delete options for local/remote branch. |
| `` r `` | Rebase | Rebase the checked-out branch onto the selected branch. |
| `` M `` | Merge | Merge selected branch into currently checked out branch. |
| `` f `` | Fast-forward | Fast-forward selected branch from its upstream. |
| `` T `` | New tag | |
| `` s `` | Sort order | |
| `` g `` | Reset | |
| `` R `` | Rename branch | |
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
| `` <enter> `` | View commits | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy branch name to clipboard
<kbd>i</kbd>: Show git-flow options
<kbd>&lt;space&gt;</kbd>: Checkout
<kbd>n</kbd>: New branch
<kbd>o</kbd>: Create pull request
<kbd>O</kbd>: Create pull request options
<kbd>&lt;c-y&gt;</kbd>: Copy pull request URL to clipboard
<kbd>c</kbd>: Checkout by name, enter '-' to switch to last
<kbd>F</kbd>: Force checkout
<kbd>d</kbd>: View delete options
<kbd>r</kbd>: Rebase checked-out branch onto this branch
<kbd>M</kbd>: Merge into currently checked out branch
<kbd>f</kbd>: Fast-forward this branch from its upstream
<kbd>T</kbd>: Create tag
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: View reset options
<kbd>R</kbd>: Rename branch
<kbd>u</kbd>: View upstream options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: View commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Main panel (merging)
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Pick hunk | |
| `` b `` | Pick all hunks | |
| `` <up> `` | Previous hunk | |
| `` <down> `` | Next hunk | |
| `` <left> `` | Previous conflict | |
| `` <right> `` | Next conflict | |
| `` z `` | Undo | Undo last merge conflict resolution. |
| `` e `` | Edit file | Open file in external editor. |
| `` o `` | Open file | Open file in default application. |
| `` M `` | Open external merge tool | Run `git mergetool`. |
| `` <esc> `` | Return to files panel | |
<pre>
<kbd>e</kbd>: Edit file
<kbd>o</kbd>: Open file
<kbd>&lt;left&gt;</kbd>: Select previous conflict
<kbd>&lt;right&gt;</kbd>: Select next conflict
<kbd>&lt;up&gt;</kbd>: Select previous hunk
<kbd>&lt;down&gt;</kbd>: Select next hunk
<kbd>z</kbd>: Undo
<kbd>M</kbd>: Open external merge tool (git mergetool)
<kbd>&lt;space&gt;</kbd>: Pick hunk
<kbd>b</kbd>: Pick all hunks
<kbd>&lt;esc&gt;</kbd>: Return to files panel
</pre>
## Main panel (normal)
| Key | Action | Info |
|-----|--------|-------------|
| `` mouse wheel down (fn+up) `` | Scroll down | |
| `` mouse wheel up (fn+down) `` | Scroll up | |
<pre>
<kbd>mouse wheel down</kbd>: Scroll down (fn+up)
<kbd>mouse wheel up</kbd>: Scroll up (fn+down)
</pre>
## Main panel (patch building)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | Go to previous hunk | |
| `` <right> `` | Go to next hunk | |
| `` v `` | Toggle range select | |
| `` a `` | Select hunk | Toggle hunk selection mode. |
| `` <c-o> `` | Copy selected text to clipboard | |
| `` o `` | Open file | Open file in default application. |
| `` e `` | Edit file | Open file in external editor. |
| `` <space> `` | Toggle lines in patch | |
| `` <esc> `` | Exit custom patch builder | |
| `` / `` | Search the current view by text | |
<pre>
<kbd>&lt;left&gt;</kbd>: Select previous hunk
<kbd>&lt;right&gt;</kbd>: Select next hunk
<kbd>v</kbd>: Toggle drag select
<kbd>V</kbd>: Toggle drag select
<kbd>a</kbd>: Toggle select hunk
<kbd>&lt;c-o&gt;</kbd>: Copy the selected text to the clipboard
<kbd>o</kbd>: Open file
<kbd>e</kbd>: Edit file
<kbd>&lt;space&gt;</kbd>: Add/Remove line(s) to patch
<kbd>&lt;esc&gt;</kbd>: Exit custom patch builder
<kbd>/</kbd>: Search the current view by text
</pre>
## Main panel (staging)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | Go to previous hunk | |
| `` <right> `` | Go to next hunk | |
| `` v `` | Toggle range select | |
| `` a `` | Select hunk | Toggle hunk selection mode. |
| `` <c-o> `` | Copy selected text to clipboard | |
| `` <space> `` | Stage | Toggle selection staged / unstaged. |
| `` d `` | Discard | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
| `` o `` | Open file | Open file in default application. |
| `` e `` | Edit file | Open file in external editor. |
| `` <esc> `` | Return to files panel | |
| `` <tab> `` | Switch view | Switch to other view (staged/unstaged changes). |
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
| `` c `` | Commit | Commit staged changes. |
| `` w `` | Commit changes without pre-commit hook | |
| `` C `` | Commit changes using git editor | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` / `` | Search the current view by text | |
<pre>
<kbd>&lt;left&gt;</kbd>: Select previous hunk
<kbd>&lt;right&gt;</kbd>: Select next hunk
<kbd>v</kbd>: Toggle drag select
<kbd>V</kbd>: Toggle drag select
<kbd>a</kbd>: Toggle select hunk
<kbd>&lt;c-o&gt;</kbd>: Copy the selected text to the clipboard
<kbd>o</kbd>: Open file
<kbd>e</kbd>: Edit file
<kbd>&lt;esc&gt;</kbd>: Return to files panel
<kbd>&lt;tab&gt;</kbd>: Switch to other panel (staged/unstaged changes)
<kbd>&lt;space&gt;</kbd>: Toggle line staged / unstaged
<kbd>d</kbd>: Discard change (git reset)
<kbd>E</kbd>: Edit hunk
<kbd>c</kbd>: Commit changes
<kbd>w</kbd>: Commit changes without pre-commit hook
<kbd>C</kbd>: Commit changes using git editor
<kbd>/</kbd>: Search the current view by text
</pre>
## Menu
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Execute | |
| `` <esc> `` | Close | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Execute
<kbd>&lt;esc&gt;</kbd>: Close
<kbd>/</kbd>: Filter the current view by text
</pre>
## Reflog
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit SHA 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 | |
| `` n `` | Create new branch off of commit | |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | Copy (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | View commits | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy commit SHA to clipboard
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Checkout commit
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: Open commit in browser
<kbd>n</kbd>: Create new branch off of commit
<kbd>g</kbd>: View reset options
<kbd>c</kbd>: Copy commit (cherry-pick)
<kbd>C</kbd>: Copy commit range (cherry-pick)
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: View commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Remote branches
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy branch name to clipboard | |
| `` <space> `` | Checkout | Checkout a new local branch based on the selected remote branch, or the remote branch as a detached head. |
| `` n `` | New branch | |
| `` M `` | Merge | Merge selected branch into currently checked out branch. |
| `` r `` | Rebase | Rebase the checked-out branch onto the selected branch. |
| `` d `` | Delete | Delete the remote branch from the remote. |
| `` u `` | Set as upstream | Set the selected remote branch as the upstream of the checked-out branch. |
| `` s `` | Sort order | |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | View commits | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy branch name to clipboard
<kbd>&lt;space&gt;</kbd>: Checkout
<kbd>n</kbd>: New branch
<kbd>M</kbd>: Merge into currently checked out branch
<kbd>r</kbd>: Rebase checked-out branch onto this branch
<kbd>d</kbd>: Delete remote tag
<kbd>u</kbd>: Set as upstream of checked-out branch
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: View reset options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: View commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Remotes
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | View branches | |
| `` n `` | New remote | |
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
| `` e `` | Edit | Edit the selected remote's name or URL. |
| `` f `` | Fetch | Fetch updates from the remote repository. This retrieves new commits and branches without merging them into your local branches. |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>f</kbd>: Fetch remote
<kbd>n</kbd>: Add new remote
<kbd>d</kbd>: Remove remote
<kbd>e</kbd>: Edit remote
<kbd>/</kbd>: Filter the current view by text
</pre>
## Stash
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Apply | Apply the stash entry to your working directory. |
| `` g `` | Pop | Apply the stash entry to your working directory and remove the stash entry. |
| `` d `` | Drop | Remove the stash entry from the stash list. |
| `` n `` | New branch | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
| `` r `` | Rename stash | |
| `` <enter> `` | View files | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: Apply
<kbd>g</kbd>: Pop
<kbd>d</kbd>: Drop
<kbd>n</kbd>: New branch
<kbd>r</kbd>: Rename stash
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: View selected item's files
<kbd>/</kbd>: Filter the current view by text
</pre>
## Status
| Key | Action | Info |
|-----|--------|-------------|
| `` o `` | Open config file | Open file in default application. |
| `` e `` | Edit config file | Open file in external editor. |
| `` u `` | Check for update | |
| `` <enter> `` | Switch to a recent repo | |
| `` a `` | Show all branch logs | |
<pre>
<kbd>o</kbd>: Open config file
<kbd>e</kbd>: Edit config file
<kbd>u</kbd>: Check for update
<kbd>&lt;enter&gt;</kbd>: Switch to a recent repo
<kbd>a</kbd>: Show all branch logs
</pre>
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy commit SHA 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 | |
| `` n `` | Create new branch off of commit | |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | Copy (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | View files | |
| `` w `` | View worktree options | |
| `` / `` | Search the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy commit SHA to clipboard
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Checkout commit
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: Open commit in browser
<kbd>n</kbd>: Create new branch off of commit
<kbd>g</kbd>: View reset options
<kbd>c</kbd>: Copy commit (cherry-pick)
<kbd>C</kbd>: Copy commit range (cherry-pick)
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: View selected item's files
<kbd>/</kbd>: Search the current view by text
</pre>
## Submodules
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Copy submodule name to clipboard | |
| `` <enter> `` | Enter | Enter submodule. After entering the submodule, you can press `<esc>` to escape back to the parent repo. |
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
| `` u `` | Update | Update selected submodule. |
| `` n `` | New submodule | |
| `` e `` | Update submodule URL | |
| `` i `` | Initialize | Initialize the selected submodule to prepare for fetching. You probably want to follow this up by invoking the 'update' action to fetch the submodule. |
| `` b `` | View bulk submodule options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy submodule name to clipboard
<kbd>&lt;enter&gt;</kbd>: Enter submodule
<kbd>&lt;space&gt;</kbd>: Enter submodule
<kbd>d</kbd>: Remove submodule
<kbd>u</kbd>: Update submodule
<kbd>n</kbd>: Add new submodule
<kbd>e</kbd>: Update submodule URL
<kbd>i</kbd>: Initialize submodule
<kbd>b</kbd>: View bulk submodule options
<kbd>/</kbd>: Filter the current view by text
</pre>
## Tags
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Checkout | Checkout the selected tag tag as a detached HEAD. |
| `` n `` | New tag | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
| `` d `` | Delete | View delete options for local/remote tag. |
| `` P `` | Push tag | Push the selected tag to a remote. You'll be prompted to select a remote. |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | View commits | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: Checkout
<kbd>d</kbd>: View delete options
<kbd>P</kbd>: Push tag
<kbd>n</kbd>: Create tag
<kbd>g</kbd>: View reset options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: View commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Worktrees
| Key | Action | Info |
|-----|--------|-------------|
| `` n `` | New worktree | |
| `` <space> `` | Switch | Switch to the selected worktree. |
| `` o `` | Open in editor | |
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>n</kbd>: Create worktree
<kbd>&lt;space&gt;</kbd>: Switch to worktree
<kbd>&lt;enter&gt;</kbd>: Switch to worktree
<kbd>o</kbd>: Open in editor
<kbd>d</kbd>: Remove worktree
<kbd>/</kbd>: Filter the current view by text
</pre>

View File

@@ -6,359 +6,357 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
## グローバルキーバインド
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-r> `` | 最近使用したリポジトリに切り替え | |
| `` <pgup> (fn+up/shift+k) `` | メインパネルをにスクロール | |
| `` <pgdown> (fn+down/shift+j) `` | メインパネルを下にスクロール | |
| `` @ `` | コマンドログメニューを開く | View options for the command log e.g. show/hide the command log and focus the command log. |
| `` P `` | Push | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` p `` | Pull | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` } `` | Increase diff context size | Increase the amount of the context shown around changes in the diff view. |
| `` { `` | Decrease diff context size | Decrease the amount of the context shown around changes in the diff view. |
| `` : `` | カスタムコマンドを実行 | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
| `` <c-p> `` | View custom patch options | |
| `` m `` | View merge/rebase options | View options to abort/continue/skip the current merge/rebase. |
| `` R `` | リフレッシュ | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
| `` + `` | 次のスクリーンモード (normal/half/fullscreen) | |
| `` _ `` | 前のスクリーンモード | |
| `` ? `` | メニューを開く | |
| `` <c-s> `` | View filter options | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | 差分メニューを開く | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | 差分メニューを開く | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | 終了 | |
| `` <esc> `` | キャンセル | |
| `` <c-w> `` | 空白文字の差分の表示有無を切り替え | Toggle whether or not whitespace changes are shown in the diff view. |
| `` z `` | アンドゥ (via reflog) (experimental) | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
| `` <c-z> `` | リドゥ (via reflog) (experimental) | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
<pre>
<kbd>&lt;c-r&gt;</kbd>: 最近使用したリポジトリに切り替え
<kbd>&lt;pgup&gt;</kbd>: メインパネルを上にスクロール (fn+up/shift+k)
<kbd>&lt;pgdown&gt;</kbd>: メインパネルをにスクロール (fn+down/shift+j)
<kbd>@</kbd>: コマンドログメニューを開く
<kbd>}</kbd>: Increase the size of the context shown around changes in the diff view
<kbd>{</kbd>: Decrease the size of the context shown around changes in the diff view
<kbd>:</kbd>: カスタムコマンドを実行
<kbd>&lt;c-p&gt;</kbd>: View custom patch options
<kbd>m</kbd>: View merge/rebase options
<kbd>R</kbd>: リフレッシュ
<kbd>+</kbd>: 次のスクリーンモード (normal/half/fullscreen)
<kbd>_</kbd>: 前のスクリーンモード
<kbd>?</kbd>: メニューを開く
<kbd>&lt;c-s&gt;</kbd>: View filter-by-path options
<kbd>W</kbd>: 差分メニューを開く
<kbd>&lt;c-e&gt;</kbd>: 差分メニューを開く
<kbd>&lt;c-w&gt;</kbd>: 空白文字の差分の表示有無を切り替え
<kbd>z</kbd>: アンドゥ (via reflog) (experimental)
<kbd>&lt;c-z&gt;</kbd>: リドゥ (via reflog) (experimental)
<kbd>P</kbd>: Push
<kbd>p</kbd>: Pull
</pre>
## 一覧パネルの操作
| Key | Action | Info |
|-----|--------|-------------|
| `` , `` | 前のページ | |
| `` . `` | 次のページ | |
| `` < `` |部までスクロール | |
| `` > `` | 最下部までスクロール | |
| `` v `` | 範囲選択を切り替え | |
| `` <s-down> `` | Range select down | |
| `` <s-up> `` | Range select up | |
| `` / `` | 検索を開始 | |
| `` H `` | 左スクロール | |
| `` L `` | 右スクロール | |
| `` ] `` | 次のタブ | |
| `` [ `` | 前のタブ | |
<pre>
<kbd>,</kbd>: 前のページ
<kbd>.</kbd>: 次のページ
<kbd>&lt;</kbd>: 最上部までスクロール
<kbd>&gt;</kbd>:部までスクロール
<kbd>/</kbd>: 検索を開始
<kbd>H</kbd>: 左スクロール
<kbd>L</kbd>: 右スクロール
<kbd>]</kbd>: 次のタブ
<kbd>[</kbd>: 前のタブ
</pre>
## Stash
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | 適用 | Apply the stash entry to your working directory. |
| `` g `` | Pop | Apply the stash entry to your working directory and remove the stash entry. |
| `` d `` | Drop | Remove the stash entry from the stash list. |
| `` n `` | 新しいブランチを作成 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
| `` r `` | Stashを変更 | |
| `` <enter> `` | View files | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: 適用
<kbd>g</kbd>: Pop
<kbd>d</kbd>: Drop
<kbd>n</kbd>: 新しいブランチを作成
<kbd>r</kbd>: Stashを変更
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: View selected item's files
<kbd>/</kbd>: Filter the current view by text
</pre>
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | コミットのSHAをクリップボードにコピー | |
| `` <space> `` | チェックアウト | Checkout the selected commit as a detached HEAD. |
| `` y `` | コミットの情報をコピー | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | ブラウザでコミットを開く | |
| `` n `` | コミットにブランチを作成 | |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | コミットをコピー (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | View files | |
| `` w `` | View worktree options | |
| `` / `` | 検索を開始 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: コミットのSHAをクリップボードにコピー
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: コミットをチェックアウト
<kbd>y</kbd>: コミットの情報をコピー
<kbd>o</kbd>: ブラウザでコミットを開く
<kbd>n</kbd>: コミットにブランチを作成
<kbd>g</kbd>: View reset options
<kbd>c</kbd>: コミットをコピー (cherry-pick)
<kbd>C</kbd>: コミットを範囲コピー (cherry-pick)
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: View selected item's files
<kbd>/</kbd>: 検索を開始
</pre>
## Worktrees
| Key | Action | Info |
|-----|--------|-------------|
| `` n `` | New worktree | |
| `` <space> `` | Switch | Switch to the selected worktree. |
| `` o `` | Open in editor | |
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>n</kbd>: Create worktree
<kbd>&lt;space&gt;</kbd>: Switch to worktree
<kbd>&lt;enter&gt;</kbd>: Switch to worktree
<kbd>o</kbd>: Open in editor
<kbd>d</kbd>: Remove worktree
<kbd>/</kbd>: Filter the current view by text
</pre>
## コミット
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | コミットのSHAをクリップボードにコピー | |
| `` <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 fixup, but the selected commit's message will be discarded. |
| `` 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. |
| `` e `` | Edit (start interactive rebase) | コミットを編集 |
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
| `` p `` | Pick | Mark the selected commit to be picked (when mid-rebase). This means that the commit will be retained upon continuing the rebase. |
| `` F `` | Fixupコミットを作成 | このコミットに対するfixupコミットを作成 |
| `` S `` | Apply fixup commits | Squash all 'fixup!' commits, either above the selected commit, or all in current branch (autosquash). |
| `` <c-j> `` | コミットを1つ下に移動 | |
| `` <c-k> `` | コミットを1つ上に移動 | |
| `` V `` | コミットを貼り付け (cherry-pick) | |
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
| `` A `` | Amend | ステージされた変更でamendコミット |
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
| `` T `` | タグを作成 | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
| `` <c-l> `` | ログメニューを開く | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
| `` <space> `` | チェックアウト | Checkout the selected commit as a detached HEAD. |
| `` y `` | コミットの情報をコピー | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | ブラウザでコミットを開く | |
| `` n `` | コミットにブランチを作成 | |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | コミットをコピー (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | View files | |
| `` w `` | View worktree options | |
| `` / `` | 検索を開始 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: コミットのSHAをクリップボードにコピー
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>b</kbd>: View bisect options
<kbd>s</kbd>: Squash down
<kbd>f</kbd>: Fixup commit
<kbd>r</kbd>: コミットメッセージを変更
<kbd>R</kbd>: エディタでコミットメッセージを編集
<kbd>d</kbd>: コミットを削除
<kbd>e</kbd>: コミットを編集
<kbd>p</kbd>: Pick commit (when mid-rebase)
<kbd>F</kbd>: このコミットに対するfixupコミットを作成
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
<kbd>&lt;c-j&gt;</kbd>: コミットを1つ下に移動
<kbd>&lt;c-k&gt;</kbd>: コミットを1つ上に移動
<kbd>v</kbd>: コミットを貼り付け (cherry-pick)
<kbd>B</kbd>: Mark commit as base commit for rebase
<kbd>A</kbd>: ステージされた変更でamendコミット
<kbd>a</kbd>: Set/Reset commit author
<kbd>t</kbd>: コミットをrevert
<kbd>T</kbd>: タグを作成
<kbd>&lt;c-l&gt;</kbd>: ログメニューを開く
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: コミットをチェックアウト
<kbd>y</kbd>: コミットの情報をコピー
<kbd>o</kbd>: ブラウザでコミットを開く
<kbd>n</kbd>: コミットにブランチを作成
<kbd>g</kbd>: View reset options
<kbd>c</kbd>: コミットをコピー (cherry-pick)
<kbd>C</kbd>: コミットを範囲コピー (cherry-pick)
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: View selected item's files
<kbd>/</kbd>: 検索を開始
</pre>
## コミットファイル
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | ファイル名をクリップボードにコピー | |
| `` c `` | チェックアウト | 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. |
| `` o `` | ファイルを開く | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <space> `` | Toggle file included in patch | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` <enter> `` | Enter file / Toggle directory collapsed | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
| `` ` `` | ファイルツリーの表示を切り替え | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` / `` | 検索を開始 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: コミットされたファイル名をクリップボードにコピー
<kbd>c</kbd>: Checkout file
<kbd>d</kbd>: Discard this commit's changes to this file
<kbd>o</kbd>: ファイルを開く
<kbd>e</kbd>: ファイルを編集
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;space&gt;</kbd>: Toggle file included in patch
<kbd>a</kbd>: Toggle all files included in patch
<kbd>&lt;enter&gt;</kbd>: Enter file to add selected lines to the patch (or toggle directory collapsed)
<kbd>`</kbd>: ファイルツリーの表示を切り替え
<kbd>/</kbd>: 検索を開始
</pre>
## コミットメッセージ
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 確認 | |
| `` <esc> `` | 閉じる | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 確認
<kbd>&lt;esc&gt;</kbd>: 閉じる
</pre>
## サブモジュール
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | サブモジュール名をクリップボードにコピー | |
| `` <enter> `` | Enter | サブモジュールを開く |
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
| `` u `` | Update | サブモジュールを更新 |
| `` n `` | サブモジュールを新規追加 | |
| `` e `` | サブモジュールのURLを更新 | |
| `` i `` | Initialize | サブモジュールを初期化 |
| `` b `` | View bulk submodule options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: サブモジュール名をクリップボードにコピー
<kbd>&lt;enter&gt;</kbd>: サブモジュールを開く
<kbd>&lt;space&gt;</kbd>: サブモジュールを開く
<kbd>d</kbd>: サブモジュールを削除
<kbd>u</kbd>: サブモジュールを更新
<kbd>n</kbd>: サブモジュールを新規追加
<kbd>e</kbd>: サブモジュールのURLを更新
<kbd>i</kbd>: サブモジュールを初期化
<kbd>b</kbd>: View bulk submodule options
<kbd>/</kbd>: Filter the current view by text
</pre>
## ステータス
| Key | Action | Info |
|-----|--------|-------------|
| `` o `` | 設定ファイルを開く | Open file in default application. |
| `` e `` | 設定ファイルを編集 | Open file in external editor. |
| `` u `` | 更新を確認 | |
| `` <enter> `` | 最近使用したリポジトリに切り替え | |
| `` a `` | すべてのブランチログを表示 | |
<pre>
<kbd>o</kbd>: 設定ファイルを開く
<kbd>e</kbd>: 設定ファイルを編集
<kbd>u</kbd>: 更新を確認
<kbd>&lt;enter&gt;</kbd>: 最近使用したリポジトリに切り替え
<kbd>a</kbd>: すべてのブランチログを表示
</pre>
## タグ
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | チェックアウト | Checkout the selected tag tag as a detached HEAD. |
| `` n `` | タグを作成 | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
| `` d `` | Delete | View delete options for local/remote tag. |
| `` P `` | タグをpush | Push the selected tag to a remote. You'll be prompted to select a remote. |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | コミットを閲覧 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: チェックアウト
<kbd>d</kbd>: View delete options
<kbd>P</kbd>: タグをpush
<kbd>n</kbd>: タグを作成
<kbd>g</kbd>: View reset options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: コミットを閲覧
<kbd>/</kbd>: Filter the current view by text
</pre>
## ファイル
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | ファイル名をクリップボードにコピー | |
| `` <space> `` | ステージ/アンステージ | Toggle staged for selected file. |
| `` <c-b> `` | ファイルをフィルタ (ステージ/アンステージ) | |
| `` y `` | Copy to clipboard | |
| `` c `` | 変更をコミット | Commit staged changes. |
| `` w `` | pre-commitフックを実行せずに変更をコミット | |
| `` A `` | 最新のコミットにamend | |
| `` C `` | gitエディタを使用して変更をコミット | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` e `` | Edit | Open file in external editor. |
| `` o `` | ファイルを開く | Open file in default application. |
| `` i `` | ファイルをignore | |
| `` r `` | ファイルをリフレッシュ | |
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
| `` S `` | View stash options | View stash options (e.g. stash all, stash staged, stash unstaged). |
| `` a `` | すべての変更をステージ/アンステージ | Toggle staged/unstaged for all files in working tree. |
| `` <enter> `` | Stage lines / Collapse directory | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
| `` d `` | Discard | View options for discarding changes to the selected file. |
| `` g `` | View upstream reset options | |
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
| `` ` `` | ファイルツリーの表示を切り替え | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` M `` | Git mergetoolを開く | Run `git mergetool`. |
| `` f `` | Fetch | Fetch changes from remote. |
| `` / `` | 検索を開始 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: ファイル名をクリップボードにコピー
<kbd>d</kbd>: View 'discard changes' options
<kbd>&lt;space&gt;</kbd>: ステージ/アンステージ
<kbd>&lt;c-b&gt;</kbd>: ファイルをフィルタ (ステージ/アンステージ)
<kbd>y</kbd>: Copy to clipboard
<kbd>c</kbd>: 変更をコミット
<kbd>w</kbd>: pre-commitフックを実行せずに変更をコミット
<kbd>A</kbd>: 最新のコミットにamend
<kbd>C</kbd>: gitエディタを使用して変更をコミット
<kbd>&lt;c-f&gt;</kbd>: Find base commit for fixup
<kbd>e</kbd>: ファイルを編集
<kbd>o</kbd>: ファイルを開く
<kbd>i</kbd>: ファイルをignore
<kbd>r</kbd>: ファイルをリフレッシュ
<kbd>s</kbd>: 変更をstash
<kbd>S</kbd>: View stash options
<kbd>a</kbd>: すべての変更をステージ/アンステージ
<kbd>&lt;enter&gt;</kbd>: Stage individual hunks/lines for file, or collapse/expand for directory
<kbd>g</kbd>: View upstream reset options
<kbd>D</kbd>: View reset options
<kbd>`</kbd>: ファイルツリーの表示を切り替え
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>M</kbd>: Git mergetoolを開く
<kbd>f</kbd>: Fetch
<kbd>/</kbd>: 検索を開始
</pre>
## ブランチ
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | ブランチ名をクリップボードにコピー | |
| `` i `` | Show git-flow options | |
| `` <space> `` | チェックアウト | Checkout selected item. |
| `` n `` | 新しいブランチを作成 | |
| `` o `` | Pull Requestを作成 | |
| `` O `` | View create pull request options | |
| `` <c-y> `` | Pull RequestのURLをクリップボードにコピー | |
| `` c `` | Checkout by name | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
| `` F `` | Force checkout | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
| `` d `` | Delete | View delete options for local/remote branch. |
| `` r `` | Rebase | Rebase the checked-out branch onto the selected branch. |
| `` M `` | 現在のブランチにマージ | Merge selected branch into currently checked out branch. |
| `` f `` | Fast-forward | Fast-forward selected branch from its upstream. |
| `` T `` | タグを作成 | |
| `` s `` | 並び替え | |
| `` g `` | Reset | |
| `` R `` | ブランチ名を変更 | |
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
| `` <enter> `` | コミットを閲覧 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: ブランチ名をクリップボードにコピー
<kbd>i</kbd>: Show git-flow options
<kbd>&lt;space&gt;</kbd>: チェックアウト
<kbd>n</kbd>: 新しいブランチを作成
<kbd>o</kbd>: Pull Requestを作成
<kbd>O</kbd>: Create pull request options
<kbd>&lt;c-y&gt;</kbd>: Pull RequestのURLをクリップボードにコピー
<kbd>c</kbd>: Checkout by name, enter '-' to switch to last
<kbd>F</kbd>: Force checkout
<kbd>d</kbd>: View delete options
<kbd>r</kbd>: Rebase checked-out branch onto this branch
<kbd>M</kbd>: 現在のブランチにマージ
<kbd>f</kbd>: Fast-forward this branch from its upstream
<kbd>T</kbd>: タグを作成
<kbd>s</kbd>: 並び替え
<kbd>g</kbd>: View reset options
<kbd>R</kbd>: ブランチ名を変更
<kbd>u</kbd>: View upstream options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: コミットを閲覧
<kbd>/</kbd>: Filter the current view by text
</pre>
## メインパネル (Merging)
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Pick hunk | |
| `` b `` | Pick all hunks | |
| `` <up> `` | 前のhunkを選択 | |
| `` <down> `` | 次のhunkを選択 | |
| `` <left> `` | 前のコンフリクトを選択 | |
| `` <right> `` | 次のコンフリクトを選択 | |
| `` z `` | アンドゥ | Undo last merge conflict resolution. |
| `` e `` | ファイルを編集 | Open file in external editor. |
| `` o `` | ファイルを開く | Open file in default application. |
| `` M `` | Git mergetoolを開く | Run `git mergetool`. |
| `` <esc> `` | ファイル一覧に戻る | |
<pre>
<kbd>e</kbd>: ファイルを編集
<kbd>o</kbd>: ファイルを開く
<kbd>&lt;left&gt;</kbd>: 前のコンフリクトを選択
<kbd>&lt;right&gt;</kbd>: 次のコンフリクトを選択
<kbd>&lt;up&gt;</kbd>: 前のhunkを選択
<kbd>&lt;down&gt;</kbd>: 次のhunkを選択
<kbd>z</kbd>: アンドゥ
<kbd>M</kbd>: Git mergetoolを開く
<kbd>&lt;space&gt;</kbd>: Pick hunk
<kbd>b</kbd>: Pick all hunks
<kbd>&lt;esc&gt;</kbd>: ファイル一覧に戻る
</pre>
## メインパネル (Normal)
| Key | Action | Info |
|-----|--------|-------------|
| `` mouse wheel down (fn+up) `` | 下にスクロール | |
| `` mouse wheel up (fn+down) `` | 上にスクロール | |
<pre>
<kbd>mouse wheel down</kbd>: 下にスクロール (fn+up)
<kbd>mouse wheel up</kbd>: 上にスクロール (fn+down)
</pre>
## メインパネル (Patch Building)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | 前のhunkを選択 | |
| `` <right> `` | 次のhunkを選択 | |
| `` v `` | 範囲選択を切り替え | |
| `` a `` | Hunk選択を切り替え | Toggle hunk selection mode. |
| `` <c-o> `` | 選択されたテキストをクリップボードにコピー | |
| `` o `` | ファイルを開く | Open file in default application. |
| `` e `` | ファイルを編集 | Open file in external editor. |
| `` <space> `` | 行をパッチに追加/削除 | |
| `` <esc> `` | Exit custom patch builder | |
| `` / `` | 検索を開始 | |
<pre>
<kbd>&lt;left&gt;</kbd>: 前のhunkを選択
<kbd>&lt;right&gt;</kbd>: 次のhunkを選択
<kbd>v</kbd>: 範囲選択を切り替え
<kbd>V</kbd>: 範囲選択を切り替え
<kbd>a</kbd>: Hunk選択を切り替え
<kbd>&lt;c-o&gt;</kbd>: 選択されたテキストをクリップボードにコピー
<kbd>o</kbd>: ファイルを開く
<kbd>e</kbd>: ファイルを編集
<kbd>&lt;space&gt;</kbd>: 行をパッチに追加/削除
<kbd>&lt;esc&gt;</kbd>: Exit custom patch builder
<kbd>/</kbd>: 検索を開始
</pre>
## メインパネル (Staging)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | 前のhunkを選択 | |
| `` <right> `` | 次のhunkを選択 | |
| `` v `` | 範囲選択を切り替え | |
| `` a `` | Hunk選択を切り替え | Toggle hunk selection mode. |
| `` <c-o> `` | 選択されたテキストをクリップボードにコピー | |
| `` <space> `` | ステージ/アンステージ | 選択行をステージ/アンステージ |
| `` d `` | 変更を削除 (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
| `` o `` | ファイルを開く | Open file in default application. |
| `` e `` | ファイルを編集 | Open file in external editor. |
| `` <esc> `` | ファイル一覧に戻る | |
| `` <tab> `` | パネルを切り替え | Switch to other view (staged/unstaged changes). |
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
| `` c `` | 変更をコミット | Commit staged changes. |
| `` w `` | pre-commitフックを実行せずに変更をコミット | |
| `` C `` | gitエディタを使用して変更をコミット | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` / `` | 検索を開始 | |
<pre>
<kbd>&lt;left&gt;</kbd>: 前のhunkを選択
<kbd>&lt;right&gt;</kbd>: 次のhunkを選択
<kbd>v</kbd>: 範囲選択を切り替え
<kbd>V</kbd>: 範囲選択を切り替え
<kbd>a</kbd>: Hunk選択を切り替え
<kbd>&lt;c-o&gt;</kbd>: 選択されたテキストをクリップボードにコピー
<kbd>o</kbd>: ファイルを開く
<kbd>e</kbd>: ファイルを編集
<kbd>&lt;esc&gt;</kbd>: ファイル一覧に戻る
<kbd>&lt;tab&gt;</kbd>: パネルを切り替え
<kbd>&lt;space&gt;</kbd>: 選択行をステージ/アンステージ
<kbd>d</kbd>: 変更を削除 (git reset)
<kbd>E</kbd>: Edit hunk
<kbd>c</kbd>: 変更をコミット
<kbd>w</kbd>: pre-commitフックを実行せずに変更をコミット
<kbd>C</kbd>: gitエディタを使用して変更をコミット
<kbd>/</kbd>: 検索を開始
</pre>
## メニュー
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 実行 | |
| `` <esc> `` | 閉じる | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 実行
<kbd>&lt;esc&gt;</kbd>: 閉じる
<kbd>/</kbd>: Filter the current view by text
</pre>
## リモート
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | View branches | |
| `` n `` | リモートを新規追加 | |
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
| `` e `` | Edit | リモートを編集 |
| `` f `` | Fetch | リモートをfetch |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>f</kbd>: リモートをfetch
<kbd>n</kbd>: リモートを新規追加
<kbd>d</kbd>: リモートを削除
<kbd>e</kbd>: リモートを編集
<kbd>/</kbd>: Filter the current view by text
</pre>
## リモートブランチ
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | ブランチ名をクリップボードにコピー | |
| `` <space> `` | チェックアウト | Checkout a new local branch based on the selected remote branch, or the remote branch as a detached head. |
| `` n `` | 新しいブランチを作成 | |
| `` M `` | 現在のブランチにマージ | Merge selected branch into currently checked out branch. |
| `` r `` | Rebase | Rebase the checked-out branch onto the selected branch. |
| `` d `` | Delete | Delete the remote branch from the remote. |
| `` u `` | Set as upstream | Set the selected remote branch as the upstream of the checked-out branch. |
| `` s `` | 並び替え | |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | コミットを閲覧 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: ブランチ名をクリップボードにコピー
<kbd>&lt;space&gt;</kbd>: チェックアウト
<kbd>n</kbd>: 新しいブランチを作成
<kbd>M</kbd>: 現在のブランチにマージ
<kbd>r</kbd>: Rebase checked-out branch onto this branch
<kbd>d</kbd>: Delete remote tag
<kbd>u</kbd>: Set as upstream of checked-out branch
<kbd>s</kbd>: 並び替え
<kbd>g</kbd>: View reset options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: コミットを閲覧
<kbd>/</kbd>: Filter the current view by text
</pre>
## 参照ログ
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | コミットのSHAをクリップボードにコピー | |
| `` <space> `` | チェックアウト | Checkout the selected commit as a detached HEAD. |
| `` y `` | コミットの情報をコピー | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | ブラウザでコミットを開く | |
| `` n `` | コミットにブランチを作成 | |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | コミットをコピー (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | コミットを閲覧 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: コミットのSHAをクリップボードにコピー
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: コミットをチェックアウト
<kbd>y</kbd>: コミットの情報をコピー
<kbd>o</kbd>: ブラウザでコミットを開く
<kbd>n</kbd>: コミットにブランチを作成
<kbd>g</kbd>: View reset options
<kbd>c</kbd>: コミットをコピー (cherry-pick)
<kbd>C</kbd>: コミットを範囲コピー (cherry-pick)
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: コミットを閲覧
<kbd>/</kbd>: Filter the current view by text
</pre>
## 確認パネル
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 確認 | |
| `` <esc> `` | 閉じる/キャンセル | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 確認
<kbd>&lt;esc&gt;</kbd>: 閉じる/キャンセル
</pre>

View File

@@ -6,359 +6,357 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
## 글로벌 키 바인딩
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-r> `` | 최근에 사용한 저장소로 전환 | |
| `` <pgup> (fn+up/shift+k) `` | 메인 패널을 로 스크롤 | |
| `` <pgdown> (fn+down/shift+j) `` | 메인 패널을 아래로로 스크롤 | |
| `` @ `` | 명령어 로그 메뉴 열기 | View options for the command log e.g. show/hide the command log and focus the command log. |
| `` P `` | 푸시 | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` p `` | 업데이트 | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` } `` | Diff 보기의 변경 사항 주위에 표시되는 컨텍스트의 크기를 늘리기 | Increase the amount of the context shown around changes in the diff view. |
| `` { `` | Diff 보기의 변경 사항 주위에 표시되는 컨텍스트 크기 줄이기 | Decrease the amount of the context shown around changes in the diff view. |
| `` : `` | Execute custom command | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
| `` <c-p> `` | 커스텀 Patch 옵션 보기 | |
| `` m `` | View merge/rebase options | View options to abort/continue/skip the current merge/rebase. |
| `` R `` | 새로고침 | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
| `` + `` | 다음 스크린 모드 (normal/half/fullscreen) | |
| `` _ `` | 이전 스크린 모드 | |
| `` ? `` | 매뉴 열기 | |
| `` <c-s> `` | View filter-by-path options | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | Diff 메뉴 열기 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | Diff 메뉴 열기 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | 종료 | |
| `` <esc> `` | 취소 | |
| `` <c-w> `` | 공백문자를 Diff 뷰에서 표시 여부 전환 | Toggle whether or not whitespace changes are shown in the diff view. |
| `` z `` | 되돌리기 (reflog) (실험적) | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
| `` <c-z> `` | 다시 실행 (reflog) (실험적) | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
<pre>
<kbd>&lt;c-r&gt;</kbd>: 최근에 사용한 저장소로 전환
<kbd>&lt;pgup&gt;</kbd>: 메인 패널을 위로 스크롤 (fn+up/shift+k)
<kbd>&lt;pgdown&gt;</kbd>: 메인 패널을 아래로로 스크롤 (fn+down/shift+j)
<kbd>@</kbd>: 명령어 로그 메뉴 열기
<kbd>}</kbd>: Diff 보기의 변경 사항 주위에 표시되는 컨텍스트의 크기를 늘리기
<kbd>{</kbd>: Diff 보기의 변경 사항 주위에 표시되는 컨텍스트 크기 줄이기
<kbd>:</kbd>: Execute custom command
<kbd>&lt;c-p&gt;</kbd>: 커스텀 Patch 옵션 보기
<kbd>m</kbd>: View merge/rebase options
<kbd>R</kbd>: 새로고침
<kbd>+</kbd>: 다음 스크린 모드 (normal/half/fullscreen)
<kbd>_</kbd>: 이전 스크린 모드
<kbd>?</kbd>: 매뉴 열기
<kbd>&lt;c-s&gt;</kbd>: View filter-by-path options
<kbd>W</kbd>: Diff 메뉴 열기
<kbd>&lt;c-e&gt;</kbd>: Diff 메뉴 열기
<kbd>&lt;c-w&gt;</kbd>: 공백문자를 Diff 뷰에서 표시 여부 전환
<kbd>z</kbd>: 되돌리기 (reflog) (실험적)
<kbd>&lt;c-z&gt;</kbd>: 다시 실행 (reflog) (실험적)
<kbd>P</kbd>: 푸시
<kbd>p</kbd>: 업데이트
</pre>
## List panel navigation
| Key | Action | Info |
|-----|--------|-------------|
| `` , `` | 이전 페이지 | |
| `` . `` | 다음 페이지 | |
| `` < `` |로 스크롤 | |
| `` > `` | 맨 아래로 스크롤 | |
| `` v `` | 드래그 선택 전환 | |
| `` <s-down> `` | Range select down | |
| `` <s-up> `` | Range select up | |
| `` / `` | 검색 시작 | |
| `` H `` | 우 스크롤 | |
| `` L `` | 좌 스크롤 | |
| `` ] `` | 이전 탭 | |
| `` [ `` | 다음 탭 | |
<pre>
<kbd>,</kbd>: 이전 페이지
<kbd>.</kbd>: 다음 페이지
<kbd>&lt;</kbd>: 맨 위로 스크롤
<kbd>&gt;</kbd>:아래로 스크롤
<kbd>/</kbd>: 검색 시작
<kbd>H</kbd>: 우 스크롤
<kbd>L</kbd>: 좌 스크롤
<kbd>]</kbd>: 이전 탭
<kbd>[</kbd>: 다음 탭
</pre>
## Reflog
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 커밋 SHA를 클립보드에 복사 | |
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 브라우저에서 커밋 열기 | |
| `` n `` | 커밋에서 새 브랜치를 만듭니다. | |
| `` g `` | View reset options | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | 커밋을 복사 (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | Reset cherry-picked (copied) commits selection | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | 커밋 보기 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 커밋 SHA를 클립보드에 복사
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: 커밋을 체크아웃
<kbd>y</kbd>: 커밋 attribute 복사
<kbd>o</kbd>: 브라우저에서 커밋 열기
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
<kbd>g</kbd>: View reset options
<kbd>c</kbd>: 커밋을 복사 (cherry-pick)
<kbd>C</kbd>: 커밋을 범위로 복사 (cherry-pick)
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: 커밋 보기
<kbd>/</kbd>: Filter the current view by text
</pre>
## Stash
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | 적용 | Apply the stash entry to your working directory. |
| `` g `` | Pop | Apply the stash entry to your working directory and remove the stash entry. |
| `` d `` | Drop | Remove the stash entry from the stash list. |
| `` n `` | 새 브랜치 생성 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
| `` r `` | Rename stash | |
| `` <enter> `` | View selected item's files | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: 적용
<kbd>g</kbd>: Pop
<kbd>d</kbd>: Drop
<kbd>n</kbd>: 새 브랜치 생성
<kbd>r</kbd>: Rename stash
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: View selected item's files
<kbd>/</kbd>: Filter the current view by text
</pre>
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 커밋 SHA를 클립보드에 복사 | |
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 브라우저에서 커밋 열기 | |
| `` n `` | 커밋에서 새 브랜치를 만듭니다. | |
| `` g `` | View reset options | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | 커밋을 복사 (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | Reset cherry-picked (copied) commits selection | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | View selected item's files | |
| `` w `` | View worktree options | |
| `` / `` | 검색 시작 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 커밋 SHA를 클립보드에 복사
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: 커밋을 체크아웃
<kbd>y</kbd>: 커밋 attribute 복사
<kbd>o</kbd>: 브라우저에서 커밋 열기
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
<kbd>g</kbd>: View reset options
<kbd>c</kbd>: 커밋을 복사 (cherry-pick)
<kbd>C</kbd>: 커밋을 범위로 복사 (cherry-pick)
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: View selected item's files
<kbd>/</kbd>: 검색 시작
</pre>
## Worktrees
| Key | Action | Info |
|-----|--------|-------------|
| `` n `` | New worktree | |
| `` <space> `` | Switch | Switch to the selected worktree. |
| `` o `` | Open in editor | |
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>n</kbd>: Create worktree
<kbd>&lt;space&gt;</kbd>: Switch to worktree
<kbd>&lt;enter&gt;</kbd>: Switch to worktree
<kbd>o</kbd>: Open in editor
<kbd>d</kbd>: Remove worktree
<kbd>/</kbd>: Filter the current view by text
</pre>
## 메뉴
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 실행 | |
| `` <esc> `` | 닫기 | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 실행
<kbd>&lt;esc&gt;</kbd>: 닫기
<kbd>/</kbd>: Filter the current view by text
</pre>
## 메인 패널 (Merging)
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Pick hunk | |
| `` b `` | Pick all hunks | |
| `` <up> `` | 이전 hunk를 선택 | |
| `` <down> `` | 다음 hunk를 선택 | |
| `` <left> `` | 이전 충돌을 선택 | |
| `` <right> `` | 다음 충돌을 선택 | |
| `` z `` | 되돌리기 | Undo last merge conflict resolution. |
| `` e `` | 파일 편집 | Open file in external editor. |
| `` o `` | 파일 닫기 | Open file in default application. |
| `` M `` | Git mergetool를 열기 | Run `git mergetool`. |
| `` <esc> `` | 파일 목록으로 돌아가기 | |
<pre>
<kbd>e</kbd>: 파일 편집
<kbd>o</kbd>: 파일 닫기
<kbd>&lt;left&gt;</kbd>: 이전 충돌을 선택
<kbd>&lt;right&gt;</kbd>: 다음 충돌을 선택
<kbd>&lt;up&gt;</kbd>: 이전 hunk를 선택
<kbd>&lt;down&gt;</kbd>: 다음 hunk를 선택
<kbd>z</kbd>: 되돌리기
<kbd>M</kbd>: Git mergetool를 열기
<kbd>&lt;space&gt;</kbd>: Pick hunk
<kbd>b</kbd>: Pick all hunks
<kbd>&lt;esc&gt;</kbd>: 파일 목록으로 돌아가기
</pre>
## 메인 패널 (Normal)
| Key | Action | Info |
|-----|--------|-------------|
| `` mouse wheel down (fn+up) `` | 아래로 스크롤 | |
| `` mouse wheel up (fn+down) `` | 위로 스크롤 | |
<pre>
<kbd>mouse wheel down</kbd>: 아래로 스크롤 (fn+up)
<kbd>mouse wheel up</kbd>: 위로 스크롤 (fn+down)
</pre>
## 메인 패널 (Patch Building)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | 이전 hunk를 선택 | |
| `` <right> `` | 다음 hunk를 선택 | |
| `` v `` | 드래그 선택 전환 | |
| `` a `` | Toggle select hunk | Toggle hunk selection mode. |
| `` <c-o> `` | 선택한 텍스트를 클립보드에 복사 | |
| `` o `` | 파일 닫기 | Open file in default application. |
| `` e `` | 파일 편집 | Open file in external editor. |
| `` <space> `` | Line(s)을 패치에 추가/삭제 | |
| `` <esc> `` | Exit custom patch builder | |
| `` / `` | 검색 시작 | |
<pre>
<kbd>&lt;left&gt;</kbd>: 이전 hunk를 선택
<kbd>&lt;right&gt;</kbd>: 다음 hunk를 선택
<kbd>v</kbd>: 드래그 선택 전환
<kbd>V</kbd>: 드래그 선택 전환
<kbd>a</kbd>: Toggle select hunk
<kbd>&lt;c-o&gt;</kbd>: 선택한 텍스트를 클립보드에 복사
<kbd>o</kbd>: 파일 닫기
<kbd>e</kbd>: 파일 편집
<kbd>&lt;space&gt;</kbd>: Line(s)을 패치에 추가/삭제
<kbd>&lt;esc&gt;</kbd>: Exit custom patch builder
<kbd>/</kbd>: 검색 시작
</pre>
## 메인 패널 (Staging)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | 이전 hunk를 선택 | |
| `` <right> `` | 다음 hunk를 선택 | |
| `` v `` | 드래그 선택 전환 | |
| `` a `` | Toggle select hunk | Toggle hunk selection mode. |
| `` <c-o> `` | 선택한 텍스트를 클립보드에 복사 | |
| `` <space> `` | Staged 전환 | 선택한 행을 staged / unstaged |
| `` d `` | 변경을 삭제 (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
| `` o `` | 파일 닫기 | Open file in default application. |
| `` e `` | 파일 편집 | Open file in external editor. |
| `` <esc> `` | 파일 목록으로 돌아가기 | |
| `` <tab> `` | 패널 전환 | Switch to other view (staged/unstaged changes). |
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
| `` c `` | 커밋 변경내용 | Commit staged changes. |
| `` w `` | Commit changes without pre-commit hook | |
| `` C `` | Git 편집기를 사용하여 변경 내용을 커밋합니다. | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` / `` | 검색 시작 | |
<pre>
<kbd>&lt;left&gt;</kbd>: 이전 hunk를 선택
<kbd>&lt;right&gt;</kbd>: 다음 hunk를 선택
<kbd>v</kbd>: 드래그 선택 전환
<kbd>V</kbd>: 드래그 선택 전환
<kbd>a</kbd>: Toggle select hunk
<kbd>&lt;c-o&gt;</kbd>: 선택한 텍스트를 클립보드에 복사
<kbd>o</kbd>: 파일 닫기
<kbd>e</kbd>: 파일 편집
<kbd>&lt;esc&gt;</kbd>: 파일 목록으로 돌아가기
<kbd>&lt;tab&gt;</kbd>: 패널 전환
<kbd>&lt;space&gt;</kbd>: 선택한 행을 staged / unstaged
<kbd>d</kbd>: 변경을 삭제 (git reset)
<kbd>E</kbd>: Edit hunk
<kbd>c</kbd>: 커밋 변경내용
<kbd>w</kbd>: Commit changes without pre-commit hook
<kbd>C</kbd>: Git 편집기를 사용하여 변경 내용을 커밋합니다.
<kbd>/</kbd>: 검색 시작
</pre>
## 브랜치
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 브랜치명을 클립보드에 복사 | |
| `` i `` | Git-flow 옵션 보기 | |
| `` <space> `` | 체크아웃 | Checkout selected item. |
| `` n `` | 새 브랜치 생성 | |
| `` o `` | 풀 리퀘스트 생성 | |
| `` O `` | 풀 리퀘스트 생성 옵션 | |
| `` <c-y> `` | 풀 리퀘스트 URL을 클립보드에 복사 | |
| `` c `` | 이름으로 체크아웃 | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
| `` F `` | 강제 체크아웃 | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
| `` d `` | Delete | View delete options for local/remote branch. |
| `` r `` | 체크아웃된 브랜치를 이 브랜치에 리베이스 | Rebase the checked-out branch onto the selected branch. |
| `` M `` | 현재 브랜치에 병합 | Merge selected branch into currently checked out branch. |
| `` f `` | Fast-forward this branch from its upstream | Fast-forward selected branch from its upstream. |
| `` T `` | 태그를 생성 | |
| `` s `` | Sort order | |
| `` g `` | View reset options | |
| `` R `` | 브랜치 이름 변경 | |
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
| `` <enter> `` | 커밋 보기 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 브랜치명을 클립보드에 복사
<kbd>i</kbd>: Git-flow 옵션 보기
<kbd>&lt;space&gt;</kbd>: 체크아웃
<kbd>n</kbd>: 새 브랜치 생성
<kbd>o</kbd>: 풀 리퀘스트 생성
<kbd>O</kbd>: 풀 리퀘스트 생성 옵션
<kbd>&lt;c-y&gt;</kbd>: 풀 리퀘스트 URL을 클립보드에 복사
<kbd>c</kbd>: 이름으로 체크아웃
<kbd>F</kbd>: 강제 체크아웃
<kbd>d</kbd>: View delete options
<kbd>r</kbd>: 체크아웃된 브랜치를 이 브랜치에 리베이스
<kbd>M</kbd>: 현재 브랜치에 병합
<kbd>f</kbd>: Fast-forward this branch from its upstream
<kbd>T</kbd>: 태그를 생성
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: View reset options
<kbd>R</kbd>: 브랜치 이름 변경
<kbd>u</kbd>: View upstream options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 커밋 보기
<kbd>/</kbd>: Filter the current view by text
</pre>
## 상태
| Key | Action | Info |
|-----|--------|-------------|
| `` o `` | 설정 파일 열기 | Open file in default application. |
| `` e `` | 설정 파일 수정 | Open file in external editor. |
| `` u `` | 업데이트 확인 | |
| `` <enter> `` | 최근에 사용한 저장소로 전환 | |
| `` a `` | 모든 브랜치 로그 표시 | |
<pre>
<kbd>o</kbd>: 설정 파일 열기
<kbd>e</kbd>: 설정 파일 수정
<kbd>u</kbd>: 업데이트 확인
<kbd>&lt;enter&gt;</kbd>: 최근에 사용한 저장소로 전환
<kbd>a</kbd>: 모든 브랜치 로그 표시
</pre>
## 서브모듈
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 서브모듈 이름을 클립보드에 복사 | |
| `` <enter> `` | Enter | 서브모듈 열기 |
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
| `` u `` | Update | 서브모듈 업데이트 |
| `` n `` | 새로운 서브모듈 추가 | |
| `` e `` | 서브모듈의 URL을 수정 | |
| `` i `` | Initialize | 서브모듈 초기화 |
| `` b `` | View bulk submodule options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 서브모듈 이름을 클립보드에 복사
<kbd>&lt;enter&gt;</kbd>: 서브모듈 열기
<kbd>&lt;space&gt;</kbd>: 서브모듈 열기
<kbd>d</kbd>: 서브모듈 삭제
<kbd>u</kbd>: 서브모듈 업데이트
<kbd>n</kbd>: 새로운 서브모듈 추가
<kbd>e</kbd>: 서브모듈의 URL을 수정
<kbd>i</kbd>: 서브모듈 초기화
<kbd>b</kbd>: View bulk submodule options
<kbd>/</kbd>: Filter the current view by text
</pre>
## 원격
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | View branches | |
| `` n `` | 새로운 Remote 추가 | |
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
| `` e `` | Edit | Remote를 수정 |
| `` f `` | Fetch | 원격을 업데이트 |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>f</kbd>: 원격을 업데이트
<kbd>n</kbd>: 새로운 Remote 추가
<kbd>d</kbd>: Remote를 삭제
<kbd>e</kbd>: Remote를 수정
<kbd>/</kbd>: Filter the current view by text
</pre>
## 원격 브랜치
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 브랜치명을 클립보드에 복사 | |
| `` <space> `` | 체크아웃 | Checkout a new local branch based on the selected remote branch, or the remote branch as a detached head. |
| `` n `` | 새 브랜치 생성 | |
| `` M `` | 현재 브랜치에 병합 | Merge selected branch into currently checked out branch. |
| `` r `` | 체크아웃된 브랜치를 이 브랜치에 리베이스 | Rebase the checked-out branch onto the selected branch. |
| `` d `` | Delete | Delete the remote branch from the remote. |
| `` u `` | Set as upstream | Set the selected remote branch as the upstream of the checked-out branch. |
| `` s `` | Sort order | |
| `` g `` | View reset options | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | 커밋 보기 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 브랜치명을 클립보드에 복사
<kbd>&lt;space&gt;</kbd>: 체크아웃
<kbd>n</kbd>: 새 브랜치 생성
<kbd>M</kbd>: 현재 브랜치에 병합
<kbd>r</kbd>: 체크아웃된 브랜치를 이 브랜치에 리베이스
<kbd>d</kbd>: Delete remote tag
<kbd>u</kbd>: Set as upstream of checked-out branch
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: View reset options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 커밋 보기
<kbd>/</kbd>: Filter the current view by text
</pre>
## 커밋
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 커밋 SHA를 클립보드에 복사 | |
| `` <c-r> `` | Reset cherry-picked (copied) commits selection | |
| `` b `` | Bisect 옵션 보기 | |
| `` 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 fixup, but the selected commit's message will be discarded. |
| `` 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. |
| `` e `` | Edit (start interactive rebase) | 커밋을 편집 |
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
| `` p `` | Pick | Pick commit (when mid-rebase) |
| `` F `` | Create fixup commit | Create fixup commit for this commit |
| `` S `` | Apply fixup commits | Squash all 'fixup!' commits above selected commit (autosquash) |
| `` <c-j> `` | 커밋을 1개 아래로 이동 | |
| `` <c-k> `` | 커밋을 1개 위로 이동 | |
| `` V `` | 커밋을 붙여넣기 (cherry-pick) | |
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
| `` A `` | Amend | Amend commit with staged changes |
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
| `` T `` | Tag commit | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
| `` <c-l> `` | 로그 메뉴 열기 | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 브라우저에서 커밋 열기 | |
| `` n `` | 커밋에서 새 브랜치를 만듭니다. | |
| `` g `` | View reset options | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | 커밋을 복사 (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | View selected item's files | |
| `` w `` | View worktree options | |
| `` / `` | 검색 시작 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 커밋 SHA를 클립보드에 복사
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>b</kbd>: Bisect 옵션 보기
<kbd>s</kbd>: Squash down
<kbd>f</kbd>: Fixup commit
<kbd>r</kbd>: 커밋메시지 변경
<kbd>R</kbd>: 에디터에서 커밋메시지 수정
<kbd>d</kbd>: 커밋 삭제
<kbd>e</kbd>: 커밋을 편집
<kbd>p</kbd>: Pick commit (when mid-rebase)
<kbd>F</kbd>: Create fixup commit for this commit
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
<kbd>&lt;c-j&gt;</kbd>: 커밋을 1개 아래로 이동
<kbd>&lt;c-k&gt;</kbd>: 커밋을 1개 위로 이동
<kbd>v</kbd>: 커밋을 붙여넣기 (cherry-pick)
<kbd>B</kbd>: Mark commit as base commit for rebase
<kbd>A</kbd>: Amend commit with staged changes
<kbd>a</kbd>: Set/Reset commit author
<kbd>t</kbd>: 커밋 되돌리기
<kbd>T</kbd>: Tag commit
<kbd>&lt;c-l&gt;</kbd>: 로그 메뉴 열기
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: 커밋을 체크아웃
<kbd>y</kbd>: 커밋 attribute 복사
<kbd>o</kbd>: 브라우저에서 커밋 열기
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
<kbd>g</kbd>: View reset options
<kbd>c</kbd>: 커밋을 복사 (cherry-pick)
<kbd>C</kbd>: 커밋을 범위로 복사 (cherry-pick)
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: View selected item's files
<kbd>/</kbd>: 검색 시작
</pre>
## 커밋 파일
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 파일명을 클립보드에 복사 | |
| `` c `` | 체크아웃 | Checkout file |
| `` d `` | Remove | 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) | |
| `` <space> `` | Toggle file included in patch | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` a `` | Toggle all files included in patch | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` <enter> `` | Enter file to add selected lines to the patch (or toggle directory collapsed) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
| `` ` `` | 파일 트리뷰로 전환 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` / `` | 검색 시작 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 커밋한 파일명을 클립보드에 복사
<kbd>c</kbd>: Checkout file
<kbd>d</kbd>: Discard this commit's changes to this file
<kbd>o</kbd>: 파일 닫기
<kbd>e</kbd>: 파일 편집
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;space&gt;</kbd>: Toggle file included in patch
<kbd>a</kbd>: Toggle all files included in patch
<kbd>&lt;enter&gt;</kbd>: Enter file to add selected lines to the patch (or toggle directory collapsed)
<kbd>`</kbd>: 파일 트리뷰로 전환
<kbd>/</kbd>: 검색 시작
</pre>
## 커밋메시지
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 확인 | |
| `` <esc> `` | 닫기 | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 확인
<kbd>&lt;esc&gt;</kbd>: 닫기
</pre>
## 태그
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | 체크아웃 | Checkout the selected tag tag as a detached HEAD. |
| `` n `` | 태그를 생성 | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
| `` d `` | Delete | View delete options for local/remote tag. |
| `` P `` | 태그를 push | Push the selected tag to a remote. You'll be prompted to select a remote. |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | 커밋 보기 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: 체크아웃
<kbd>d</kbd>: View delete options
<kbd>P</kbd>: 태그를 push
<kbd>n</kbd>: 태그를 생성
<kbd>g</kbd>: View reset options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 커밋 보기
<kbd>/</kbd>: Filter the current view by text
</pre>
## 파일
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 파일명을 클립보드에 복사 | |
| `` <space> `` | Staged 전환 | Toggle staged for selected file. |
| `` <c-b> `` | 파일을 필터하기 (Staged/unstaged) | |
| `` y `` | Copy to clipboard | |
| `` c `` | 커밋 변경내용 | Commit staged changes. |
| `` w `` | Commit changes without pre-commit hook | |
| `` A `` | 마지맛 커밋 수정 | |
| `` C `` | Git 편집기를 사용하여 변경 내용을 커밋합니다. | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` e `` | Edit | Open file in external editor. |
| `` o `` | 파일 닫기 | Open file in default application. |
| `` i `` | Ignore file | |
| `` r `` | 파일 새로고침 | |
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
| `` S `` | Stash 옵션 보기 | View stash options (e.g. stash all, stash staged, stash unstaged). |
| `` a `` | 모든 변경을 Staged/unstaged으로 전환 | Toggle staged/unstaged for all files in working tree. |
| `` <enter> `` | Stage individual hunks/lines for file, or collapse/expand for directory | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
| `` d `` | View 'discard changes' options | View options for discarding changes to the selected file. |
| `` g `` | View upstream reset options | |
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
| `` ` `` | 파일 트리뷰로 전환 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` M `` | Git mergetool를 열기 | Run `git mergetool`. |
| `` f `` | Fetch | Fetch changes from remote. |
| `` / `` | 검색 시작 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 파일명을 클립보드에 복사
<kbd>d</kbd>: View 'discard changes' options
<kbd>&lt;space&gt;</kbd>: Staged 전환
<kbd>&lt;c-b&gt;</kbd>: 파일을 필터하기 (Staged/unstaged)
<kbd>y</kbd>: Copy to clipboard
<kbd>c</kbd>: 커밋 변경내용
<kbd>w</kbd>: Commit changes without pre-commit hook
<kbd>A</kbd>: 마지맛 커밋 수정
<kbd>C</kbd>: Git 편집기를 사용하여 변경 내용을 커밋합니다.
<kbd>&lt;c-f&gt;</kbd>: Find base commit for fixup
<kbd>e</kbd>: 파일 편집
<kbd>o</kbd>: 파일 닫기
<kbd>i</kbd>: Ignore file
<kbd>r</kbd>: 파일 새로고침
<kbd>s</kbd>: 변경사항을 Stash
<kbd>S</kbd>: Stash 옵션 보기
<kbd>a</kbd>: 모든 변경을 Staged/unstaged으로 전환
<kbd>&lt;enter&gt;</kbd>: Stage individual hunks/lines for file, or collapse/expand for directory
<kbd>g</kbd>: View upstream reset options
<kbd>D</kbd>: View reset options
<kbd>`</kbd>: 파일 트리뷰로 전환
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>M</kbd>: Git mergetool를 열기
<kbd>f</kbd>: Fetch
<kbd>/</kbd>: 검색 시작
</pre>
## 확인 패널
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 확인 | |
| `` <esc> `` | 닫기/취소 | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 확인
<kbd>&lt;esc&gt;</kbd>: 닫기/취소
</pre>

View File

@@ -6,359 +6,357 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
## Globale sneltoetsen
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-r> `` | Wissel naar een recente repo | |
| `` <pgup> (fn+up/shift+k) `` | Scroll naar beneden vanaf hoofdpaneel | |
| `` <pgdown> (fn+down/shift+j) `` | Scroll naar beneden vanaf hoofdpaneel | |
| `` @ `` | View command log options | View options for the command log e.g. show/hide the command log and focus the command log. |
| `` P `` | Push | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` p `` | Pull | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` } `` | Increase diff context size | Increase the amount of the context shown around changes in the diff view. |
| `` { `` | Decrease diff context size | Decrease the amount of the context shown around changes in the diff view. |
| `` : `` | Voer aangepaste commando uit | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
| `` <c-p> `` | Bekijk aangepaste patch opties | |
| `` m `` | Bekijk merge/rebase opties | View options to abort/continue/skip the current merge/rebase. |
| `` R `` | Verversen | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
| `` + `` | Volgende scherm modus (normaal/half/groot) | |
| `` _ `` | Vorige scherm modus | |
| `` ? `` | Open menu | |
| `` <c-s> `` | Bekijk scoping opties | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | Open diff menu | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | Open diff menu | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | Quit | |
| `` <esc> `` | Annuleren | |
| `` <c-w> `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view. |
| `` z `` | Ongedaan maken (via reflog) (experimenteel) | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
| `` <c-z> `` | Redo (via reflog) (experimenteel) | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
<pre>
<kbd>&lt;c-r&gt;</kbd>: Wissel naar een recente repo
<kbd>&lt;pgup&gt;</kbd>: Scroll naar beneden vanaf hoofdpaneel (fn+up/shift+k)
<kbd>&lt;pgdown&gt;</kbd>: Scroll naar beneden vanaf hoofdpaneel (fn+down/shift+j)
<kbd>@</kbd>: Open command log menu
<kbd>}</kbd>: Increase the size of the context shown around changes in the diff view
<kbd>{</kbd>: Decrease the size of the context shown around changes in the diff view
<kbd>:</kbd>: Voer aangepaste commando uit
<kbd>&lt;c-p&gt;</kbd>: Bekijk aangepaste patch opties
<kbd>m</kbd>: Bekijk merge/rebase opties
<kbd>R</kbd>: Verversen
<kbd>+</kbd>: Volgende scherm modus (normaal/half/groot)
<kbd>_</kbd>: Vorige scherm modus
<kbd>?</kbd>: Open menu
<kbd>&lt;c-s&gt;</kbd>: Bekijk scoping opties
<kbd>W</kbd>: Open diff menu
<kbd>&lt;c-e&gt;</kbd>: Open diff menu
<kbd>&lt;c-w&gt;</kbd>: Toggle whether or not whitespace changes are shown in the diff view
<kbd>z</kbd>: Ongedaan maken (via reflog) (experimenteel)
<kbd>&lt;c-z&gt;</kbd>: Redo (via reflog) (experimenteel)
<kbd>P</kbd>: Push
<kbd>p</kbd>: Pull
</pre>
## Lijstpaneel navigatie
| Key | Action | Info |
|-----|--------|-------------|
| `` , `` | Vorige pagina | |
| `` . `` | Volgende pagina | |
| `` < `` | Scroll naar boven | |
| `` > `` | Scroll naar beneden | |
| `` v `` | Toggle drag selecteer | |
| `` <s-down> `` | Range select down | |
| `` <s-up> `` | Range select up | |
| `` / `` | Start met zoeken | |
| `` H `` | Scroll left | |
| `` L `` | Scroll right | |
| `` ] `` | Volgende tabblad | |
| `` [ `` | Vorige tabblad | |
<pre>
<kbd>,</kbd>: Vorige pagina
<kbd>.</kbd>: Volgende pagina
<kbd>&lt;</kbd>: Scroll naar boven
<kbd>&gt;</kbd>: Scroll naar beneden
<kbd>/</kbd>: Start met zoeken
<kbd>H</kbd>: Scroll left
<kbd>L</kbd>: Scroll right
<kbd>]</kbd>: Volgende tabblad
<kbd>[</kbd>: Vorige tabblad
</pre>
## Bestanden
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer de bestandsnaam naar het klembord | |
| `` <space> `` | Toggle staged | Toggle staged for selected file. |
| `` <c-b> `` | Filter files by status | |
| `` y `` | Copy to clipboard | |
| `` c `` | Commit veranderingen | Commit staged changes. |
| `` w `` | Commit veranderingen zonder pre-commit hook | |
| `` A `` | Wijzig laatste commit | |
| `` C `` | Commit veranderingen met de git editor | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` e `` | Edit | Open file in external editor. |
| `` o `` | Open bestand | Open file in default application. |
| `` i `` | Ignore or exclude file | |
| `` r `` | Refresh bestanden | |
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
| `` S `` | Bekijk stash opties | View stash options (e.g. stash all, stash staged, stash unstaged). |
| `` a `` | Toggle staged alle | Toggle staged/unstaged for all files in working tree. |
| `` <enter> `` | Stage individuele hunks/lijnen | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
| `` d `` | Bekijk 'veranderingen ongedaan maken' opties | View options for discarding changes to the selected file. |
| `` g `` | Bekijk upstream reset opties | |
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
| `` ` `` | Toggle bestandsboom weergave | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` M `` | Open external merge tool | Run `git mergetool`. |
| `` f `` | Fetch | Fetch changes from remote. |
| `` / `` | Start met zoeken | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Kopieer de bestandsnaam naar het klembord
<kbd>d</kbd>: Bekijk 'veranderingen ongedaan maken' opties
<kbd>&lt;space&gt;</kbd>: Toggle staged
<kbd>&lt;c-b&gt;</kbd>: Filter files by status
<kbd>y</kbd>: Copy to clipboard
<kbd>c</kbd>: Commit veranderingen
<kbd>w</kbd>: Commit veranderingen zonder pre-commit hook
<kbd>A</kbd>: Wijzig laatste commit
<kbd>C</kbd>: Commit veranderingen met de git editor
<kbd>&lt;c-f&gt;</kbd>: Find base commit for fixup
<kbd>e</kbd>: Verander bestand
<kbd>o</kbd>: Open bestand
<kbd>i</kbd>: Ignore or exclude file
<kbd>r</kbd>: Refresh bestanden
<kbd>s</kbd>: Stash-bestanden
<kbd>S</kbd>: Bekijk stash opties
<kbd>a</kbd>: Toggle staged alle
<kbd>&lt;enter&gt;</kbd>: Stage individuele hunks/lijnen
<kbd>g</kbd>: Bekijk upstream reset opties
<kbd>D</kbd>: Bekijk reset opties
<kbd>`</kbd>: Toggle bestandsboom weergave
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>M</kbd>: Open external merge tool (git mergetool)
<kbd>f</kbd>: Fetch
<kbd>/</kbd>: Start met zoeken
</pre>
## Bevestigingspaneel
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Bevestig | |
| `` <esc> `` | Sluiten | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Bevestig
<kbd>&lt;esc&gt;</kbd>: Sluiten
</pre>
## Branches
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer branch name naar klembord | |
| `` i `` | Laat git-flow opties zien | |
| `` <space> `` | Uitchecken | Checkout selected item. |
| `` n `` | Nieuwe branch | |
| `` o `` | Maak een pull-request | |
| `` O `` | Bekijk opties voor pull-aanvraag | |
| `` <c-y> `` | Kopieer de URL van het pull-verzoek naar het klembord | |
| `` c `` | Uitchecken bij naam | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
| `` F `` | Forceer checkout | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
| `` d `` | Delete | View delete options for local/remote branch. |
| `` r `` | Rebase branch | Rebase the checked-out branch onto the selected branch. |
| `` M `` | Merge in met huidige checked out branch | Merge selected branch into currently checked out branch. |
| `` f `` | Fast-forward deze branch vanaf zijn upstream | Fast-forward selected branch from its upstream. |
| `` T `` | Creëer tag | |
| `` s `` | Sort order | |
| `` g `` | Bekijk reset opties | |
| `` R `` | Hernoem branch | |
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
| `` <enter> `` | Bekijk commits | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Kopieer branch name naar klembord
<kbd>i</kbd>: Laat git-flow opties zien
<kbd>&lt;space&gt;</kbd>: Uitchecken
<kbd>n</kbd>: Nieuwe branch
<kbd>o</kbd>: Maak een pull-request
<kbd>O</kbd>: Bekijk opties voor pull-aanvraag
<kbd>&lt;c-y&gt;</kbd>: Kopieer de URL van het pull-verzoek naar het klembord
<kbd>c</kbd>: Uitchecken bij naam
<kbd>F</kbd>: Forceer checkout
<kbd>d</kbd>: View delete options
<kbd>r</kbd>: Rebase branch
<kbd>M</kbd>: Merge in met huidige checked out branch
<kbd>f</kbd>: Fast-forward deze branch vanaf zijn upstream
<kbd>T</kbd>: Creëer tag
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: Bekijk reset opties
<kbd>R</kbd>: Hernoem branch
<kbd>u</kbd>: View upstream options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: Bekijk commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Commit bericht
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Bevestig | |
| `` <esc> `` | Sluiten | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Bevestig
<kbd>&lt;esc&gt;</kbd>: Sluiten
</pre>
## Commit bestanden
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer de bestandsnaam naar het klembord | |
| `` c `` | Uitchecken | Bestand uitchecken |
| `` d `` | Remove | 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) | |
| `` <space> `` | Toggle bestand inbegrepen in patch | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` <enter> `` | Enter bestand om geselecteerde regels toe te voegen aan de patch | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
| `` ` `` | Toggle bestandsboom weergave | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` / `` | Start met zoeken | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Kopieer de vastgelegde bestandsnaam naar het klembord
<kbd>c</kbd>: Bestand uitchecken
<kbd>d</kbd>: Uitsluit deze commit zijn veranderingen aan dit bestand
<kbd>o</kbd>: Open bestand
<kbd>e</kbd>: Verander bestand
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;space&gt;</kbd>: Toggle bestand inbegrepen in patch
<kbd>a</kbd>: Toggle all files included in patch
<kbd>&lt;enter&gt;</kbd>: Enter bestand om geselecteerde regels toe te voegen aan de patch
<kbd>`</kbd>: Toggle bestandsboom weergave
<kbd>/</kbd>: Start met zoeken
</pre>
## Commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer commit SHA naar klembord | |
| `` <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 fixup, but the selected commit's message will be discarded. |
| `` 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. |
| `` e `` | Edit (start interactive rebase) | Wijzig commit |
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
| `` p `` | Pick | Kies commit (wanneer midden in rebase) |
| `` F `` | Creëer fixup commit | Creëer fixup commit |
| `` S `` | Apply fixup commits | Squash bovenstaande commits |
| `` <c-j> `` | Verplaats commit 1 naar beneden | |
| `` <c-k> `` | Verplaats commit 1 naar boven | |
| `` V `` | Plak commits (cherry-pick) | |
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
| `` A `` | Amend | Wijzig commit met staged veranderingen |
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
| `` T `` | Tag commit | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
| `` <c-l> `` | View log options | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
| `` <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 | |
| `` n `` | Creëer nieuwe branch van commit | |
| `` g `` | Bekijk reset opties | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | Kopieer commit (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | Bekijk gecommite bestanden | |
| `` w `` | View worktree options | |
| `` / `` | Start met zoeken | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Kopieer commit SHA naar klembord
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (gekopieerde) commits selectie
<kbd>b</kbd>: View bisect options
<kbd>s</kbd>: Squash beneden
<kbd>f</kbd>: Fixup commit
<kbd>r</kbd>: Hernoem commit
<kbd>R</kbd>: Hernoem commit met editor
<kbd>d</kbd>: Verwijder commit
<kbd>e</kbd>: Wijzig commit
<kbd>p</kbd>: Kies commit (wanneer midden in rebase)
<kbd>F</kbd>: Creëer fixup commit
<kbd>S</kbd>: Squash bovenstaande commits
<kbd>&lt;c-j&gt;</kbd>: Verplaats commit 1 naar beneden
<kbd>&lt;c-k&gt;</kbd>: Verplaats commit 1 naar boven
<kbd>v</kbd>: Plak commits (cherry-pick)
<kbd>B</kbd>: Mark commit as base commit for rebase
<kbd>A</kbd>: Wijzig commit met staged veranderingen
<kbd>a</kbd>: Set/Reset commit author
<kbd>t</kbd>: Commit ongedaan maken
<kbd>T</kbd>: Tag commit
<kbd>&lt;c-l&gt;</kbd>: Open log menu
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Checkout commit
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: Open commit in browser
<kbd>n</kbd>: Creëer nieuwe branch van commit
<kbd>g</kbd>: Bekijk reset opties
<kbd>c</kbd>: Kopieer commit (cherry-pick)
<kbd>C</kbd>: Kopieer commit reeks (cherry-pick)
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: Bekijk gecommite bestanden
<kbd>/</kbd>: Start met zoeken
</pre>
## Menu
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Uitvoeren | |
| `` <esc> `` | Sluiten | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Uitvoeren
<kbd>&lt;esc&gt;</kbd>: Sluiten
<kbd>/</kbd>: Filter the current view by text
</pre>
## Mergen
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Kies stuk | |
| `` b `` | Kies beide stukken | |
| `` <up> `` | Selecteer bovenste hunk | |
| `` <down> `` | Selecteer onderste hunk | |
| `` <left> `` | Selecteer voorgaand conflict | |
| `` <right> `` | Selecteer volgende conflict | |
| `` z `` | Ongedaan maken | Undo last merge conflict resolution. |
| `` e `` | Verander bestand | Open file in external editor. |
| `` o `` | Open bestand | Open file in default application. |
| `` M `` | Open external merge tool | Run `git mergetool`. |
| `` <esc> `` | Ga terug naar het bestanden paneel | |
<pre>
<kbd>e</kbd>: Verander bestand
<kbd>o</kbd>: Open bestand
<kbd>&lt;left&gt;</kbd>: Selecteer voorgaand conflict
<kbd>&lt;right&gt;</kbd>: Selecteer volgende conflict
<kbd>&lt;up&gt;</kbd>: Selecteer bovenste hunk
<kbd>&lt;down&gt;</kbd>: Selecteer onderste hunk
<kbd>z</kbd>: Ongedaan maken
<kbd>M</kbd>: Open external merge tool (git mergetool)
<kbd>&lt;space&gt;</kbd>: Kies stuk
<kbd>b</kbd>: Kies beide stukken
<kbd>&lt;esc&gt;</kbd>: Ga terug naar het bestanden paneel
</pre>
## Normaal
| Key | Action | Info |
|-----|--------|-------------|
| `` mouse wheel down (fn+up) `` | Scroll omlaag | |
| `` mouse wheel up (fn+down) `` | Scroll omhoog | |
<pre>
<kbd>mouse wheel down</kbd>: Scroll omlaag (fn+up)
<kbd>mouse wheel up</kbd>: Scroll omhoog (fn+down)
</pre>
## Patch bouwen
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | Selecteer de vorige hunk | |
| `` <right> `` | Selecteer de volgende hunk | |
| `` v `` | Toggle drag selecteer | |
| `` a `` | Toggle selecteer hunk | Toggle hunk selection mode. |
| `` <c-o> `` | Copy selected text to clipboard | |
| `` o `` | Open bestand | Open file in default application. |
| `` e `` | Verander bestand | Open file in external editor. |
| `` <space> `` | Voeg toe/verwijder lijn(en) in patch | |
| `` <esc> `` | Sluit lijn-bij-lijn modus | |
| `` / `` | Start met zoeken | |
<pre>
<kbd>&lt;left&gt;</kbd>: Selecteer de vorige hunk
<kbd>&lt;right&gt;</kbd>: Selecteer de volgende hunk
<kbd>v</kbd>: Toggle drag selecteer
<kbd>V</kbd>: Toggle drag selecteer
<kbd>a</kbd>: Toggle selecteer hunk
<kbd>&lt;c-o&gt;</kbd>: Copy the selected text to the clipboard
<kbd>o</kbd>: Open bestand
<kbd>e</kbd>: Verander bestand
<kbd>&lt;space&gt;</kbd>: Voeg toe/verwijder lijn(en) in patch
<kbd>&lt;esc&gt;</kbd>: Sluit lijn-bij-lijn modus
<kbd>/</kbd>: Start met zoeken
</pre>
## Reflog
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer commit SHA naar klembord | |
| `` <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 | |
| `` n `` | Creëer nieuwe branch van commit | |
| `` g `` | Bekijk reset opties | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | Kopieer commit (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | Reset cherry-picked (gekopieerde) commits selectie | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | Bekijk commits | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Kopieer commit SHA naar klembord
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Checkout commit
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: Open commit in browser
<kbd>n</kbd>: Creëer nieuwe branch van commit
<kbd>g</kbd>: Bekijk reset opties
<kbd>c</kbd>: Kopieer commit (cherry-pick)
<kbd>C</kbd>: Kopieer commit reeks (cherry-pick)
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (gekopieerde) commits selectie
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: Bekijk commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Remote branches
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer branch name naar klembord | |
| `` <space> `` | Uitchecken | Checkout a new local branch based on the selected remote branch, or the remote branch as a detached head. |
| `` n `` | Nieuwe branch | |
| `` M `` | Merge in met huidige checked out branch | Merge selected branch into currently checked out branch. |
| `` r `` | Rebase branch | Rebase the checked-out branch onto the selected branch. |
| `` d `` | Delete | Delete the remote branch from the remote. |
| `` u `` | Set as upstream | Stel in als upstream van uitgecheckte branch |
| `` s `` | Sort order | |
| `` g `` | Bekijk reset opties | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | Bekijk commits | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Kopieer branch name naar klembord
<kbd>&lt;space&gt;</kbd>: Uitchecken
<kbd>n</kbd>: Nieuwe branch
<kbd>M</kbd>: Merge in met huidige checked out branch
<kbd>r</kbd>: Rebase branch
<kbd>d</kbd>: Delete remote tag
<kbd>u</kbd>: Stel in als upstream van uitgecheckte branch
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: Bekijk reset opties
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: Bekijk commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Remotes
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | View branches | |
| `` n `` | Voeg een nieuwe remote toe | |
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
| `` e `` | Edit | Wijzig remote |
| `` f `` | Fetch | Fetch remote |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>f</kbd>: Fetch remote
<kbd>n</kbd>: Voeg een nieuwe remote toe
<kbd>d</kbd>: Verwijder remote
<kbd>e</kbd>: Wijzig remote
<kbd>/</kbd>: Filter the current view by text
</pre>
## Staging
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | Selecteer de vorige hunk | |
| `` <right> `` | Selecteer de volgende hunk | |
| `` v `` | Toggle drag selecteer | |
| `` a `` | Toggle selecteer hunk | Toggle hunk selection mode. |
| `` <c-o> `` | Copy selected text to clipboard | |
| `` <space> `` | Toggle staged | Toggle lijnen staged / unstaged |
| `` d `` | Verwijdert change (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
| `` o `` | Open bestand | Open file in default application. |
| `` e `` | Verander bestand | Open file in external editor. |
| `` <esc> `` | Ga terug naar het bestanden paneel | |
| `` <tab> `` | Ga naar een ander paneel | Switch to other view (staged/unstaged changes). |
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
| `` c `` | Commit veranderingen | Commit staged changes. |
| `` w `` | Commit veranderingen zonder pre-commit hook | |
| `` C `` | Commit veranderingen met de git editor | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` / `` | Start met zoeken | |
<pre>
<kbd>&lt;left&gt;</kbd>: Selecteer de vorige hunk
<kbd>&lt;right&gt;</kbd>: Selecteer de volgende hunk
<kbd>v</kbd>: Toggle drag selecteer
<kbd>V</kbd>: Toggle drag selecteer
<kbd>a</kbd>: Toggle selecteer hunk
<kbd>&lt;c-o&gt;</kbd>: Copy the selected text to the clipboard
<kbd>o</kbd>: Open bestand
<kbd>e</kbd>: Verander bestand
<kbd>&lt;esc&gt;</kbd>: Ga terug naar het bestanden paneel
<kbd>&lt;tab&gt;</kbd>: Ga naar een ander paneel
<kbd>&lt;space&gt;</kbd>: Toggle lijnen staged / unstaged
<kbd>d</kbd>: Verwijdert change (git reset)
<kbd>E</kbd>: Edit hunk
<kbd>c</kbd>: Commit veranderingen
<kbd>w</kbd>: Commit veranderingen zonder pre-commit hook
<kbd>C</kbd>: Commit veranderingen met de git editor
<kbd>/</kbd>: Start met zoeken
</pre>
## Stash
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Toepassen | Apply the stash entry to your working directory. |
| `` g `` | Pop | Apply the stash entry to your working directory and remove the stash entry. |
| `` d `` | Laten vallen | Remove the stash entry from the stash list. |
| `` n `` | Nieuwe branch | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
| `` r `` | Rename stash | |
| `` <enter> `` | Bekijk gecommite bestanden | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: Toepassen
<kbd>g</kbd>: Pop
<kbd>d</kbd>: Laten vallen
<kbd>n</kbd>: Nieuwe branch
<kbd>r</kbd>: Rename stash
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: Bekijk gecommite bestanden
<kbd>/</kbd>: Filter the current view by text
</pre>
## Status
| Key | Action | Info |
|-----|--------|-------------|
| `` o `` | Open config bestand | Open file in default application. |
| `` e `` | Verander config bestand | Open file in external editor. |
| `` u `` | Check voor updates | |
| `` <enter> `` | Wissel naar een recente repo | |
| `` a `` | Alle logs van de branch laten zien | |
<pre>
<kbd>o</kbd>: Open config bestand
<kbd>e</kbd>: Verander config bestand
<kbd>u</kbd>: Check voor updates
<kbd>&lt;enter&gt;</kbd>: Wissel naar een recente repo
<kbd>a</kbd>: Alle logs van de branch laten zien
</pre>
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer commit SHA naar klembord | |
| `` <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 | |
| `` n `` | Creëer nieuwe branch van commit | |
| `` g `` | Bekijk reset opties | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | Kopieer commit (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | Reset cherry-picked (gekopieerde) commits selectie | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | Bekijk gecommite bestanden | |
| `` w `` | View worktree options | |
| `` / `` | Start met zoeken | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Kopieer commit SHA naar klembord
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Checkout commit
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: Open commit in browser
<kbd>n</kbd>: Creëer nieuwe branch van commit
<kbd>g</kbd>: Bekijk reset opties
<kbd>c</kbd>: Kopieer commit (cherry-pick)
<kbd>C</kbd>: Kopieer commit reeks (cherry-pick)
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (gekopieerde) commits selectie
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: Bekijk gecommite bestanden
<kbd>/</kbd>: Start met zoeken
</pre>
## Submodules
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopieer submodule naam naar klembord | |
| `` <enter> `` | Enter | Enter submodule |
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
| `` u `` | Update | Update selected submodule. |
| `` n `` | Voeg nieuwe submodule toe | |
| `` e `` | Update submodule URL | |
| `` i `` | Initialize | Initialiseer submodule |
| `` b `` | Bekijk bulk submodule opties | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Kopieer submodule naam naar klembord
<kbd>&lt;enter&gt;</kbd>: Enter submodule
<kbd>&lt;space&gt;</kbd>: Enter submodule
<kbd>d</kbd>: Remove submodule
<kbd>u</kbd>: Update submodule
<kbd>n</kbd>: Voeg nieuwe submodule toe
<kbd>e</kbd>: Update submodule URL
<kbd>i</kbd>: Initialiseer submodule
<kbd>b</kbd>: Bekijk bulk submodule opties
<kbd>/</kbd>: Filter the current view by text
</pre>
## Tags
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Uitchecken | Checkout the selected tag tag as a detached HEAD. |
| `` n `` | Creëer tag | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
| `` d `` | Delete | View delete options for local/remote tag. |
| `` P `` | Push tag | Push the selected tag to a remote. You'll be prompted to select a remote. |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | Bekijk commits | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: Uitchecken
<kbd>d</kbd>: View delete options
<kbd>P</kbd>: Push tag
<kbd>n</kbd>: Creëer tag
<kbd>g</kbd>: Bekijk reset opties
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: Bekijk commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Worktrees
| Key | Action | Info |
|-----|--------|-------------|
| `` n `` | New worktree | |
| `` <space> `` | Switch | Switch to the selected worktree. |
| `` o `` | Open in editor | |
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>n</kbd>: Create worktree
<kbd>&lt;space&gt;</kbd>: Switch to worktree
<kbd>&lt;enter&gt;</kbd>: Switch to worktree
<kbd>o</kbd>: Open in editor
<kbd>d</kbd>: Remove worktree
<kbd>/</kbd>: Filter the current view by text
</pre>

View File

@@ -1,364 +1,362 @@
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go generate ./...` from the project root._
# Lazygit Skróty klawiszowe
# Lazygit Keybindings
_Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
_Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
## Globalne skróty klawiszowe
## Globalne
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-r> `` | Przełącz na ostatnie repozytorium | |
| `` <pgup> (fn+up/shift+k) `` | Przewiń główne okno w górę | |
| `` <pgdown> (fn+down/shift+j) `` | Przewiń główne okno w dół | |
| `` @ `` | Pokaż opcje dziennika poleceń | Pokaż opcje dla dziennika poleceń, np. pokazywanie/ukrywanie dziennika poleceń i skupienie na dzienniku poleceń. |
| `` P `` | Wypchnij | Wypchnij bieżącą gałąź do jej gałęzi nadrzędnej. Jeśli nie skonfigurowano gałęzi nadrzędnej, zostaniesz poproszony o skonfigurowanie gałęzi nadrzędnej. |
| `` p `` | Pociągnij | Pociągnij zmiany z zdalnego dla bieżącej gałęzi. Jeśli nie skonfigurowano gałęzi nadrzędnej, zostaniesz poproszony o skonfigurowanie gałęzi nadrzędnej. |
| `` } `` | Zwiększ rozmiar kontekstu w widoku różnic | Zwiększ ilość kontekstu pokazywanego wokół zmian w widoku różnic. |
| `` { `` | Zmniejsz rozmiar kontekstu w widoku różnic | Zmniejsz ilość kontekstu pokazywanego wokół zmian w widoku różnic. |
| `` : `` | Wykonaj polecenie niestandardowe | Wyświetl monit, w którym możesz wprowadzić polecenie powłoki do wykonania. Nie należy mylić z wcześniej skonfigurowanymi poleceniami niestandardowymi. |
| `` <c-p> `` | Wyświetl opcje niestandardowej łatki | |
| `` m `` | Pokaż opcje scalania/rebase | Pokaż opcje do przerwania/kontynuowania/pominięcia bieżącego scalania/rebase. |
| `` R `` | Odśwież | Odśwież stan git (tj. uruchom `git status`, `git branch`, itp. w tle, aby zaktualizować zawartość paneli). To nie uruchamia `git fetch`. |
| `` + `` | Następny tryb ekranu (normalny/półpełny/pełnoekranowy) | |
| `` _ `` | Poprzedni tryb ekranu | |
| `` ? `` | Otwórz menu przypisań klawiszy | |
| `` <c-s> `` | Pokaż opcje filtrowania | Pokaż opcje filtrowania dziennika commitów, tak aby pokazywane były tylko commity pasujące do filtra. |
| `` W `` | Pokaż opcje różnicowania | Pokaż opcje dotyczące różnicowania dwóch refów, np. różnicowanie względem wybranego refa, wprowadzanie refa do różnicowania i odwracanie kierunku różnic. |
| `` <c-e> `` | Pokaż opcje różnicowania | Pokaż opcje dotyczące różnicowania dwóch refów, np. różnicowanie względem wybranego refa, wprowadzanie refa do różnicowania i odwracanie kierunku różnic. |
| `` q `` | Wyjdź | |
| `` <esc> `` | Anuluj | |
| `` <c-w> `` | Przełącz białe znaki | Przełącz czy zmiany białych znaków są pokazywane w widoku różnic. |
| `` z `` | Cofnij | Dziennik reflog zostanie użyty do określenia, jakie polecenie git należy uruchomić, aby cofnąć ostatnie polecenie git. Nie obejmuje to zmian w drzewie roboczym; brane są pod uwagę tylko commity. |
| `` <c-z> `` | Ponów | Dziennik reflog zostanie użyty do określenia, jakie polecenie git należy uruchomić, aby ponowić ostatnie polecenie git. Nie obejmuje to zmian w drzewie roboczym; brane są pod uwagę tylko commity. |
<pre>
<kbd>&lt;c-r&gt;</kbd>: Switch to a recent repo
<kbd>&lt;pgup&gt;</kbd>: Scroll up main panel (fn+up/shift+k)
<kbd>&lt;pgdown&gt;</kbd>: Scroll down main panel (fn+down/shift+j)
<kbd>@</kbd>: Open command log menu
<kbd>}</kbd>: Increase the size of the context shown around changes in the diff view
<kbd>{</kbd>: Decrease the size of the context shown around changes in the diff view
<kbd>:</kbd>: Wykonaj własną komendę
<kbd>&lt;c-p&gt;</kbd>: View custom patch options
<kbd>m</kbd>: Widok scalenia/opcje zmiany bazy
<kbd>R</kbd>: Odśwież
<kbd>+</kbd>: Next screen mode (normal/half/fullscreen)
<kbd>_</kbd>: Prev screen mode
<kbd>?</kbd>: Open menu
<kbd>&lt;c-s&gt;</kbd>: View filter-by-path options
<kbd>W</kbd>: Open diff menu
<kbd>&lt;c-e&gt;</kbd>: Open diff menu
<kbd>&lt;c-w&gt;</kbd>: Toggle whether or not whitespace changes are shown in the diff view
<kbd>z</kbd>: Undo
<kbd>&lt;c-z&gt;</kbd>: Redo
<kbd>P</kbd>: Push
<kbd>p</kbd>: Pull
</pre>
## Nawigacja panelu listy
## List panel navigation
| Key | Action | Info |
|-----|--------|-------------|
| `` , `` | Poprzednia strona | |
| `` . `` | Następna strona | |
| `` < `` | Przewiń do góry | |
| `` > `` | Przewiń do dołu | |
| `` v `` | Przełącz zaznaczenie zakresu | |
| `` <s-down> `` | Zaznacz zakres w dół | |
| `` <s-up> `` | Zaznacz zakres w górę | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
| `` H `` | Przewiń w lewo | |
| `` L `` | Przewiń w prawo | |
| `` ] `` | Następna zakładka | |
| `` [ `` | Poprzednia zakładka | |
<pre>
<kbd>,</kbd>: Previous page
<kbd>.</kbd>: Next page
<kbd>&lt;</kbd>: Scroll to top
<kbd>&gt;</kbd>: Scroll to bottom
<kbd>/</kbd>: Search the current view by text
<kbd>H</kbd>: Scroll left
<kbd>L</kbd>: Scroll right
<kbd>]</kbd>: Next tab
<kbd>[</kbd>: Previous tab
</pre>
## Commit summary
<pre>
<kbd>&lt;enter&gt;</kbd>: Potwierdź
<kbd>&lt;esc&gt;</kbd>: Zamknij
</pre>
## Commity
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj SHA commita do schowka | |
| `` <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. |
| `` 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. |
| `` e `` | Edytuj (rozpocznij interaktywne rebazowanie) | Edytuj wybrany commit. Użyj tego, aby rozpocząć interaktywne rebazowanie od wybranego commita. Podczas trwania rebazowania, to oznaczy wybrany commit do edycji, co oznacza, że po kontynuacji rebazowania, rebazowanie zostanie wstrzymane na wybranym commicie, aby umożliwić wprowadzenie zmian. |
| `` i `` | Rozpocznij interaktywny rebase | Rozpocznij interaktywny rebase dla commitów na twoim branchu. To będzie zawierać wszystkie commity od HEAD do pierwszego commita scalenia lub commita głównego brancha.
Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, naciśnij `e`. |
| `` p `` | Wybierz | Oznacz wybrany commit do wybrania (podczas rebazowania). Oznacza to, że commit zostanie zachowany po kontynuacji rebazowania. |
| `` F `` | Utwórz commit fixup | Utwórz commit 'fixup!' dla wybranego commita. Później możesz nacisnąć `S` na tym samym commicie, aby zastosować wszystkie powyższe commity fixup. |
| `` S `` | Zastosuj commity fixup | Scal wszystkie commity 'fixup!', albo powyżej wybranego commita, albo wszystkie w bieżącej gałęzi (autosquash). |
| `` <c-j> `` | Przesuń commit w dół | |
| `` <c-k> `` | Przesuń commit w górę | |
| `` V `` | Wklej (cherry-pick) | |
| `` B `` | Oznacz jako bazowy commit dla rebase | Wybierz bazowy commit dla następnego rebase. Kiedy robisz rebase na branch, tylko commity powyżej bazowego commita zostaną przeniesione. Używa to polecenia `git rebase --onto`. |
| `` A `` | Popraw | Popraw commit ze zmianami zatwierdzonymi. Jeśli wybrany commit jest commit HEAD, to wykona `git commit --amend`. W przeciwnym razie commit zostanie poprawiony za pomocą rebazowania. |
| `` a `` | Popraw atrybut commita | Ustaw/Resetuj autora commita lub ustaw współautora. |
| `` t `` | Cofnij | Utwórz commit cofający dla wybranego commita, który stosuje zmiany wybranego commita w odwrotnej kolejności. |
| `` T `` | Otaguj commit | Utwórz nowy tag wskazujący na wybrany commit. Zostaniesz poproszony o wprowadzenie nazwy tagu i opcjonalnego opisu. |
| `` <c-l> `` | Zobacz opcje logów | Zobacz opcje dla logów commitów, np. zmiana kolejności sortowania, ukrywanie grafu gita, pokazywanie całego grafu gita. |
| `` <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 | |
| `` n `` | Utwórz nową gałąź z commita | |
| `` g `` | Reset | Wyświetl opcje resetu (miękki/mieszany/twardy) do wybranego elementu. |
| `` C `` | Kopiuj (cherry-pick) | Oznacz commit jako skopiowany. Następnie, w widoku lokalnych commitów, możesz nacisnąć `V`, aby wkleić (cherry-pick) skopiowane commity do sprawdzonej gałęzi. W dowolnym momencie możesz nacisnąć `<esc>`, aby anulować zaznaczenie. |
| `` <c-t> `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | |
| `` <enter> `` | Wyświetl pliki | |
| `` w `` | Zobacz opcje drzewa pracy | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy commit SHA to clipboard
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>b</kbd>: View bisect options
<kbd>s</kbd>: Ściśnij
<kbd>f</kbd>: Napraw commit
<kbd>r</kbd>: Zmień nazwę commita
<kbd>R</kbd>: Zmień nazwę commita w edytorze
<kbd>d</kbd>: Usuń commit
<kbd>e</kbd>: Edytuj commit
<kbd>p</kbd>: Wybierz commit (podczas zmiany bazy)
<kbd>F</kbd>: Utwórz commit naprawczy dla tego commita
<kbd>S</kbd>: Spłaszcz wszystkie commity naprawcze powyżej zaznaczonych commitów (autosquash)
<kbd>&lt;c-j&gt;</kbd>: Przenieś commit 1 w dół
<kbd>&lt;c-k&gt;</kbd>: Przenieś commit 1 w górę
<kbd>v</kbd>: Wklej commity (przebieranie)
<kbd>B</kbd>: Mark commit as base commit for rebase
<kbd>A</kbd>: Popraw commit zmianami z poczekalni
<kbd>a</kbd>: Set/Reset commit author
<kbd>t</kbd>: Odwróć commit
<kbd>T</kbd>: Tag commit
<kbd>&lt;c-l&gt;</kbd>: Open log menu
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Checkout commit
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: Open commit in browser
<kbd>n</kbd>: Create new branch off of commit
<kbd>g</kbd>: Wyświetl opcje resetu
<kbd>c</kbd>: Kopiuj commit (przebieranie)
<kbd>C</kbd>: Kopiuj zakres commitów (przebieranie)
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: Przeglądaj pliki commita
<kbd>/</kbd>: Search the current view by text
</pre>
## Drzewa pracy
## Confirmation panel
| Key | Action | Info |
|-----|--------|-------------|
| `` n `` | Nowe drzewo pracy | |
| `` <space> `` | Przełącz | Przełącz do wybranego drzewa pracy. |
| `` o `` | Otwórz w edytorze | |
| `` d `` | Usuń | Usuń wybrane drzewo pracy. To usunie zarówno katalog drzewa pracy, jak i metadane o drzewie pracy w katalogu .git. |
| `` / `` | Filtruj bieżący widok po tekście | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Potwierdź
<kbd>&lt;esc&gt;</kbd>: Zamknij
</pre>
## Główny panel (budowanie łatki)
## Local branches
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | Idź do poprzedniego fragmentu | |
| `` <right> `` | Idź do następnego fragmentu | |
| `` v `` | Przełącz zaznaczenie zakresu | |
| `` a `` | Zaznacz fragment | Przełącz tryb zaznaczania fragmentu. |
| `` <c-o> `` | Kopiuj zaznaczony tekst do schowka | |
| `` 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 | |
| `` <esc> `` | Wyjdź z budowniczego niestandardowej łatki | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy branch name to clipboard
<kbd>i</kbd>: Show git-flow options
<kbd>&lt;space&gt;</kbd>: Przełącz
<kbd>n</kbd>: Nowa gałąź
<kbd>o</kbd>: Utwórz żądanie pobrania
<kbd>O</kbd>: Utwórz opcje żądania ściągnięcia
<kbd>&lt;c-y&gt;</kbd>: Skopiuj adres URL żądania pobrania do schowka
<kbd>c</kbd>: Przełącz używając nazwy
<kbd>F</kbd>: Wymuś przełączenie
<kbd>d</kbd>: View delete options
<kbd>r</kbd>: Zmiana bazy gałęzi
<kbd>M</kbd>: Scal do obecnej gałęzi
<kbd>f</kbd>: Fast-forward this branch from its upstream
<kbd>T</kbd>: Create tag
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: Wyświetl opcje resetu
<kbd>R</kbd>: Rename branch
<kbd>u</kbd>: View upstream options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: View commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Lokalne gałęzie
## Main panel (patch building)
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj nazwę gałęzi do schowka | |
| `` i `` | Pokaż opcje git-flow | |
| `` <space> `` | Przełącz | Przełącz wybrany element. |
| `` n `` | Nowa gałąź | |
| `` o `` | Utwórz żądanie ściągnięcia | |
| `` O `` | Zobacz opcje tworzenia pull requesta | |
| `` <c-y> `` | Kopiuj adres URL żądania ściągnięcia do schowka | |
| `` c `` | Przełącz według nazwy | Przełącz według nazwy. W polu wprowadzania możesz wpisać '-' aby przełączyć się na ostatnią gałąź. |
| `` F `` | Wymuś przełączenie | Wymuś przełączenie wybranej gałęzi. To spowoduje odrzucenie wszystkich lokalnych zmian w drzewie roboczym przed przełączeniem na wybraną gałąź. |
| `` d `` | Usuń | Wyświetl opcje usuwania lokalnej/odległej gałęzi. |
| `` r `` | Przebazuj | Przebazuj przełączoną gałąź na wybraną gałąź. |
| `` M `` | Scal | Scal wybraną gałąź z aktualnie sprawdzoną gałęzią. |
| `` f `` | Szybkie przewijanie | Szybkie przewijanie wybranej gałęzi z jej źródła. |
| `` T `` | Nowy tag | |
| `` s `` | Kolejność sortowania | |
| `` g `` | Reset | |
| `` R `` | Zmień nazwę gałęzi | |
| `` u `` | Pokaż opcje upstream | Pokaż opcje dotyczące upstream gałęzi, np. ustawianie/usuwanie upstream i resetowanie do upstream. |
| `` <enter> `` | Pokaż commity | |
| `` w `` | Zobacz opcje drzewa pracy | |
| `` / `` | Filtruj bieżący widok po tekście | |
<pre>
<kbd>&lt;left&gt;</kbd>: Poprzedni kawałek
<kbd>&lt;right&gt;</kbd>: Następny kawałek
<kbd>v</kbd>: Toggle drag select
<kbd>V</kbd>: Toggle drag select
<kbd>a</kbd>: Toggle select hunk
<kbd>&lt;c-o&gt;</kbd>: Copy the selected text to the clipboard
<kbd>o</kbd>: Otwórz plik
<kbd>e</kbd>: Edytuj plik
<kbd>&lt;space&gt;</kbd>: Add/Remove line(s) to patch
<kbd>&lt;esc&gt;</kbd>: Wyście z trybu "linia po linii"
<kbd>/</kbd>: Search the current view by text
</pre>
## Menu
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Wykonaj | |
| `` <esc> `` | Zamknij | |
| `` / `` | Filtruj bieżący widok po tekście | |
## Panel główny (normalny)
| Key | Action | Info |
|-----|--------|-------------|
| `` mouse wheel down (fn+up) `` | Przewiń w dół | |
| `` mouse wheel up (fn+down) `` | Przewiń w górę | |
## Panel główny (scalanie)
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Wybierz fragment | |
| `` b `` | Wybierz wszystkie fragmenty | |
| `` <up> `` | Poprzedni fragment | |
| `` <down> `` | Następny fragment | |
| `` <left> `` | Poprzedni konflikt | |
| `` <right> `` | Następny konflikt | |
| `` z `` | Cofnij | Cofnij ostatnie rozwiązanie konfliktu scalania. |
| `` e `` | Edytuj plik | Otwórz plik w zewnętrznym edytorze. |
| `` o `` | Otwórz plik | Otwórz plik w domyślnej aplikacji. |
| `` M `` | Otwórz zewnętrzne narzędzie scalania | Uruchom `git mergetool`. |
| `` <esc> `` | Wróć do panelu plików | |
## Panel główny (zatwierdzanie)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | Idź do poprzedniego fragmentu | |
| `` <right> `` | Idź do następnego fragmentu | |
| `` v `` | Przełącz zaznaczenie zakresu | |
| `` a `` | Zaznacz fragment | Przełącz tryb zaznaczania fragmentu. |
| `` <c-o> `` | Kopiuj zaznaczony tekst do schowka | |
| `` <space> `` | Zatwierdź | Przełącz zaznaczenie zatwierdzone/niezatwierdzone. |
| `` d `` | Odrzuć | Gdy zaznaczona jest niezatwierdzona zmiana, odrzuć ją używając `git reset`. Gdy zaznaczona jest zatwierdzona zmiana, cofnij zatwierdzenie. |
| `` o `` | Otwórz plik | Otwórz plik w domyślnej aplikacji. |
| `` e `` | Edytuj plik | Otwórz plik w zewnętrznym edytorze. |
| `` <esc> `` | Wróć do panelu plików | |
| `` <tab> `` | Przełącz widok | Przełącz na inny widok (zatwierdzone/niezatwierdzone zmiany). |
| `` E `` | Edytuj fragment | Edytuj wybrany fragment w zewnętrznym edytorze. |
| `` c `` | Commit | Zatwierdź zmiany zatwierdzone. |
| `` w `` | Zatwierdź zmiany bez hooka pre-commit | |
| `` C `` | Zatwierdź zmiany używając edytora git | |
| `` <c-f> `` | Znajdź bazowy commit do poprawki | Znajdź commit, na którym opierają się Twoje obecne zmiany, w celu poprawienia/zmiany commita. To pozwala Ci uniknąć przeglądania commitów w Twojej gałęzi jeden po drugim, aby zobaczyć, który commit powinien być poprawiony/zmieniony. Zobacz dokumentację: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
## Panel potwierdzenia
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Potwierdź | |
| `` <esc> `` | Zamknij/Anuluj | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Wykonaj
<kbd>&lt;esc&gt;</kbd>: Zamknij
<kbd>/</kbd>: Filter the current view by text
</pre>
## Pliki
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj ścieżkę do schowka | |
| `` <space> `` | Zatwierdź | Przełącz zatwierdzenie dla wybranego pliku. |
| `` <c-b> `` | Filtruj pliki według statusu | |
| `` y `` | Kopiuj do schowka | |
| `` c `` | Commit | Zatwierdź zmiany zatwierdzone. |
| `` w `` | Zatwierdź zmiany bez hooka pre-commit | |
| `` A `` | Popraw ostatni commit | |
| `` C `` | Zatwierdź zmiany używając edytora git | |
| `` <c-f> `` | Znajdź bazowy commit do poprawki | Znajdź commit, na którym opierają się Twoje obecne zmiany, w celu poprawienia/zmiany commita. To pozwala Ci uniknąć przeglądania commitów w Twojej gałęzi jeden po drugim, aby zobaczyć, który commit powinien być poprawiony/zmieniony. Zobacz dokumentację: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` e `` | Edytuj | Otwórz plik w zewnętrznym edytorze. |
| `` o `` | Otwórz plik | Otwórz plik w domyślnej aplikacji. |
| `` i `` | Ignoruj lub wyklucz plik | |
| `` r `` | Odśwież pliki | |
| `` s `` | Schowaj | Schowaj wszystkie zmiany. Dla innych wariantów schowania, użyj klawisza wyświetlania opcji schowka. |
| `` S `` | Wyświetl opcje schowka | Wyświetl opcje schowka (np. schowaj wszystko, schowaj zatwierdzone, schowaj niezatwierdzone). |
| `` a `` | Zatwierdź wszystko | Przełącz zatwierdzenie/odznaczenie dla wszystkich plików w drzewie roboczym. |
| `` <enter> `` | Zatwierdź linie / Zwiń katalog | Jeśli wybrany element jest plikiem, skup się na widoku zatwierdzania, aby móc zatwierdzać poszczególne fragmenty/linie. Jeśli wybrany element jest katalogiem, zwiń/rozwiń go. |
| `` d `` | Odrzuć | Wyświetl opcje odrzucania zmian w wybranym pliku. |
| `` g `` | Pokaż opcje resetowania do upstream | |
| `` D `` | Reset | Wyświetl opcje resetu dla drzewa roboczego (np. zniszczenie drzewa roboczego). |
| `` ` `` | Przełącz widok drzewa plików | Przełącz widok plików między płaskim a drzewem. Płaski układ pokazuje wszystkie ścieżki plików na jednej liście, układ drzewa grupuje pliki według katalogów. |
| `` <c-t> `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | |
| `` M `` | Otwórz zewnętrzne narzędzie scalania | Uruchom `git mergetool`. |
| `` f `` | Pobierz | Pobierz zmiany ze zdalnego serwera. |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy the file name to the clipboard
<kbd>d</kbd>: Pokaż opcje porzucania zmian
<kbd>&lt;space&gt;</kbd>: Przełącz stan poczekalni
<kbd>&lt;c-b&gt;</kbd>: Filter files by status
<kbd>y</kbd>: Copy to clipboard
<kbd>c</kbd>: Zatwierdź zmiany
<kbd>w</kbd>: Zatwierdź zmiany bez skryptu pre-commit
<kbd>A</kbd>: Zmień ostatni commit
<kbd>C</kbd>: Zatwierdź zmiany używając edytora
<kbd>&lt;c-f&gt;</kbd>: Find base commit for fixup
<kbd>e</kbd>: Edytuj plik
<kbd>o</kbd>: Otwórz plik
<kbd>i</kbd>: Ignore or exclude file
<kbd>r</kbd>: Odśwież pliki
<kbd>s</kbd>: Przechowaj zmiany
<kbd>S</kbd>: Wyświetl opcje schowka
<kbd>a</kbd>: Przełącz stan poczekalni wszystkich
<kbd>&lt;enter&gt;</kbd>: Zatwierdź pojedyncze linie
<kbd>g</kbd>: View upstream reset options
<kbd>D</kbd>: Wyświetl opcje resetu
<kbd>`</kbd>: Toggle file tree view
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>M</kbd>: Open external merge tool (git mergetool)
<kbd>f</kbd>: Pobierz
<kbd>/</kbd>: Search the current view by text
</pre>
## Pliki commita
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj ścieżkę 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. |
| `` 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) | |
| `` <space> `` | Przełącz plik włączony w łatkę | Przełącz, czy plik jest włączony w niestandardową łatkę. Zobacz https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` a `` | Przełącz wszystkie pliki | Dodaj/usuń wszystkie pliki commita do niestandardowej łatki. Zobacz https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` <enter> `` | Wejdź do pliku / Przełącz zwiń katalog | Jeśli plik jest wybrany, wejdź do pliku, aby móc dodawać/usuwać poszczególne linie do niestandardowej łatki. Jeśli wybrany jest katalog, przełącz katalog. |
| `` ` `` | Przełącz widok drzewa plików | Przełącz widok plików między płaskim a drzewem. Płaski układ pokazuje wszystkie ścieżki plików na jednej liście, układ drzewa grupuje pliki według katalogów. |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy the committed file name to the clipboard
<kbd>c</kbd>: Plik wybierania
<kbd>d</kbd>: Porzuć zmiany commita dla tego pliku
<kbd>o</kbd>: Otwórz plik
<kbd>e</kbd>: Edytuj plik
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;space&gt;</kbd>: Toggle file included in patch
<kbd>a</kbd>: Toggle all files included in patch
<kbd>&lt;enter&gt;</kbd>: Enter file to add selected lines to the patch (or toggle directory collapsed)
<kbd>`</kbd>: Toggle file tree view
<kbd>/</kbd>: Search the current view by text
</pre>
## Podsumowanie commita
## Poczekalnia
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Potwierdź | |
| `` <esc> `` | Zamknij | |
<pre>
<kbd>&lt;left&gt;</kbd>: Poprzedni kawałek
<kbd>&lt;right&gt;</kbd>: Następny kawałek
<kbd>v</kbd>: Toggle drag select
<kbd>V</kbd>: Toggle drag select
<kbd>a</kbd>: Toggle select hunk
<kbd>&lt;c-o&gt;</kbd>: Copy the selected text to the clipboard
<kbd>o</kbd>: Otwórz plik
<kbd>e</kbd>: Edytuj plik
<kbd>&lt;esc&gt;</kbd>: Wróć do panelu plików
<kbd>&lt;tab&gt;</kbd>: Switch to other panel (staged/unstaged changes)
<kbd>&lt;space&gt;</kbd>: Toggle line staged / unstaged
<kbd>d</kbd>: Discard change (git reset)
<kbd>E</kbd>: Edit hunk
<kbd>c</kbd>: Zatwierdź zmiany
<kbd>w</kbd>: Zatwierdź zmiany bez skryptu pre-commit
<kbd>C</kbd>: Zatwierdź zmiany używając edytora
<kbd>/</kbd>: Search the current view by text
</pre>
## Reflog
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj SHA commita do schowka | |
| `` <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 | |
| `` n `` | Utwórz nową gałąź z commita | |
| `` g `` | Reset | Wyświetl opcje resetu (miękki/mieszany/twardy) do wybranego elementu. |
| `` C `` | Kopiuj (cherry-pick) | Oznacz commit jako skopiowany. Następnie, w widoku lokalnych commitów, możesz nacisnąć `V`, aby wkleić (cherry-pick) skopiowane commity do sprawdzonej gałęzi. W dowolnym momencie możesz nacisnąć `<esc>`, aby anulować zaznaczenie. |
| `` <c-r> `` | Resetuj wybrane (cherry-picked) commity | |
| `` <c-t> `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | |
| `` <enter> `` | Pokaż commity | |
| `` w `` | Zobacz opcje drzewa pracy | |
| `` / `` | Filtruj bieżący widok po tekście | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy commit SHA to clipboard
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Checkout commit
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: Open commit in browser
<kbd>n</kbd>: Create new branch off of commit
<kbd>g</kbd>: Wyświetl opcje resetu
<kbd>c</kbd>: Kopiuj commit (przebieranie)
<kbd>C</kbd>: Kopiuj zakres commitów (przebieranie)
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: View commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Remote branches
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy branch name to clipboard
<kbd>&lt;space&gt;</kbd>: Przełącz
<kbd>n</kbd>: Nowa gałąź
<kbd>M</kbd>: Scal do obecnej gałęzi
<kbd>r</kbd>: Zmiana bazy gałęzi
<kbd>d</kbd>: Delete remote tag
<kbd>u</kbd>: Set as upstream of checked-out branch
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: Wyświetl opcje resetu
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: View commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Remotes
<pre>
<kbd>f</kbd>: Fetch remote
<kbd>n</kbd>: Add new remote
<kbd>d</kbd>: Remove remote
<kbd>e</kbd>: Edit remote
<kbd>/</kbd>: Filter the current view by text
</pre>
## Scalanie
<pre>
<kbd>e</kbd>: Edytuj plik
<kbd>o</kbd>: Otwórz plik
<kbd>&lt;left&gt;</kbd>: Poprzedni konflikt
<kbd>&lt;right&gt;</kbd>: Następny konflikt
<kbd>&lt;up&gt;</kbd>: Wybierz poprzedni kawałek
<kbd>&lt;down&gt;</kbd>: Wybierz następny kawałek
<kbd>z</kbd>: Cofnij
<kbd>M</kbd>: Open external merge tool (git mergetool)
<kbd>&lt;space&gt;</kbd>: Wybierz kawałek
<kbd>b</kbd>: Wybierz oba kawałki
<kbd>&lt;esc&gt;</kbd>: Wróć do panelu plików
</pre>
## Schowek
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Zastosuj | Zastosuj wpis schowka do katalogu roboczego. |
| `` g `` | Wyciągnij | Zastosuj wpis schowka do katalogu roboczego i usuń wpis schowka. |
| `` d `` | Usuń | Usuń wpis schowka z listy schowka. |
| `` n `` | Nowa gałąź | Utwórz nową gałąź z wybranego wpisu schowka. Działa poprzez przełączenie git na commit, na którym wpis schowka został utworzony, tworzenie nowej gałęzi z tego commita, a następnie zastosowanie wpisu schowka do nowej gałęzi jako dodatkowego commita. |
| `` r `` | Zmień nazwę schowka | |
| `` <enter> `` | Wyświetl pliki | |
| `` w `` | Zobacz opcje drzewa pracy | |
| `` / `` | Filtruj bieżący widok po tekście | |
<pre>
<kbd>&lt;space&gt;</kbd>: Zastosuj
<kbd>g</kbd>: Wyciągnij
<kbd>d</kbd>: Porzuć
<kbd>n</kbd>: Nowa gałąź
<kbd>r</kbd>: Rename stash
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: Przeglądaj pliki commita
<kbd>/</kbd>: Filter the current view by text
</pre>
## Status
| Key | Action | Info |
|-----|--------|-------------|
| `` o `` | Otwórz plik konfiguracyjny | Otwórz plik w domyślnej aplikacji. |
| `` e `` | Edytuj plik konfiguracyjny | Otwórz plik w zewnętrznym edytorze. |
| `` u `` | Sprawdź aktualizacje | |
| `` <enter> `` | Przełącz na ostatnie repozytorium | |
| `` a `` | Pokaż wszystkie gałęzie w logach | |
<pre>
<kbd>o</kbd>: Otwórz konfigurację
<kbd>e</kbd>: Edytuj konfigurację
<kbd>u</kbd>: Sprawdź aktualizacje
<kbd>&lt;enter&gt;</kbd>: Switch to a recent repo
<kbd>a</kbd>: Pokaż wszystkie logi gałęzi
</pre>
## Sub-commity
## Sub-commits
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj SHA commita do schowka | |
| `` <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 | |
| `` n `` | Utwórz nową gałąź z commita | |
| `` g `` | Reset | Wyświetl opcje resetu (miękki/mieszany/twardy) do wybranego elementu. |
| `` C `` | Kopiuj (cherry-pick) | Oznacz commit jako skopiowany. Następnie, w widoku lokalnych commitów, możesz nacisnąć `V`, aby wkleić (cherry-pick) skopiowane commity do sprawdzonej gałęzi. W dowolnym momencie możesz nacisnąć `<esc>`, aby anulować zaznaczenie. |
| `` <c-r> `` | Resetuj wybrane (cherry-picked) commity | |
| `` <c-t> `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | |
| `` <enter> `` | Wyświetl pliki | |
| `` w `` | Zobacz opcje drzewa pracy | |
| `` / `` | Szukaj w bieżącym widoku po tekście | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy commit SHA to clipboard
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Checkout commit
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: Open commit in browser
<kbd>n</kbd>: Create new branch off of commit
<kbd>g</kbd>: Wyświetl opcje resetu
<kbd>c</kbd>: Kopiuj commit (przebieranie)
<kbd>C</kbd>: Kopiuj zakres commitów (przebieranie)
<kbd>&lt;c-r&gt;</kbd>: Reset cherry-picked (copied) commits selection
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: Przeglądaj pliki commita
<kbd>/</kbd>: Search the current view by text
</pre>
## Submoduły
## Submodules
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj nazwę submodułu do schowka | |
| `` <enter> `` | Wejdź | Wejdź do submodułu. Po wejściu do submodułu możesz nacisnąć `<esc>`, aby wrócić do repozytorium nadrzędnego. |
| `` d `` | Usuń | Usuń wybrany submoduł i odpowiadający mu katalog. |
| `` u `` | Aktualizuj | Aktualizuj wybrany submoduł. |
| `` n `` | Nowy submoduł | |
| `` e `` | Zaktualizuj URL submodułu | |
| `` i `` | Zainicjuj | Zainicjuj wybrany submoduł, aby przygotować do pobrania. Prawdopodobnie chcesz to kontynuować, wywołując akcję 'update', aby pobrać submoduł. |
| `` b `` | Pokaż opcje masowych operacji na submodułach | |
| `` / `` | Filtruj bieżący widok po tekście | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Copy submodule name to clipboard
<kbd>&lt;enter&gt;</kbd>: Enter submodule
<kbd>&lt;space&gt;</kbd>: Enter submodule
<kbd>d</kbd>: Remove submodule
<kbd>u</kbd>: Update submodule
<kbd>n</kbd>: Add new submodule
<kbd>e</kbd>: Update submodule URL
<kbd>i</kbd>: Initialize submodule
<kbd>b</kbd>: View bulk submodule options
<kbd>/</kbd>: Filter the current view by text
</pre>
## Tagi
## Tags
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Przełącz | Przełącz wybrany tag jako odłączoną głowę (detached HEAD). |
| `` n `` | Nowy tag | Utwórz nowy tag z bieżącego commita. Zostaniesz poproszony o wprowadzenie nazwy tagu i opcjonalnego opisu. |
| `` d `` | Usuń | Wyświetl opcje usuwania lokalnego/odległego tagu. |
| `` P `` | Wyślij tag | Wyślij wybrany tag do zdalnego. Zostaniesz poproszony o wybranie zdalnego. |
| `` g `` | Reset | Wyświetl opcje resetu (miękki/mieszany/twardy) do wybranego elementu. |
| `` <enter> `` | Pokaż commity | |
| `` w `` | Zobacz opcje drzewa pracy | |
| `` / `` | Filtruj bieżący widok po tekście | |
<pre>
<kbd>&lt;space&gt;</kbd>: Przełącz
<kbd>d</kbd>: View delete options
<kbd>P</kbd>: Push tag
<kbd>n</kbd>: Create tag
<kbd>g</kbd>: Wyświetl opcje resetu
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: View commits
<kbd>/</kbd>: Filter the current view by text
</pre>
## Zdalne
## Worktrees
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Wyświetl gałęzie | |
| `` n `` | Nowy zdalny | |
| `` d `` | Usuń | Usuń wybrany zdalny. Wszelkie lokalne gałęzie śledzące gałąź zdalną z tego zdalnego nie zostaną dotknięte. |
| `` e `` | Edytuj | Edytuj nazwę lub URL wybranego zdalnego. |
| `` f `` | Pobierz | Pobierz aktualizacje z zdalnego repozytorium. Pobiera nowe commity i gałęzie bez scalania ich z lokalnymi gałęziami. |
| `` / `` | Filtruj bieżący widok po tekście | |
<pre>
<kbd>n</kbd>: Create worktree
<kbd>&lt;space&gt;</kbd>: Switch to worktree
<kbd>&lt;enter&gt;</kbd>: Switch to worktree
<kbd>o</kbd>: Open in editor
<kbd>d</kbd>: Remove worktree
<kbd>/</kbd>: Filter the current view by text
</pre>
## Zdalne gałęzie
## Zwykłe
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Kopiuj nazwę gałęzi do schowka | |
| `` <space> `` | Przełącz | Przełącz na nową lokalną gałąź na podstawie wybranej gałęzi zdalnej. Nowa gałąź będzie śledzić gałąź zdalną. |
| `` n `` | Nowa gałąź | |
| `` M `` | Scal | Scal wybraną gałąź z aktualnie sprawdzoną gałęzią. |
| `` r `` | Przebazuj | Przebazuj przełączoną gałąź na wybraną gałąź. |
| `` d `` | Usuń | Usuń gałąź zdalną ze zdalnego. |
| `` u `` | Ustaw jako upstream | Ustaw wybraną gałąź zdalną jako upstream sprawdzonej gałęzi. |
| `` s `` | Kolejność sortowania | |
| `` g `` | Reset | Wyświetl opcje resetu (miękki/mieszany/twardy) do wybranego elementu. |
| `` <enter> `` | Pokaż commity | |
| `` w `` | Zobacz opcje drzewa pracy | |
| `` / `` | Filtruj bieżący widok po tekście | |
<pre>
<kbd>mouse wheel down</kbd>: Przewiń w dół (fn+up)
<kbd>mouse wheel up</kbd>: Przewiń w górę (fn+down)
</pre>

View File

@@ -6,359 +6,357 @@ _Связки клавиш_
## Глобальные сочетания клавиш
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-r> `` | Переключиться на последний репозиторий | |
| `` <pgup> (fn+up/shift+k) `` | Прокрутить вверх главную панель | |
| `` <pgdown> (fn+down/shift+j) `` | Прокрутить вниз главную панель | |
| `` @ `` | Открыть меню журнала команд | View options for the command log e.g. show/hide the command log and focus the command log. |
| `` P `` | Отправить изменения | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` p `` | Получить и слить изменения | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` } `` | Увеличить размер контекста, отображаемого вокруг изменений в просмотрщике сравнении | Increase the amount of the context shown around changes in the diff view. |
| `` { `` | Уменьшите размер контекста, отображаемого вокруг изменений в просмотрщике сравнении | Decrease the amount of the context shown around changes in the diff view. |
| `` : `` | Выполнить пользовательскую команду | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
| `` <c-p> `` | Просмотреть пользовательские параметры патча | |
| `` m `` | Просмотреть параметры слияния/перебазирования | View options to abort/continue/skip the current merge/rebase. |
| `` R `` | Обновить | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
| `` + `` | Следующий режим экрана (нормальный/полуэкранный/полноэкранный) | |
| `` _ `` | Предыдущий режим экрана | |
| `` ? `` | Открыть меню | |
| `` <c-s> `` | Просмотреть параметры фильтрации по пути | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | Открыть меню сравнении | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | Открыть меню сравнении | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | Выйти | |
| `` <esc> `` | Отменить | |
| `` <c-w> `` | Переключить отображение изменении пробелов в просмотрщике сравнении | Toggle whether or not whitespace changes are shown in the diff view. |
| `` z `` | Отменить (через reflog) (экспериментальный) | Журнал ссылок (reflog) будет использоваться для определения того, какую команду git запустить, чтобы отменить последнюю команду git. Сюда не входят изменения в рабочем дереве; учитываются только коммиты. |
| `` <c-z> `` | Повторить (через reflog) (экспериментальный) | Журнал ссылок (reflog) будет использоваться для определения того, какую команду git нужно запустить, чтобы повторить последнюю команду git. Сюда не входят изменения в рабочем дереве; учитываются только коммиты. |
<pre>
<kbd>&lt;c-r&gt;</kbd>: Переключиться на последний репозиторий
<kbd>&lt;pgup&gt;</kbd>: Прокрутить вверх главную панель (fn+up/shift+k)
<kbd>&lt;pgdown&gt;</kbd>: Прокрутить вниз главную панель (fn+down/shift+j)
<kbd>@</kbd>: Открыть меню журнала команд
<kbd>}</kbd>: Увеличить размер контекста, отображаемого вокруг изменений в просмотрщике сравнении
<kbd>{</kbd>: Уменьшите размер контекста, отображаемого вокруг изменений в просмотрщике сравнении
<kbd>:</kbd>: Выполнить пользовательскую команду
<kbd>&lt;c-p&gt;</kbd>: Просмотреть пользовательские параметры патча
<kbd>m</kbd>: Просмотреть параметры слияния/перебазирования
<kbd>R</kbd>: Обновить
<kbd>+</kbd>: Следующий режим экрана (нормальный/полуэкранный/полноэкранный)
<kbd>_</kbd>: Предыдущий режим экрана
<kbd>?</kbd>: Открыть меню
<kbd>&lt;c-s&gt;</kbd>: Просмотреть параметры фильтрации по пути
<kbd>W</kbd>: Открыть меню сравнении
<kbd>&lt;c-e&gt;</kbd>: Открыть меню сравнении
<kbd>&lt;c-w&gt;</kbd>: Переключить отображение изменении пробелов в просмотрщике сравнении
<kbd>z</kbd>: Отменить (через reflog) (экспериментальный)
<kbd>&lt;c-z&gt;</kbd>: Повторить (через reflog) (экспериментальный)
<kbd>P</kbd>: Отправить изменения
<kbd>p</kbd>: Получить и слить изменения
</pre>
## Навигация по панели списка
| Key | Action | Info |
|-----|--------|-------------|
| `` , `` | Предыдущая страница | |
| `` . `` | Следующая страница | |
| `` < `` | Пролистать наверх | |
| `` > `` | Прокрутить вниз | |
| `` v `` | Переключить выборку перетаскивания | |
| `` <s-down> `` | Range select down | |
| `` <s-up> `` | Range select up | |
| `` / `` | Найти | |
| `` H `` | Прокрутить влево | |
| `` L `` | Прокрутить вправо | |
| `` ] `` | Следующая вкладка | |
| `` [ `` | Предыдущая вкладка | |
<pre>
<kbd>,</kbd>: Предыдущая страница
<kbd>.</kbd>: Следующая страница
<kbd>&lt;</kbd>: Пролистать наверх
<kbd>&gt;</kbd>: Прокрутить вниз
<kbd>/</kbd>: Найти
<kbd>H</kbd>: Прокрутить влево
<kbd>L</kbd>: Прокрутить вправо
<kbd>]</kbd>: Следующая вкладка
<kbd>[</kbd>: Предыдущая вкладка
</pre>
## Worktrees
| Key | Action | Info |
|-----|--------|-------------|
| `` n `` | New worktree | |
| `` <space> `` | Switch | Switch to the selected worktree. |
| `` o `` | Open in editor | |
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>n</kbd>: Create worktree
<kbd>&lt;space&gt;</kbd>: Switch to worktree
<kbd>&lt;enter&gt;</kbd>: Switch to worktree
<kbd>o</kbd>: Open in editor
<kbd>d</kbd>: Remove worktree
<kbd>/</kbd>: Filter the current view by text
</pre>
## Главная панель (Индексирование)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | Выбрать предыдущую часть | |
| `` <right> `` | Выбрать следующую часть | |
| `` v `` | Переключить выборку перетаскивания | |
| `` a `` | Переключить выборку частей | Toggle hunk selection mode. |
| `` <c-o> `` | Скопировать выделенный текст в буфер обмена | |
| `` <space> `` | Переключить индекс | Переключить строку в проиндексированные / непроиндексированные |
| `` d `` | Отменить изменение (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
| `` o `` | Открыть файл | Open file in default application. |
| `` e `` | Редактировать файл | Open file in external editor. |
| `` <esc> `` | Вернуться к панели файлов | |
| `` <tab> `` | Переключиться на другую панель (проиндексированные/непроиндексированные изменения) | Switch to other view (staged/unstaged changes). |
| `` E `` | Изменить эту часть | Edit selected hunk in external editor. |
| `` c `` | Сохранить изменения | Commit staged changes. |
| `` w `` | Закоммитить изменения без предварительного хука коммита | |
| `` C `` | Сохранить изменения с помощью редактора git | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` / `` | Найти | |
<pre>
<kbd>&lt;left&gt;</kbd>: Выбрать предыдущую часть
<kbd>&lt;right&gt;</kbd>: Выбрать следующую часть
<kbd>v</kbd>: Переключить выборку перетаскивания
<kbd>V</kbd>: Переключить выборку перетаскивания
<kbd>a</kbd>: Переключить выборку частей
<kbd>&lt;c-o&gt;</kbd>: Скопировать выделенный текст в буфер обмена
<kbd>o</kbd>: Открыть файл
<kbd>e</kbd>: Редактировать файл
<kbd>&lt;esc&gt;</kbd>: Вернуться к панели файлов
<kbd>&lt;tab&gt;</kbd>: Переключиться на другую панель (проиндексированные/непроиндексированные изменения)
<kbd>&lt;space&gt;</kbd>: Переключить строку в проиндексированные / непроиндексированные
<kbd>d</kbd>: Отменить изменение (git reset)
<kbd>E</kbd>: Изменить эту часть
<kbd>c</kbd>: Сохранить изменения
<kbd>w</kbd>: Закоммитить изменения без предварительного хука коммита
<kbd>C</kbd>: Сохранить изменения с помощью редактора git
<kbd>/</kbd>: Найти
</pre>
## Главная панель (Обычный)
| Key | Action | Info |
|-----|--------|-------------|
| `` mouse wheel down (fn+up) `` | Прокрутить вниз | |
| `` mouse wheel up (fn+down) `` | Прокрутить вверх | |
<pre>
<kbd>mouse wheel down</kbd>: Прокрутить вниз (fn+up)
<kbd>mouse wheel up</kbd>: Прокрутить вверх (fn+down)
</pre>
## Главная панель (Слияние)
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Выбрать эту часть | |
| `` b `` | Выбрать все части | |
| `` <up> `` | Выбрать предыдущую часть | |
| `` <down> `` | Выбрать следующую часть | |
| `` <left> `` | Выбрать предыдущий конфликт | |
| `` <right> `` | Выбрать следующий конфликт | |
| `` z `` | Отменить | Undo last merge conflict resolution. |
| `` e `` | Редактировать файл | Open file in external editor. |
| `` o `` | Открыть файл | Open file in default application. |
| `` M `` | Открыть внешний инструмент слияния (git mergetool) | Run `git mergetool`. |
| `` <esc> `` | Вернуться к панели файлов | |
<pre>
<kbd>e</kbd>: Редактировать файл
<kbd>o</kbd>: Открыть файл
<kbd>&lt;left&gt;</kbd>: Выбрать предыдущий конфликт
<kbd>&lt;right&gt;</kbd>: Выбрать следующий конфликт
<kbd>&lt;up&gt;</kbd>: Выбрать предыдущую часть
<kbd>&lt;down&gt;</kbd>: Выбрать следующую часть
<kbd>z</kbd>: Отменить
<kbd>M</kbd>: Открыть внешний инструмент слияния (git mergetool)
<kbd>&lt;space&gt;</kbd>: Выбрать эту часть
<kbd>b</kbd>: Выбрать все части
<kbd>&lt;esc&gt;</kbd>: Вернуться к панели файлов
</pre>
## Главная панель (сборка патчей)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | Выбрать предыдущую часть | |
| `` <right> `` | Выбрать следующую часть | |
| `` v `` | Переключить выборку перетаскивания | |
| `` a `` | Переключить выборку частей | Toggle hunk selection mode. |
| `` <c-o> `` | Скопировать выделенный текст в буфер обмена | |
| `` o `` | Открыть файл | Open file in default application. |
| `` e `` | Редактировать файл | Open file in external editor. |
| `` <space> `` | Добавить/удалить строку(и) для патча | |
| `` <esc> `` | Выйти из сборщика пользовательских патчей | |
| `` / `` | Найти | |
<pre>
<kbd>&lt;left&gt;</kbd>: Выбрать предыдущую часть
<kbd>&lt;right&gt;</kbd>: Выбрать следующую часть
<kbd>v</kbd>: Переключить выборку перетаскивания
<kbd>V</kbd>: Переключить выборку перетаскивания
<kbd>a</kbd>: Переключить выборку частей
<kbd>&lt;c-o&gt;</kbd>: Скопировать выделенный текст в буфер обмена
<kbd>o</kbd>: Открыть файл
<kbd>e</kbd>: Редактировать файл
<kbd>&lt;space&gt;</kbd>: Добавить/удалить строку(и) для патча
<kbd>&lt;esc&gt;</kbd>: Выйти из сборщика пользовательских патчей
<kbd>/</kbd>: Найти
</pre>
## Журнал ссылок (Reflog)
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать SHA коммита в буфер обмена | |
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Открыть коммит в браузере | |
| `` n `` | Создать новую ветку с этого коммита | |
| `` g `` | Просмотреть параметры сброса | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | Скопировать отобранные коммит (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | Сбросить отобранную (скопированную | cherry-picked) выборку коммитов | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | Просмотреть коммиты | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Скопировать SHA коммита в буфер обмена
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Переключить коммит
<kbd>y</kbd>: Скопировать атрибут коммита
<kbd>o</kbd>: Открыть коммит в браузере
<kbd>n</kbd>: Создать новую ветку с этого коммита
<kbd>g</kbd>: Просмотреть параметры сброса
<kbd>c</kbd>: Скопировать отобранные коммит (cherry-pick)
<kbd>C</kbd>: Скопировать несколько отобранных коммитов (cherry-pick)
<kbd>&lt;c-r&gt;</kbd>: Сбросить отобранную (скопированную | cherry-picked) выборку коммитов
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: Просмотреть коммиты
<kbd>/</kbd>: Filter the current view by text
</pre>
## Коммиты
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать SHA коммита в буфер обмена | |
| `` <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 fixup, but the selected commit's message will be discarded. |
| `` 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. |
| `` e `` | Edit (start interactive rebase) | Изменить коммит |
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
| `` p `` | Pick | Выбрать коммит (в середине перебазирования) |
| `` F `` | Создать fixup коммит | Создать fixup коммит для этого коммита |
| `` S `` | Apply fixup commits | Объединить все 'fixup!' коммиты выше в выбранный коммит (автосохранение) |
| `` <c-j> `` | Переместить коммит вниз на один | |
| `` <c-k> `` | Переместить коммит вверх на один | |
| `` V `` | Вставить отобранные коммиты (cherry-pick) | |
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
| `` A `` | Amend | Править последний коммит с проиндексированными изменениями |
| `` a `` | Установить/убрать автора коммита | Set/Reset commit author or set co-author. |
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
| `` T `` | Пометить коммит тегом | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
| `` <c-l> `` | Открыть меню журнала | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Открыть коммит в браузере | |
| `` n `` | Создать новую ветку с этого коммита | |
| `` g `` | Просмотреть параметры сброса | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | Скопировать отобранные коммит (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | Просмотреть файлы выбранного элемента | |
| `` w `` | View worktree options | |
| `` / `` | Найти | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Скопировать SHA коммита в буфер обмена
<kbd>&lt;c-r&gt;</kbd>: Сбросить отобранную (скопированную | cherry-picked) выборку коммитов
<kbd>b</kbd>: Просмотреть параметры бинарного поиска
<kbd>s</kbd>: Объединить несколько коммитов в один нижний
<kbd>f</kbd>: Объединить несколько коммитов в один отбросив сообщение коммита
<kbd>r</kbd>: Перефразировать коммит
<kbd>R</kbd>: Переписать коммит с помощью редактора
<kbd>d</kbd>: Удалить коммит
<kbd>e</kbd>: Изменить коммит
<kbd>p</kbd>: Выбрать коммит (в середине перебазирования)
<kbd>F</kbd>: Создать fixup коммит для этого коммита
<kbd>S</kbd>: Объединить все 'fixup!' коммиты выше в выбранный коммит (автосохранение)
<kbd>&lt;c-j&gt;</kbd>: Переместить коммит вниз на один
<kbd>&lt;c-k&gt;</kbd>: Переместить коммит вверх на один
<kbd>v</kbd>: Вставить отобранные коммиты (cherry-pick)
<kbd>B</kbd>: Mark commit as base commit for rebase
<kbd>A</kbd>: Править последний коммит с проиндексированными изменениями
<kbd>a</kbd>: Установить/убрать автора коммита
<kbd>t</kbd>: Отменить коммит
<kbd>T</kbd>: Пометить коммит тегом
<kbd>&lt;c-l&gt;</kbd>: Открыть меню журнала
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Переключить коммит
<kbd>y</kbd>: Скопировать атрибут коммита
<kbd>o</kbd>: Открыть коммит в браузере
<kbd>n</kbd>: Создать новую ветку с этого коммита
<kbd>g</kbd>: Просмотреть параметры сброса
<kbd>c</kbd>: Скопировать отобранные коммит (cherry-pick)
<kbd>C</kbd>: Скопировать несколько отобранных коммитов (cherry-pick)
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: Просмотреть файлы выбранного элемента
<kbd>/</kbd>: Найти
</pre>
## Локальные Ветки
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать название ветки в буфер обмена | |
| `` i `` | Показать параметры git-flow | |
| `` <space> `` | Переключить | Checkout selected item. |
| `` n `` | Новая ветка | |
| `` o `` | Создать запрос на принятие изменений | |
| `` O `` | Создать параметры запроса принятие изменений | |
| `` <c-y> `` | Скопировать URL запроса на принятие изменений в буфер обмена | |
| `` c `` | Переключить по названию | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
| `` F `` | Принудительное переключение | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
| `` d `` | Delete | View delete options for local/remote branch. |
| `` r `` | Перебазировать переключённую ветку на эту ветку | Rebase the checked-out branch onto the selected branch. |
| `` M `` | Слияние с текущей переключённой веткой | Merge selected branch into currently checked out branch. |
| `` f `` | Перемотать эту ветку вперёд из её upstream-ветки | Fast-forward selected branch from its upstream. |
| `` T `` | Создать тег | |
| `` s `` | Порядок сортировки | |
| `` g `` | Просмотреть параметры сброса | |
| `` R `` | Переименовать ветку | |
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
| `` <enter> `` | Просмотреть коммиты | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Скопировать название ветки в буфер обмена
<kbd>i</kbd>: Показать параметры git-flow
<kbd>&lt;space&gt;</kbd>: Переключить
<kbd>n</kbd>: Новая ветка
<kbd>o</kbd>: Создать запрос на принятие изменений
<kbd>O</kbd>: Создать параметры запроса принятие изменений
<kbd>&lt;c-y&gt;</kbd>: Скопировать URL запроса на принятие изменений в буфер обмена
<kbd>c</kbd>: Переключить по названию
<kbd>F</kbd>: Принудительное переключение
<kbd>d</kbd>: View delete options
<kbd>r</kbd>: Перебазировать переключённую ветку на эту ветку
<kbd>M</kbd>: Слияние с текущей переключённой веткой
<kbd>f</kbd>: Перемотать эту ветку вперёд из её upstream-ветки
<kbd>T</kbd>: Создать тег
<kbd>s</kbd>: Порядок сортировки
<kbd>g</kbd>: Просмотреть параметры сброса
<kbd>R</kbd>: Переименовать ветку
<kbd>u</kbd>: View upstream options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: Просмотреть коммиты
<kbd>/</kbd>: Filter the current view by text
</pre>
## Меню
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Выполнить | |
| `` <esc> `` | Закрыть | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Выполнить
<kbd>&lt;esc&gt;</kbd>: Закрыть
<kbd>/</kbd>: Filter the current view by text
</pre>
## Панель Подтверждения
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Подтвердить | |
| `` <esc> `` | Закрыть/отменить | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Подтвердить
<kbd>&lt;esc&gt;</kbd>: Закрыть/отменить
</pre>
## Подкоммиты
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать SHA коммита в буфер обмена | |
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | Открыть коммит в браузере | |
| `` n `` | Создать новую ветку с этого коммита | |
| `` g `` | Просмотреть параметры сброса | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | Скопировать отобранные коммит (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | Сбросить отобранную (скопированную | cherry-picked) выборку коммитов | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | Просмотреть файлы выбранного элемента | |
| `` w `` | View worktree options | |
| `` / `` | Найти | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Скопировать SHA коммита в буфер обмена
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: Переключить коммит
<kbd>y</kbd>: Скопировать атрибут коммита
<kbd>o</kbd>: Открыть коммит в браузере
<kbd>n</kbd>: Создать новую ветку с этого коммита
<kbd>g</kbd>: Просмотреть параметры сброса
<kbd>c</kbd>: Скопировать отобранные коммит (cherry-pick)
<kbd>C</kbd>: Скопировать несколько отобранных коммитов (cherry-pick)
<kbd>&lt;c-r&gt;</kbd>: Сбросить отобранную (скопированную | cherry-picked) выборку коммитов
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: Просмотреть файлы выбранного элемента
<kbd>/</kbd>: Найти
</pre>
## Подмодули
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать название подмодуля в буфер обмена | |
| `` <enter> `` | Enter | Ввести подмодуль |
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
| `` u `` | Update | Обновить подмодуль |
| `` n `` | Добавить новый подмодуль | |
| `` e `` | Обновить URL подмодуля | |
| `` i `` | Initialize | Инициализировать подмодуль |
| `` b `` | Просмотреть параметры массового подмодуля | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Скопировать название подмодуля в буфер обмена
<kbd>&lt;enter&gt;</kbd>: Ввести подмодуль
<kbd>&lt;space&gt;</kbd>: Ввести подмодуль
<kbd>d</kbd>: Удалить подмодуль
<kbd>u</kbd>: Обновить подмодуль
<kbd>n</kbd>: Добавить новый подмодуль
<kbd>e</kbd>: Обновить URL подмодуля
<kbd>i</kbd>: Инициализировать подмодуль
<kbd>b</kbd>: Просмотреть параметры массового подмодуля
<kbd>/</kbd>: Filter the current view by text
</pre>
## Сводка коммита
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | Подтвердить | |
| `` <esc> `` | Закрыть | |
<pre>
<kbd>&lt;enter&gt;</kbd>: Подтвердить
<kbd>&lt;esc&gt;</kbd>: Закрыть
</pre>
## Сохранить Изменения Файлов
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать название файла в буфер обмена | |
| `` c `` | Переключить | Переключить файл |
| `` d `` | Remove | Отменить изменения коммита в этом файле |
| `` o `` | Открыть файл | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <space> `` | Переключить файлы включённые в патч | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` a `` | Переключить все файлы, включённые в патч | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` <enter> `` | Введите файл, чтобы добавить выбранные строки в патч (или свернуть каталог переключения) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
| `` ` `` | Переключить вид дерева файлов | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` / `` | Найти | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Скопировать закомиченное имя файла в буфер обмена
<kbd>c</kbd>: Переключить файл
<kbd>d</kbd>: Отменить изменения коммита в этом файле
<kbd>o</kbd>: Открыть файл
<kbd>e</kbd>: Редактировать файл
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;space&gt;</kbd>: Переключить файлы включённые в патч
<kbd>a</kbd>: Переключить все файлы, включённые в патч
<kbd>&lt;enter&gt;</kbd>: Введите файл, чтобы добавить выбранные строки в патч (или свернуть каталог переключения)
<kbd>`</kbd>: Переключить вид дерева файлов
<kbd>/</kbd>: Найти
</pre>
## Статус
| Key | Action | Info |
|-----|--------|-------------|
| `` o `` | Открыть файл конфигурации | Open file in default application. |
| `` e `` | Редактировать файл конфигурации | Open file in external editor. |
| `` u `` | Проверить обновления | |
| `` <enter> `` | Переключиться на последний репозиторий | |
| `` a `` | Показать все логи ветки | |
<pre>
<kbd>o</kbd>: Открыть файл конфигурации
<kbd>e</kbd>: Редактировать файл конфигурации
<kbd>u</kbd>: Проверить обновления
<kbd>&lt;enter&gt;</kbd>: Переключиться на последний репозиторий
<kbd>a</kbd>: Показать все логи ветки
</pre>
## Теги
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Переключить | Checkout the selected tag tag as a detached HEAD. |
| `` n `` | Создать тег | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
| `` d `` | Delete | View delete options for local/remote tag. |
| `` P `` | Отправить тег | Push the selected tag to a remote. You'll be prompted to select a remote. |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | Просмотреть коммиты | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: Переключить
<kbd>d</kbd>: View delete options
<kbd>P</kbd>: Отправить тег
<kbd>n</kbd>: Создать тег
<kbd>g</kbd>: Просмотреть параметры сброса
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: Просмотреть коммиты
<kbd>/</kbd>: Filter the current view by text
</pre>
## Удалённые ветки
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать название ветки в буфер обмена | |
| `` <space> `` | Переключить | Checkout a new local branch based on the selected remote branch, or the remote branch as a detached head. |
| `` n `` | Новая ветка | |
| `` M `` | Слияние с текущей переключённой веткой | Merge selected branch into currently checked out branch. |
| `` r `` | Перебазировать переключённую ветку на эту ветку | Rebase the checked-out branch onto the selected branch. |
| `` d `` | Delete | Delete the remote branch from the remote. |
| `` u `` | Set as upstream | Установить как upstream-ветку переключённую ветку |
| `` s `` | Порядок сортировки | |
| `` g `` | Просмотреть параметры сброса | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | Просмотреть коммиты | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Скопировать название ветки в буфер обмена
<kbd>&lt;space&gt;</kbd>: Переключить
<kbd>n</kbd>: Новая ветка
<kbd>M</kbd>: Слияние с текущей переключённой веткой
<kbd>r</kbd>: Перебазировать переключённую ветку на эту ветку
<kbd>d</kbd>: Delete remote tag
<kbd>u</kbd>: Установить как upstream-ветку переключённую ветку
<kbd>s</kbd>: Порядок сортировки
<kbd>g</kbd>: Просмотреть параметры сброса
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: Просмотреть коммиты
<kbd>/</kbd>: Filter the current view by text
</pre>
## Удалённые репозитории
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | View branches | |
| `` n `` | Добавить новую удалённую ветку | |
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
| `` e `` | Edit | Редактировать удалённый репозитории |
| `` f `` | Получить изменения | Получение изменения из удалённого репозитория |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>f</kbd>: Получение изменения из удалённого репозитория
<kbd>n</kbd>: Добавить новую удалённую ветку
<kbd>d</kbd>: Удалить удалённую ветку
<kbd>e</kbd>: Редактировать удалённый репозитории
<kbd>/</kbd>: Filter the current view by text
</pre>
## Файлы
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | Скопировать название файла в буфер обмена | |
| `` <space> `` | Переключить индекс | Toggle staged for selected file. |
| `` <c-b> `` | Фильтровать файлы (проиндексированные/непроиндексированные) | |
| `` y `` | Copy to clipboard | |
| `` c `` | Сохранить изменения | Commit staged changes. |
| `` w `` | Закоммитить изменения без предварительного хука коммита | |
| `` A `` | Правка последнего коммита | |
| `` C `` | Сохранить изменения с помощью редактора git | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` e `` | Edit | Open file in external editor. |
| `` o `` | Открыть файл | Open file in default application. |
| `` i `` | Игнорировать или исключить файл | |
| `` r `` | Обновить файлы | |
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
| `` S `` | Просмотреть параметры хранилища | View stash options (e.g. stash all, stash staged, stash unstaged). |
| `` a `` | Все проиндексированные/непроиндексированные | Toggle staged/unstaged for all files in working tree. |
| `` <enter> `` | Проиндексировать отдельные части/строки для файла или свернуть/развернуть для каталога | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
| `` d `` | Просмотреть параметры «отмены изменении» | View options for discarding changes to the selected file. |
| `` g `` | Просмотреть параметры сброса upstream-ветки | |
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
| `` ` `` | Переключить вид дерева файлов | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` M `` | Открыть внешний инструмент слияния (git mergetool) | Run `git mergetool`. |
| `` f `` | Получить изменения | Fetch changes from remote. |
| `` / `` | Найти | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: Скопировать название файла в буфер обмена
<kbd>d</kbd>: Просмотреть параметры «отмены изменении»
<kbd>&lt;space&gt;</kbd>: Переключить индекс
<kbd>&lt;c-b&gt;</kbd>: Фильтровать файлы (проиндексированные/непроиндексированные)
<kbd>y</kbd>: Copy to clipboard
<kbd>c</kbd>: Сохранить изменения
<kbd>w</kbd>: Закоммитить изменения без предварительного хука коммита
<kbd>A</kbd>: Правка последнего коммита
<kbd>C</kbd>: Сохранить изменения с помощью редактора git
<kbd>&lt;c-f&gt;</kbd>: Find base commit for fixup
<kbd>e</kbd>: Редактировать файл
<kbd>o</kbd>: Открыть файл
<kbd>i</kbd>: Игнорировать или исключить файл
<kbd>r</kbd>: Обновить файлы
<kbd>s</kbd>: Припрятать все изменения
<kbd>S</kbd>: Просмотреть параметры хранилища
<kbd>a</kbd>: Все проиндексированные/непроиндексированные
<kbd>&lt;enter&gt;</kbd>: Проиндексировать отдельные части/строки для файла или свернуть/развернуть для каталога
<kbd>g</kbd>: Просмотреть параметры сброса upstream-ветки
<kbd>D</kbd>: Просмотреть параметры сброса
<kbd>`</kbd>: Переключить вид дерева файлов
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>M</kbd>: Открыть внешний инструмент слияния (git mergetool)
<kbd>f</kbd>: Получить изменения
<kbd>/</kbd>: Найти
</pre>
## Хранилище
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | Применить припрятанные изменения | Apply the stash entry to your working directory. |
| `` g `` | Применить припрятанные изменения и тут же удалить их из хранилища | Apply the stash entry to your working directory and remove the stash entry. |
| `` d `` | Удалить припрятанные изменения из хранилища | Remove the stash entry from the stash list. |
| `` n `` | Новая ветка | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
| `` r `` | Переименовать хранилище | |
| `` <enter> `` | Просмотреть файлы выбранного элемента | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: Применить припрятанные изменения
<kbd>g</kbd>: Применить припрятанные изменения и тут же удалить их из хранилища
<kbd>d</kbd>: Удалить припрятанные изменения из хранилища
<kbd>n</kbd>: Новая ветка
<kbd>r</kbd>: Переименовать хранилище
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: Просмотреть файлы выбранного элемента
<kbd>/</kbd>: Filter the current view by text
</pre>

View File

@@ -6,359 +6,357 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
## 全局键绑定
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-r> `` | 切换到最近的仓库 | |
| `` <pgup> (fn+up/shift+k) `` | 向上滚动主面板 | |
| `` <pgdown> (fn+down/shift+j) `` | 向下滚动主面板 | |
| `` @ `` | 打开命令日志菜单 | View options for the command log e.g. show/hide the command log and focus the command log. |
| `` P `` | 推送 | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` p `` | 拉取 | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` } `` | 扩大差异视图中显示的上下文范围 | Increase the amount of the context shown around changes in the diff view. |
| `` { `` | 缩小差异视图中显示的上下文范围 | Decrease the amount of the context shown around changes in the diff view. |
| `` : `` | 执行自定义命令 | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
| `` <c-p> `` | 查看自定义补丁选项 | |
| `` m `` | 查看 合并/变基 选项 | View options to abort/continue/skip the current merge/rebase. |
| `` R `` | 刷新 | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
| `` + `` | 下一屏模式(正常/半屏/全屏) | |
| `` _ `` | 上一屏模式 | |
| `` ? `` | 打开菜单 | |
| `` <c-s> `` | 查看按路径过滤选项 | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | 打开 diff 菜单 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | 打开 diff 菜单 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | 退出 | |
| `` <esc> `` | 取消 | |
| `` <c-w> `` | 切换是否在差异视图中显示空白字符差异 | Toggle whether or not whitespace changes are shown in the diff view. |
| `` z `` | (通过 reflog撤销「实验功能」 | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
| `` <c-z> `` | (通过 reflog重做「实验功能」 | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
<pre>
<kbd>&lt;c-r&gt;</kbd>: 切换到最近的仓库
<kbd>&lt;pgup&gt;</kbd>: 向上滚动主面板 (fn+up/shift+k)
<kbd>&lt;pgdown&gt;</kbd>: 向下滚动主面板 (fn+down/shift+j)
<kbd>@</kbd>: 打开命令日志菜单
<kbd>}</kbd>: 扩大差异视图中显示的上下文范围
<kbd>{</kbd>: 缩小差异视图中显示的上下文范围
<kbd>:</kbd>: 执行自定义命令
<kbd>&lt;c-p&gt;</kbd>: 查看自定义补丁选项
<kbd>m</kbd>: 查看 合并/变基 选项
<kbd>R</kbd>: 刷新
<kbd>+</kbd>: 下一屏模式(正常/半屏/全屏)
<kbd>_</kbd>: 上一屏模式
<kbd>?</kbd>: 打开菜单
<kbd>&lt;c-s&gt;</kbd>: 查看按路径过滤选项
<kbd>W</kbd>: 打开 diff 菜单
<kbd>&lt;c-e&gt;</kbd>: 打开 diff 菜单
<kbd>&lt;c-w&gt;</kbd>: 切换是否在差异视图中显示空白字符差异
<kbd>z</kbd>: (通过 reflog撤销「实验功能」
<kbd>&lt;c-z&gt;</kbd>: (通过 reflog重做「实验功能」
<kbd>P</kbd>: 推送
<kbd>p</kbd>: 拉取
</pre>
## 列表面板导航
| Key | Action | Info |
|-----|--------|-------------|
| `` , `` | 上一页 | |
| `` . `` | 下一页 | |
| `` < `` | 滚动到顶部 | |
| `` > `` | 滚动到底部 | |
| `` v `` | 切换拖动选择 | |
| `` <s-down> `` | Range select down | |
| `` <s-up> `` | Range select up | |
| `` / `` | 开始搜索 | |
| `` H `` | 向左滚动 | |
| `` L `` | 向右滚动 | |
| `` ] `` | 下一个标签 | |
| `` [ `` | 上一个标签 | |
<pre>
<kbd>,</kbd>: 上一页
<kbd>.</kbd>: 下一页
<kbd>&lt;</kbd>: 滚动到顶部
<kbd>&gt;</kbd>: 滚动到底部
<kbd>/</kbd>: 开始搜索
<kbd>H</kbd>: 向左滚动
<kbd>L</kbd>: 向右滚动
<kbd>]</kbd>: 下一个标签
<kbd>[</kbd>: 上一个标签
</pre>
## Reflog 页面
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 将提交的 SHA 复制到剪贴板 | |
| `` <space> `` | 检出 | 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 `` | 在浏览器中打开提交 | |
| `` n `` | 从提交创建新分支 | |
| `` g `` | 查看重置选项 | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | 复制提交(拣选) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | 重置已拣选(复制)的提交 | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | 查看提交 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 将提交的 SHA 复制到剪贴板
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: 检出提交
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: 在浏览器中打开提交
<kbd>n</kbd>: 从提交创建新分支
<kbd>g</kbd>: 查看重置选项
<kbd>c</kbd>: 复制提交(拣选)
<kbd>C</kbd>: 复制提交范围(拣选)
<kbd>&lt;c-r&gt;</kbd>: 重置已拣选(复制)的提交
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: 查看提交
<kbd>/</kbd>: Filter the current view by text
</pre>
## Worktrees
| Key | Action | Info |
|-----|--------|-------------|
| `` n `` | New worktree | |
| `` <space> `` | Switch | Switch to the selected worktree. |
| `` o `` | Open in editor | |
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>n</kbd>: Create worktree
<kbd>&lt;space&gt;</kbd>: Switch to worktree
<kbd>&lt;enter&gt;</kbd>: Switch to worktree
<kbd>o</kbd>: Open in editor
<kbd>d</kbd>: Remove worktree
<kbd>/</kbd>: Filter the current view by text
</pre>
## 分支页面
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 将分支名称复制到剪贴板 | |
| `` i `` | 显示 git-flow 选项 | |
| `` <space> `` | 检出 | Checkout selected item. |
| `` n `` | 新分支 | |
| `` o `` | 创建抓取请求 | |
| `` O `` | 创建抓取请求选项 | |
| `` <c-y> `` | 将抓取请求 URL 复制到剪贴板 | |
| `` c `` | 按名称检出 | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
| `` F `` | 强制检出 | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
| `` d `` | Delete | View delete options for local/remote branch. |
| `` r `` | 将已检出的分支变基到该分支 | Rebase the checked-out branch onto the selected branch. |
| `` M `` | 合并到当前检出的分支 | Merge selected branch into currently checked out branch. |
| `` f `` | 从上游快进此分支 | Fast-forward selected branch from its upstream. |
| `` T `` | 创建标签 | |
| `` s `` | Sort order | |
| `` g `` | 查看重置选项 | |
| `` R `` | 重命名分支 | |
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
| `` <enter> `` | 查看提交 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 将分支名称复制到剪贴板
<kbd>i</kbd>: 显示 git-flow 选项
<kbd>&lt;space&gt;</kbd>: 检出
<kbd>n</kbd>: 新分支
<kbd>o</kbd>: 创建抓取请求
<kbd>O</kbd>: 创建抓取请求选项
<kbd>&lt;c-y&gt;</kbd>: 将抓取请求 URL 复制到剪贴板
<kbd>c</kbd>: 按名称检出
<kbd>F</kbd>: 强制检出
<kbd>d</kbd>: View delete options
<kbd>r</kbd>: 将已检出的分支变基到该分支
<kbd>M</kbd>: 合并到当前检出的分支
<kbd>f</kbd>: 从上游快进此分支
<kbd>T</kbd>: 创建标签
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: 查看重置选项
<kbd>R</kbd>: 重命名分支
<kbd>u</kbd>: View upstream options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 查看提交
<kbd>/</kbd>: Filter the current view by text
</pre>
## 子提交
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 将提交的 SHA 复制到剪贴板 | |
| `` <space> `` | 检出 | 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 `` | 在浏览器中打开提交 | |
| `` n `` | 从提交创建新分支 | |
| `` g `` | 查看重置选项 | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | 复制提交(拣选) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | 重置已拣选(复制)的提交 | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | 查看提交的文件 | |
| `` w `` | View worktree options | |
| `` / `` | 开始搜索 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 将提交的 SHA 复制到剪贴板
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: 检出提交
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: 在浏览器中打开提交
<kbd>n</kbd>: 从提交创建新分支
<kbd>g</kbd>: 查看重置选项
<kbd>c</kbd>: 复制提交(拣选)
<kbd>C</kbd>: 复制提交范围(拣选)
<kbd>&lt;c-r&gt;</kbd>: 重置已拣选(复制)的提交
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: 查看提交的文件
<kbd>/</kbd>: 开始搜索
</pre>
## 子模块
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 将子模块名称复制到剪贴板 | |
| `` <enter> `` | Enter | 输入子模块 |
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
| `` u `` | Update | 更新子模块 |
| `` n `` | 添加新的子模块 | |
| `` e `` | 更新子模块 URL | |
| `` i `` | Initialize | 初始化子模块 |
| `` b `` | 查看批量子模块选项 | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 将子模块名称复制到剪贴板
<kbd>&lt;enter&gt;</kbd>: 输入子模块
<kbd>&lt;space&gt;</kbd>: 输入子模块
<kbd>d</kbd>: 删除子模块
<kbd>u</kbd>: 更新子模块
<kbd>n</kbd>: 添加新的子模块
<kbd>e</kbd>: 更新子模块 URL
<kbd>i</kbd>: 初始化子模块
<kbd>b</kbd>: 查看批量子模块选项
<kbd>/</kbd>: Filter the current view by text
</pre>
## 提交
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 将提交的 SHA 复制到剪贴板 | |
| `` <c-r> `` | 重置已拣选(复制)的提交 | |
| `` b `` | 查看二分查找选项 | |
| `` 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 fixup, but the selected commit's message will be discarded. |
| `` 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. |
| `` e `` | Edit (start interactive rebase) | 编辑提交 |
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
| `` p `` | Pick | 选择提交(变基过程中) |
| `` F `` | 为此提交创建修正 | 创建修正提交 |
| `` S `` | Apply fixup commits | 压缩在所选提交之上的所有“fixup!”提交(自动压缩) |
| `` <c-j> `` | 下移提交 | |
| `` <c-k> `` | 上移提交 | |
| `` V `` | 粘贴提交(拣选) | |
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
| `` A `` | Amend | 用已暂存的更改来修补提交 |
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
| `` T `` | 标签提交 | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
| `` <c-l> `` | 打开日志菜单 | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
| `` <space> `` | 检出 | 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 `` | 在浏览器中打开提交 | |
| `` n `` | 从提交创建新分支 | |
| `` g `` | 查看重置选项 | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | 复制提交(拣选) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | 查看提交的文件 | |
| `` w `` | View worktree options | |
| `` / `` | 开始搜索 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 将提交的 SHA 复制到剪贴板
<kbd>&lt;c-r&gt;</kbd>: 重置已拣选(复制)的提交
<kbd>b</kbd>: 查看二分查找选项
<kbd>s</kbd>: 向下压缩
<kbd>f</kbd>: 修正提交fixup
<kbd>r</kbd>: 改写提交
<kbd>R</kbd>: 使用编辑器重命名提交
<kbd>d</kbd>: 删除提交
<kbd>e</kbd>: 编辑提交
<kbd>p</kbd>: 选择提交(变基过程中)
<kbd>F</kbd>: 创建修正提交
<kbd>S</kbd>: 压缩在所选提交之上的所有“fixup!”提交(自动压缩)
<kbd>&lt;c-j&gt;</kbd>: 下移提交
<kbd>&lt;c-k&gt;</kbd>: 上移提交
<kbd>v</kbd>: 粘贴提交(拣选)
<kbd>B</kbd>: Mark commit as base commit for rebase
<kbd>A</kbd>: 用已暂存的更改来修补提交
<kbd>a</kbd>: Set/Reset commit author
<kbd>t</kbd>: 还原提交
<kbd>T</kbd>: 标签提交
<kbd>&lt;c-l&gt;</kbd>: 打开日志菜单
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: 检出提交
<kbd>y</kbd>: Copy commit attribute
<kbd>o</kbd>: 在浏览器中打开提交
<kbd>n</kbd>: 从提交创建新分支
<kbd>g</kbd>: 查看重置选项
<kbd>c</kbd>: 复制提交(拣选)
<kbd>C</kbd>: 复制提交范围(拣选)
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: 查看提交的文件
<kbd>/</kbd>: 开始搜索
</pre>
## 提交文件
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 将文件名复制到剪贴板 | |
| `` c `` | 检出 | 检出文件 |
| `` d `` | Remove | 放弃对此文件的提交更改 |
| `` o `` | 打开文件 | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <space> `` | 补丁中包含的切换文件 | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` <enter> `` | 输入文件以将所选行添加到补丁中(或切换目录折叠) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
| `` ` `` | 切换文件树视图 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` / `` | 开始搜索 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 将提交的文件名复制到剪贴板
<kbd>c</kbd>: 检出文件
<kbd>d</kbd>: 放弃对此文件的提交更改
<kbd>o</kbd>: 打开文件
<kbd>e</kbd>: 编辑文件
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;space&gt;</kbd>: 补丁中包含的切换文件
<kbd>a</kbd>: Toggle all files included in patch
<kbd>&lt;enter&gt;</kbd>: 输入文件以将所选行添加到补丁中(或切换目录折叠)
<kbd>`</kbd>: 切换文件树视图
<kbd>/</kbd>: 开始搜索
</pre>
## 提交讯息
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 确认 | |
| `` <esc> `` | 关闭 | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 确认
<kbd>&lt;esc&gt;</kbd>: 关闭
</pre>
## 文件
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 将文件名复制到剪贴板 | |
| `` <space> `` | 切换暂存状态 | Toggle staged for selected file. |
| `` <c-b> `` | Filter files by status | |
| `` y `` | Copy to clipboard | |
| `` c `` | 提交更改 | Commit staged changes. |
| `` w `` | 提交更改而无需预先提交钩子 | |
| `` A `` | 修补最后一次提交 | |
| `` C `` | 提交更改(使用编辑器编辑提交信息) | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` e `` | Edit | Open file in external editor. |
| `` o `` | 打开文件 | Open file in default application. |
| `` i `` | 忽略文件 | |
| `` r `` | 刷新文件 | |
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
| `` S `` | 查看贮藏选项 | View stash options (e.g. stash all, stash staged, stash unstaged). |
| `` a `` | 切换所有文件的暂存状态 | Toggle staged/unstaged for all files in working tree. |
| `` <enter> `` | 暂存单个 块/行 用于文件, 或 折叠/展开 目录 | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
| `` d `` | 查看'放弃更改'选项 | View options for discarding changes to the selected file. |
| `` g `` | 查看上游重置选项 | |
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
| `` ` `` | 切换文件树视图 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` M `` | 打开外部合并工具 (git mergetool) | Run `git mergetool`. |
| `` f `` | 抓取 | Fetch changes from remote. |
| `` / `` | 开始搜索 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 将文件名复制到剪贴板
<kbd>d</kbd>: 查看'放弃更改'选项
<kbd>&lt;space&gt;</kbd>: 切换暂存状态
<kbd>&lt;c-b&gt;</kbd>: Filter files by status
<kbd>y</kbd>: Copy to clipboard
<kbd>c</kbd>: 提交更改
<kbd>w</kbd>: 提交更改而无需预先提交钩子
<kbd>A</kbd>: 修补最后一次提交
<kbd>C</kbd>: 提交更改(使用编辑器编辑提交信息)
<kbd>&lt;c-f&gt;</kbd>: Find base commit for fixup
<kbd>e</kbd>: 编辑文件
<kbd>o</kbd>: 打开文件
<kbd>i</kbd>: 忽略文件
<kbd>r</kbd>: 刷新文件
<kbd>s</kbd>: 将所有更改加入贮藏
<kbd>S</kbd>: 查看贮藏选项
<kbd>a</kbd>: 切换所有文件的暂存状态
<kbd>&lt;enter&gt;</kbd>: 暂存单个 块/行 用于文件, 或 折叠/展开 目录
<kbd>g</kbd>: 查看上游重置选项
<kbd>D</kbd>: 查看重置选项
<kbd>`</kbd>: 切换文件树视图
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>M</kbd>: 打开外部合并工具 (git mergetool)
<kbd>f</kbd>: 抓取
<kbd>/</kbd>: 开始搜索
</pre>
## 构建补丁中
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | 选择一个区块 | |
| `` <right> `` | 选择下一个区块 | |
| `` v `` | 切换拖动选择 | |
| `` a `` | 切换选择区块 | Toggle hunk selection mode. |
| `` <c-o> `` | 将选中文本复制到剪贴板 | |
| `` o `` | 打开文件 | Open file in default application. |
| `` e `` | 编辑文件 | Open file in external editor. |
| `` <space> `` | 添加/移除 行到补丁 | |
| `` <esc> `` | 退出逐行模式 | |
| `` / `` | 开始搜索 | |
<pre>
<kbd>&lt;left&gt;</kbd>: 选择上一个区块
<kbd>&lt;right&gt;</kbd>: 选择一个区块
<kbd>v</kbd>: 切换拖动选择
<kbd>V</kbd>: 切换拖动选择
<kbd>a</kbd>: 切换选择区块
<kbd>&lt;c-o&gt;</kbd>: 将选中文本复制到剪贴板
<kbd>o</kbd>: 打开文件
<kbd>e</kbd>: 编辑文件
<kbd>&lt;space&gt;</kbd>: 添加/移除 行到补丁
<kbd>&lt;esc&gt;</kbd>: 退出逐行模式
<kbd>/</kbd>: 开始搜索
</pre>
## 标签页面
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | 检出 | Checkout the selected tag tag as a detached HEAD. |
| `` n `` | 创建标签 | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
| `` d `` | Delete | View delete options for local/remote tag. |
| `` P `` | 推送标签 | Push the selected tag to a remote. You'll be prompted to select a remote. |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | 查看提交 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: 检出
<kbd>d</kbd>: View delete options
<kbd>P</kbd>: 推送标签
<kbd>n</kbd>: 创建标签
<kbd>g</kbd>: 查看重置选项
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 查看提交
<kbd>/</kbd>: Filter the current view by text
</pre>
## 正在合并
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | 选中区块 | |
| `` b `` | 选中所有区块 | |
| `` <up> `` | 选择顶部块 | |
| `` <down> `` | 选择部块 | |
| `` <left> `` | 选择上一个冲突 | |
| `` <right> `` | 选择下一个冲突 | |
| `` z `` | 撤销 | Undo last merge conflict resolution. |
| `` e `` | 编辑文件 | Open file in external editor. |
| `` o `` | 打开文件 | Open file in default application. |
| `` M `` | 打开外部合并工具 (git mergetool) | Run `git mergetool`. |
| `` <esc> `` | 返回文件面板 | |
<pre>
<kbd>e</kbd>: 编辑文件
<kbd>o</kbd>: 打开文件
<kbd>&lt;left&gt;</kbd>: 选择上一个冲突
<kbd>&lt;right&gt;</kbd>: 选择下一个冲突
<kbd>&lt;up&gt;</kbd>: 选择部块
<kbd>&lt;down&gt;</kbd>: 选择底部块
<kbd>z</kbd>: 撤销
<kbd>M</kbd>: 打开外部合并工具 (git mergetool)
<kbd>&lt;space&gt;</kbd>: 选中区块
<kbd>b</kbd>: 选中所有区块
<kbd>&lt;esc&gt;</kbd>: 返回文件面板
</pre>
## 正在暂存
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | 选择一个区块 | |
| `` <right> `` | 选择下一个区块 | |
| `` v `` | 切换拖动选择 | |
| `` a `` | 切换选择区块 | Toggle hunk selection mode. |
| `` <c-o> `` | 将选中文本复制到剪贴板 | |
| `` <space> `` | 切换暂存状态 | 切换行暂存状态 |
| `` d `` | 取消变更 (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
| `` o `` | 打开文件 | Open file in default application. |
| `` e `` | 编辑文件 | Open file in external editor. |
| `` <esc> `` | 返回文件面板 | |
| `` <tab> `` | 切换到其他面板 | Switch to other view (staged/unstaged changes). |
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
| `` c `` | 提交更改 | Commit staged changes. |
| `` w `` | 提交更改而无需预先提交钩子 | |
| `` C `` | 提交更改(使用编辑器编辑提交信息) | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` / `` | 开始搜索 | |
<pre>
<kbd>&lt;left&gt;</kbd>: 选择上一个区块
<kbd>&lt;right&gt;</kbd>: 选择一个区块
<kbd>v</kbd>: 切换拖动选择
<kbd>V</kbd>: 切换拖动选择
<kbd>a</kbd>: 切换选择区块
<kbd>&lt;c-o&gt;</kbd>: 将选中文本复制到剪贴板
<kbd>o</kbd>: 打开文件
<kbd>e</kbd>: 编辑文件
<kbd>&lt;esc&gt;</kbd>: 返回文件面板
<kbd>&lt;tab&gt;</kbd>: 切换到其他面板
<kbd>&lt;space&gt;</kbd>: 切换行暂存状态
<kbd>d</kbd>: 取消变更 (git reset)
<kbd>E</kbd>: Edit hunk
<kbd>c</kbd>: 提交更改
<kbd>w</kbd>: 提交更改而无需预先提交钩子
<kbd>C</kbd>: 提交更改(使用编辑器编辑提交信息)
<kbd>/</kbd>: 开始搜索
</pre>
## 正常
| Key | Action | Info |
|-----|--------|-------------|
| `` mouse wheel down (fn+up) `` | 向下滚动 | |
| `` mouse wheel up (fn+down) `` | 向上滚动 | |
<pre>
<kbd>mouse wheel down</kbd>: 向下滚动 (fn+up)
<kbd>mouse wheel up</kbd>: 向上滚动 (fn+down)
</pre>
## 状态
| Key | Action | Info |
|-----|--------|-------------|
| `` o `` | 打开配置文件 | Open file in default application. |
| `` e `` | 编辑配置文件 | Open file in external editor. |
| `` u `` | 检查更新 | |
| `` <enter> `` | 切换到最近的仓库 | |
| `` a `` | 显示所有分支的日志 | |
<pre>
<kbd>o</kbd>: 打开配置文件
<kbd>e</kbd>: 编辑配置文件
<kbd>u</kbd>: 检查更新
<kbd>&lt;enter&gt;</kbd>: 切换到最近的仓库
<kbd>a</kbd>: 显示所有分支的日志
</pre>
## 确认面板
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 确认 | |
| `` <esc> `` | 关闭 | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 确认
<kbd>&lt;esc&gt;</kbd>: 关闭
</pre>
## 菜单
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 执行 | |
| `` <esc> `` | 关闭 | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 执行
<kbd>&lt;esc&gt;</kbd>: 关闭
<kbd>/</kbd>: Filter the current view by text
</pre>
## 贮藏
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | 应用 | Apply the stash entry to your working directory. |
| `` g `` | 应用并删除 | Apply the stash entry to your working directory and remove the stash entry. |
| `` d `` | 删除 | Remove the stash entry from the stash list. |
| `` n `` | 新分支 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
| `` r `` | Rename stash | |
| `` <enter> `` | 查看提交的文件 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;space&gt;</kbd>: 应用
<kbd>g</kbd>: 应用并删除
<kbd>d</kbd>: 删除
<kbd>n</kbd>: 新分支
<kbd>r</kbd>: Rename stash
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 查看提交的文件
<kbd>/</kbd>: Filter the current view by text
</pre>
## 远程分支
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 将分支名称复制到剪贴板 | |
| `` <space> `` | 检出 | Checkout a new local branch based on the selected remote branch, or the remote branch as a detached head. |
| `` n `` | 新分支 | |
| `` M `` | 合并到当前检出的分支 | Merge selected branch into currently checked out branch. |
| `` r `` | 将已检出的分支变基到该分支 | Rebase the checked-out branch onto the selected branch. |
| `` d `` | Delete | Delete the remote branch from the remote. |
| `` u `` | Set as upstream | 设置为检出分支的上游 |
| `` s `` | Sort order | |
| `` g `` | 查看重置选项 | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | 查看提交 | |
| `` w `` | View worktree options | |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 将分支名称复制到剪贴板
<kbd>&lt;space&gt;</kbd>: 检出
<kbd>n</kbd>: 新分支
<kbd>M</kbd>: 合并到当前检出的分支
<kbd>r</kbd>: 将已检出的分支变基到该分支
<kbd>d</kbd>: Delete remote tag
<kbd>u</kbd>: 设置为检出分支的上游
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: 查看重置选项
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 查看提交
<kbd>/</kbd>: Filter the current view by text
</pre>
## 远程页面
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | View branches | |
| `` n `` | 添加新的远程仓库 | |
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
| `` e `` | Edit | 编辑远程仓库 |
| `` f `` | 抓取 | 抓取远程仓库 |
| `` / `` | Filter the current view by text | |
<pre>
<kbd>f</kbd>: 抓取远程仓库
<kbd>n</kbd>: 添加新的远程仓库
<kbd>d</kbd>: 删除远程
<kbd>e</kbd>: 编辑远程仓库
<kbd>/</kbd>: Filter the current view by text
</pre>

View File

@@ -2,363 +2,361 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
# Lazygit 鍵盤快捷鍵
_說明:`<c-b>` 表示 CtrlB、`<a-b>` 表示 AltB`B`表示 ShiftB_
_說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B`B`表示 Shift+B_
## 全快捷鍵
## 全快捷鍵
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-r> `` | 切換到最近使用的版本庫 | |
| `` <pgup> (fn+up/shift+k) `` | 向上捲動主面板 | |
| `` <pgdown> (fn+down/shift+j) `` | 向下捲動主面板 | |
| `` @ `` | 開啟命令記錄選單 | View options for the command log e.g. show/hide the command log and focus the command log. |
| `` P `` | 推送 | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` p `` | 拉取 | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` } `` | 增加差異檢視中顯示變更周圍上下文的大小 | Increase the amount of the context shown around changes in the diff view. |
| `` { `` | 減小差異檢視中顯示變更周圍上下文的大小 | Decrease the amount of the context shown around changes in the diff view. |
| `` : `` | 執行自訂命令 | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
| `` <c-p> `` | 檢視自訂補丁選項 | |
| `` m `` | 查看合併/變基選項 | View options to abort/continue/skip the current merge/rebase. |
| `` R `` | 重新整理 | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
| `` + `` | 下一個螢幕模式(常規/半螢幕/全螢幕) | |
| `` _ `` | 上一個螢幕模式 | |
| `` ? `` | 開啟選單 | |
| `` <c-s> `` | 檢視篩選路徑選項 | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | 開啟差異比較選單 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | 開啟差異比較選單 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | 結束 | |
| `` <esc> `` | 取消 | |
| `` <c-w> `` | 切換是否在差異檢視中顯示空格變更 | Toggle whether or not whitespace changes are shown in the diff view. |
| `` z `` | 復原 | 將使用 reflog 確任 git 指令以復原。這不包括工作區更改;只考慮提交。 |
| `` <c-z> `` | 取消復原 | 將使用 reflog 確任 git 指令以重作。這不包括工作區更改;只考慮提交。 |
<pre>
<kbd>&lt;c-r&gt;</kbd>: 切換到最近使用的版本庫
<kbd>&lt;pgup&gt;</kbd>: 向上捲動主面板 (fn+up/shift+k)
<kbd>&lt;pgdown&gt;</kbd>: 向下捲動主面板 (fn+down/shift+j)
<kbd>@</kbd>: 開啟命令記錄選單
<kbd>}</kbd>: 增加差異檢視中顯示變更周圍上下文的大小
<kbd>{</kbd>: 減小差異檢視中顯示變更周圍上下文的大小
<kbd>:</kbd>: 執行自訂命令
<kbd>&lt;c-p&gt;</kbd>: 檢視自訂補丁選項
<kbd>m</kbd>: 查看合併/變基選項
<kbd>R</kbd>: 重新整理
<kbd>+</kbd>: 下一個螢幕模式(常規/半螢幕/全螢幕)
<kbd>_</kbd>: 上一個螢幕模式
<kbd>?</kbd>: 開啟選單
<kbd>&lt;c-s&gt;</kbd>: 檢視篩選路徑選項
<kbd>W</kbd>: 開啟差異比較選單
<kbd>&lt;c-e&gt;</kbd>: 開啟差異比較選單
<kbd>&lt;c-w&gt;</kbd>: 切換是否在差異檢視中顯示空格變更
<kbd>z</kbd>: 復原
<kbd>&lt;c-z&gt;</kbd>: 取消復原
<kbd>P</kbd>: 推送
<kbd>p</kbd>: 拉取
</pre>
## 移動
## 列表面板導航
| Key | Action | Info |
|-----|--------|-------------|
| `` , `` | 上一頁 | |
| `` . `` | 下一頁 | |
| `` < `` | 捲動到頂部 | |
| `` > `` | 捲動到底部 | |
| `` v `` | 切換拖曳選擇 | |
| `` <s-down> `` | Range select down | |
| `` <s-up> `` | Range select up | |
| `` / `` | 搜尋 | |
| `` H `` | 向左捲動 | |
| `` L `` | 向右捲動 | |
| `` ] `` | 下一個索引標籤 | |
| `` [ `` | 上一個索引標籤 | |
<pre>
<kbd>,</kbd>: 上一頁
<kbd>.</kbd>: 下一頁
<kbd>&lt;</kbd>: 捲動到頂部
<kbd>&gt;</kbd>: 捲動到底部
<kbd>/</kbd>: 開始搜尋
<kbd>H</kbd>: 向左捲動
<kbd>L</kbd>: 向右捲動
<kbd>]</kbd>: 下一個索引標籤
<kbd>[</kbd>: 上一個索引標籤
</pre>
## Reflog
<pre>
<kbd>&lt;c-o&gt;</kbd>: 複製提交 SHA 到剪貼簿
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: 檢出提交
<kbd>y</kbd>: 複製提交屬性
<kbd>o</kbd>: 在瀏覽器中開啟提交
<kbd>n</kbd>: 從提交建立新分支
<kbd>g</kbd>: 檢視重設選項
<kbd>c</kbd>: 複製提交 (揀選)
<kbd>C</kbd>: 複製提交範圍 (揀選)
<kbd>&lt;c-r&gt;</kbd>: 重設選定的揀選 (複製) 提交
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: 檢視提交
<kbd>/</kbd>: Filter the current view by text
</pre>
## Worktrees
<pre>
<kbd>n</kbd>: Create worktree
<kbd>&lt;space&gt;</kbd>: Switch to worktree
<kbd>&lt;enter&gt;</kbd>: Switch to worktree
<kbd>o</kbd>: Open in editor
<kbd>d</kbd>: Remove worktree
<kbd>/</kbd>: Filter the current view by text
</pre>
## 主視窗 (一般)
<pre>
<kbd>mouse wheel down</kbd>: 向下捲動 (fn+up)
<kbd>mouse wheel up</kbd>: 向上捲動 (fn+down)
</pre>
## 主視窗 (合併中)
<pre>
<kbd>e</kbd>: 編輯檔案
<kbd>o</kbd>: 開啟檔案
<kbd>&lt;left&gt;</kbd>: 選擇上一個衝突
<kbd>&lt;right&gt;</kbd>: 選擇下一個衝突
<kbd>&lt;up&gt;</kbd>: 選擇上一段
<kbd>&lt;down&gt;</kbd>: 選擇下一段
<kbd>z</kbd>: 復原
<kbd>M</kbd>: 開啟外部合併工具 (git mergetool)
<kbd>&lt;space&gt;</kbd>: 挑選程式碼片段
<kbd>b</kbd>: 挑選所有程式碼片段
<kbd>&lt;esc&gt;</kbd>: 返回檔案面板
</pre>
## 主視窗 (預存中)
<pre>
<kbd>&lt;left&gt;</kbd>: 選擇上一段
<kbd>&lt;right&gt;</kbd>: 選擇下一段
<kbd>v</kbd>: 切換拖曳選擇
<kbd>V</kbd>: 切換拖曳選擇
<kbd>a</kbd>: 切換選擇程式碼塊
<kbd>&lt;c-o&gt;</kbd>: 複製所選文本至剪貼簿
<kbd>o</kbd>: 開啟檔案
<kbd>e</kbd>: 編輯檔案
<kbd>&lt;esc&gt;</kbd>: 返回檔案面板
<kbd>&lt;tab&gt;</kbd>: 切換至另一個面板 (已預存/未預存更改)
<kbd>&lt;space&gt;</kbd>: 切換現有行的狀態 (已預存/未預存)
<kbd>d</kbd>: 刪除變更 (git reset)
<kbd>E</kbd>: 編輯程式碼塊
<kbd>c</kbd>: 提交變更
<kbd>w</kbd>: 沒有預提交 hook 就提交更改
<kbd>C</kbd>: 使用 git 編輯器提交變更
<kbd>/</kbd>: 開始搜尋
</pre>
## 主面板 (補丁生成)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | 選擇一段 | |
| `` <right> `` | 選擇下一段 | |
| `` v `` | 切換拖曳選擇 | |
| `` a `` | 切換選擇程式碼塊 | Toggle hunk selection mode. |
| `` <c-o> `` | 複製所選文本至剪貼簿 | |
| `` o `` | 開啟檔案 | Open file in default application. |
| `` e `` | 編輯檔案 | Open file in external editor. |
| `` <space> `` | 向 (或從) 補丁中添加/刪除行 | |
| `` <esc> `` | 退出自訂補丁建立器 | |
| `` / `` | 搜尋 | |
## 主面板(一般)
| Key | Action | Info |
|-----|--------|-------------|
| `` mouse wheel down (fn+up) `` | 向下捲動 | |
| `` mouse wheel up (fn+down) `` | 向上捲動 | |
## 主面板(合併)
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | 挑選程式碼片段 | |
| `` b `` | 挑選所有程式碼片段 | |
| `` <up> `` | 選擇上一段 | |
| `` <down> `` | 選擇下一段 | |
| `` <left> `` | 選擇上一個衝突 | |
| `` <right> `` | 選擇下一個衝突 | |
| `` z `` | 復原 | Undo last merge conflict resolution. |
| `` e `` | 編輯檔案 | Open file in external editor. |
| `` o `` | 開啟檔案 | Open file in default application. |
| `` M `` | 開啟外部合併工具 (git mergetool) | Run `git mergetool`. |
| `` <esc> `` | 返回檔案面板 | |
## 主面板(預存)
| Key | Action | Info |
|-----|--------|-------------|
| `` <left> `` | 選擇上一段 | |
| `` <right> `` | 選擇下一段 | |
| `` v `` | 切換拖曳選擇 | |
| `` a `` | 切換選擇程式碼塊 | Toggle hunk selection mode. |
| `` <c-o> `` | 複製所選文本至剪貼簿 | |
| `` <space> `` | 切換預存 | 切換現有行的狀態 (已預存/未預存) |
| `` d `` | 刪除變更 (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
| `` o `` | 開啟檔案 | Open file in default application. |
| `` e `` | 編輯檔案 | Open file in external editor. |
| `` <esc> `` | 返回檔案面板 | |
| `` <tab> `` | 切換至另一個面板 (已預存/未預存更改) | Switch to other view (staged/unstaged changes). |
| `` E `` | 編輯程式碼塊 | Edit selected hunk in external editor. |
| `` c `` | 提交變更 | Commit staged changes. |
| `` w `` | 沒有預提交 hook 就提交更改 | |
| `` C `` | 使用 git 編輯器提交變更 | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;left&gt;</kbd>: 選擇上一段
<kbd>&lt;right&gt;</kbd>: 選擇一段
<kbd>v</kbd>: 切換拖曳選擇
<kbd>V</kbd>: 切換拖曳選擇
<kbd>a</kbd>: 切換選擇程式碼塊
<kbd>&lt;c-o&gt;</kbd>: 複製所選文本至剪貼簿
<kbd>o</kbd>: 開啟檔案
<kbd>e</kbd>: 編輯檔案
<kbd>&lt;space&gt;</kbd>: 向 (或從) 補丁中添加/刪除行
<kbd>&lt;esc&gt;</kbd>: 退出自訂補丁建立器
<kbd>/</kbd>: 開始搜尋
</pre>
## 功能表
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 執行 | |
| `` <esc> `` | 關閉 | |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 執行
<kbd>&lt;esc&gt;</kbd>: 關閉
<kbd>/</kbd>: Filter the current view by text
</pre>
## 子提交
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製提交 SHA 到剪貼簿 | |
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 在瀏覽器中開啟提交 | |
| `` n `` | 從提交建立新分支 | |
| `` g `` | 檢視重設選項 | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | 複製提交 (揀選) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | 重設選定的揀選 (複製) 提交 | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | 檢視所選項目的檔案 | |
| `` w `` | 檢視工作目錄選項 | |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 複製提交 SHA 到剪貼簿
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: 檢出提交
<kbd>y</kbd>: 複製提交屬性
<kbd>o</kbd>: 在瀏覽器中開啟提交
<kbd>n</kbd>: 從提交建立新分支
<kbd>g</kbd>: 檢視重設選項
<kbd>c</kbd>: 複製提交 (揀選)
<kbd>C</kbd>: 複製提交範圍 (揀選)
<kbd>&lt;c-r&gt;</kbd>: 重設選定的揀選 (複製) 提交
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: 檢視所選項目的檔案
<kbd>/</kbd>: 開始搜尋
</pre>
## 子模組
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製子模組名稱到剪貼簿 | |
| `` <enter> `` | Enter | 進入子模組 |
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
| `` u `` | Update | 更新子模組 |
| `` n `` | 新增子模組 | |
| `` e `` | 更新子模組 URL | |
| `` i `` | Initialize | 初始化子模組 |
| `` b `` | 查看批量子模組選項 | |
| `` / `` | 搜尋 | |
## 工作目錄
| Key | Action | Info |
|-----|--------|-------------|
| `` n `` | New worktree | |
| `` <space> `` | Switch | Switch to the selected worktree. |
| `` o `` | Open in editor | |
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 複製子模組名稱到剪貼簿
<kbd>&lt;enter&gt;</kbd>: 進入子模組
<kbd>&lt;space&gt;</kbd>: 進入子模組
<kbd>d</kbd>: 移除子模組
<kbd>u</kbd>: 更新子模組
<kbd>n</kbd>: 新增子模組
<kbd>e</kbd>: 更新子模組 URL
<kbd>i</kbd>: 初始化子模組
<kbd>b</kbd>: 查看批量子模組選項
<kbd>/</kbd>: Filter the current view by text
</pre>
## 提交
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製提交 SHA 到剪貼簿 | |
| `` <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 fixup, but the selected commit's message will be discarded. |
| `` 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. |
| `` e `` | Edit (start interactive rebase) | 編輯提交 |
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
| `` p `` | Pick | 挑選提交 (於變基過程中) |
| `` F `` | 建立修復提交 | 為此提交建立修復提交 |
| `` S `` | 壓縮上方所有「fixup」提交自動壓縮 | 是否壓縮上方 {{.commit}} 所有「fixup」提交 |
| `` <c-j> `` | 向下移動提交 | |
| `` <c-k> `` | 向上移動提交 | |
| `` V `` | 貼上提交 (揀選) | |
| `` B `` | 為了變基已標注提交為基準提交 | 請為了下一次變基選擇一項基準提交;此將執行 `git rebase --onto`。 |
| `` A `` | Amend | 使用已預存的更改修正提交 |
| `` a `` | 設定/重設提交作者 | Set/Reset commit author or set co-author. |
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
| `` T `` | 打標籤到提交 | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
| `` <c-l> `` | 開啟記錄選單 | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 在瀏覽器中開啟提交 | |
| `` n `` | 從提交建立新分支 | |
| `` g `` | 檢視重設選項 | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | 複製提交 (揀選) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | 檢視所選項目的檔案 | |
| `` w `` | 檢視工作目錄選項 | |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 複製提交 SHA 到剪貼簿
<kbd>&lt;c-r&gt;</kbd>: 重設選定的揀選 (複製) 提交
<kbd>b</kbd>: 查看二分選項
<kbd>s</kbd>: 向下壓縮
<kbd>f</kbd>: 修復提交 (Fixup)
<kbd>r</kbd>: 改寫提交
<kbd>R</kbd>: 使用編輯器改寫提交
<kbd>d</kbd>: 刪除提交
<kbd>e</kbd>: 編輯提交
<kbd>p</kbd>: 挑選提交 (於變基過程中)
<kbd>F</kbd>: 為此提交建立修復提交
<kbd>S</kbd>: 壓縮上方所有的“fixup!”提交 (自動壓縮)
<kbd>&lt;c-j&gt;</kbd>: 向下移動提交
<kbd>&lt;c-k&gt;</kbd>: 向上移動提交
<kbd>v</kbd>: 貼上提交 (揀選)
<kbd>B</kbd>: Mark commit as base commit for rebase
<kbd>A</kbd>: 使用已預存的更改修正提交
<kbd>a</kbd>: 設置/重設提交作者
<kbd>t</kbd>: 還原提交
<kbd>T</kbd>: 打標籤到提交
<kbd>&lt;c-l&gt;</kbd>: 開啟記錄選單
<kbd>w</kbd>: View worktree options
<kbd>&lt;space&gt;</kbd>: 檢出提交
<kbd>y</kbd>: 複製提交屬性
<kbd>o</kbd>: 在瀏覽器中開啟提交
<kbd>n</kbd>: 從提交建立新分支
<kbd>g</kbd>: 檢視重設選項
<kbd>c</kbd>: 複製提交 (揀選)
<kbd>C</kbd>: 複製提交範圍 (揀選)
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;enter&gt;</kbd>: 檢視所選項目的檔案
<kbd>/</kbd>: 開始搜尋
</pre>
## 提交摘要
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 確認 | |
| `` <esc> `` | 關閉 | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 確認
<kbd>&lt;esc&gt;</kbd>: 關閉
</pre>
## 提交檔案
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製檔案名稱到剪貼簿 | |
| `` 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. |
| `` o `` | 開啟檔案 | Open file in default application. |
| `` e `` | Edit | Open file in external editor. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <space> `` | 切換檔案是否包含在補丁中 | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` a `` | 切換所有檔案是否包含在補丁中 | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
| `` <enter> `` | 輸入檔案以將選定的行添加至補丁(或切換目錄折疊) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
| `` ` `` | 顯示檔案樹狀視圖 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 複製提交的檔案名稱到剪貼簿
<kbd>c</kbd>: 檢出檔案
<kbd>d</kbd>: 捨棄此提交對此檔案的更改
<kbd>o</kbd>: 開啟檔案
<kbd>e</kbd>: 編輯檔案
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>&lt;space&gt;</kbd>: 切換檔案是否包含在補丁中
<kbd>a</kbd>: 切換所有檔案是否包含在補丁中
<kbd>&lt;enter&gt;</kbd>: 輸入檔案以將選定的行添加至補丁(或切換目錄折疊)
<kbd>`</kbd>: 切換檔案樹狀視圖
<kbd>/</kbd>: 開始搜尋
</pre>
## 收藏 (Stash)
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | 套用 | Apply the stash entry to your working directory. |
| `` g `` | 還原 | Apply the stash entry to your working directory and remove the stash entry. |
| `` d `` | 捨棄 | Remove the stash entry from the stash list. |
| `` n `` | 新分支 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
| `` r `` | 重新命名收藏 | |
| `` <enter> `` | 檢視所選項目的檔案 | |
| `` w `` | 檢視工作目錄選項 | |
| `` / `` | 搜尋 | |
## 日誌
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製提交 SHA 到剪貼簿 | |
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
| `` o `` | 在瀏覽器中開啟提交 | |
| `` n `` | 從提交建立新分支 | |
| `` g `` | 檢視重設選項 | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` C `` | 複製提交 (揀選) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
| `` <c-r> `` | 重設選定的揀選 (複製) 提交 | |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` <enter> `` | 檢視提交 | |
| `` w `` | 檢視工作目錄選項 | |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;space&gt;</kbd>: 套用
<kbd>g</kbd>: 還原
<kbd>d</kbd>: 捨棄
<kbd>n</kbd>: 新分支
<kbd>r</kbd>: 重新命名收藏
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 檢視所選項目的檔案
<kbd>/</kbd>: Filter the current view by text
</pre>
## 本地分支
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製分支名稱到剪貼簿 | |
| `` i `` | 顯示 git-flow 選項 | |
| `` <space> `` | 檢出 | Checkout selected item. |
| `` n `` | 新分支 | |
| `` o `` | 建立拉取請求 | |
| `` O `` | 建立拉取請求選項 | |
| `` <c-y> `` | 複製拉取請求的 URL 到剪貼板 | |
| `` c `` | 根據名稱檢出 | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
| `` F `` | 強制檢出 | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
| `` d `` | Delete | View delete options for local/remote branch. |
| `` r `` | 將已檢出的分支變基至此分支 | Rebase the checked-out branch onto the selected branch. |
| `` M `` | 合併到當前檢出的分支 | Merge selected branch into currently checked out branch. |
| `` f `` | 從上游快進此分支 | Fast-forward selected branch from its upstream. |
| `` T `` | 建立標籤 | |
| `` s `` | Sort order | |
| `` g `` | 檢視重設選項 | |
| `` R `` | 重新命名分支 | |
| `` u `` | 檢視上游設定 | 檢視有關上游分支的設定(例如重設至上游) |
| `` <enter> `` | 檢視提交 | |
| `` w `` | 檢視工作目錄選項 | |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 複製分支名稱到剪貼簿
<kbd>i</kbd>: 顯示 git-flow 選項
<kbd>&lt;space&gt;</kbd>: 檢出
<kbd>n</kbd>: 新分支
<kbd>o</kbd>: 建立拉取請求
<kbd>O</kbd>: 建立拉取請求選項
<kbd>&lt;c-y&gt;</kbd>: 複製拉取請求的 URL 到剪貼板
<kbd>c</kbd>: 根據名稱檢出
<kbd>F</kbd>: 強制檢出
<kbd>d</kbd>: View delete options
<kbd>r</kbd>: 將已檢出的分支變基至此分支
<kbd>M</kbd>: 合併到當前檢出的分支
<kbd>f</kbd>: 從上游快進此分支
<kbd>T</kbd>: 建立標籤
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: 檢視重設選項
<kbd>R</kbd>: 重新命名分支
<kbd>u</kbd>: View upstream options
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 檢視提交
<kbd>/</kbd>: Filter the current view by text
</pre>
## 標籤
| Key | Action | Info |
|-----|--------|-------------|
| `` <space> `` | 檢出 | Checkout the selected tag tag as a detached HEAD. |
| `` n `` | 建立標籤 | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
| `` d `` | Delete | View delete options for local/remote tag. |
| `` P `` | 推送標籤 | Push the selected tag to a remote. You'll be prompted to select a remote. |
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | 檢視提交 | |
| `` w `` | 檢視工作目錄選項 | |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;space&gt;</kbd>: 檢出
<kbd>d</kbd>: View delete options
<kbd>P</kbd>: 推送標籤
<kbd>n</kbd>: 建立標籤
<kbd>g</kbd>: 檢視重設選項
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 檢視提交
<kbd>/</kbd>: Filter the current view by text
</pre>
## 檔案
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製檔案名稱到剪貼簿 | |
| `` <space> `` | 切換預存 | Toggle staged for selected file. |
| `` <c-b> `` | 篩選檔案 (預存/未預存) | |
| `` y `` | Copy to clipboard | |
| `` c `` | 提交變更 | Commit staged changes. |
| `` w `` | 沒有預提交 hook 就提交更改 | |
| `` A `` |上次提交 | |
| `` C `` | 使用 git 編輯器提交變更 | |
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
| `` e `` | Edit | Open file in external editor. |
| `` o `` | 開啟檔案 | Open file in default application. |
| `` i `` | 忽略或排除檔案 | |
| `` r `` | 重新整理檔案 | |
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
| `` S `` | 檢視收藏選項 | View stash options (e.g. stash all, stash staged, stash unstaged). |
| `` a `` | 全部預存/取消預存 | Toggle staged/unstaged for all files in working tree. |
| `` <enter> `` | 選擇檔案中的單個程式碼塊/行,或展開/折疊目錄 | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
| `` d `` | Discard | View options for discarding changes to the selected file. |
| `` g `` | 檢視上游重設選項 | |
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
| `` ` `` | 顯示檔案樹狀視圖 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
| `` <c-t> `` | Open external diff tool (git difftool) | |
| `` M `` | 開啟外部合併工具 (git mergetool) | Run `git mergetool`. |
| `` f `` | 擷取 | Fetch changes from remote. |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 複製檔案名稱到剪貼簿
<kbd>d</kbd>: 檢視“捨棄更改”的選項
<kbd>&lt;space&gt;</kbd>: 切換預存
<kbd>&lt;c-b&gt;</kbd>: 篩選檔案 (預存/未預存)
<kbd>y</kbd>: Copy to clipboard
<kbd>c</kbd>: 提交變更
<kbd>w</kbd>: 沒有預提交 hook 就提交更改
<kbd>A</kbd>:上次提交
<kbd>C</kbd>: 使用 git 編輯器提交變更
<kbd>&lt;c-f&gt;</kbd>: Find base commit for fixup
<kbd>e</kbd>: 編輯檔案
<kbd>o</kbd>: 開啟檔案
<kbd>i</kbd>: 忽略或排除檔案
<kbd>r</kbd>: 重新整理檔案
<kbd>s</kbd>: 收藏所有變更
<kbd>S</kbd>: 檢視收藏選項
<kbd>a</kbd>: 全部預存/取消預存
<kbd>&lt;enter&gt;</kbd>: 選擇檔案中的單個程式碼塊/行,或展開/折疊目錄
<kbd>g</kbd>: 檢視上游重設選項
<kbd>D</kbd>: 檢視重設選項
<kbd>`</kbd>: 切換檔案樹狀視圖
<kbd>&lt;c-t&gt;</kbd>: Open external diff tool (git difftool)
<kbd>M</kbd>: 開啟外部合併工具 (git mergetool)
<kbd>f</kbd>: 擷取
<kbd>/</kbd>: 開始搜尋
</pre>
## 狀態
| Key | Action | Info |
|-----|--------|-------------|
| `` o `` | 開啟設定檔案 | Open file in default application. |
| `` e `` | 編輯設定檔案 | Open file in external editor. |
| `` u `` | 檢查更新 | |
| `` <enter> `` | 切換到最近使用的版本庫 | |
| `` a `` | 顯示所有分支日誌 | |
<pre>
<kbd>o</kbd>: 開啟設定檔案
<kbd>e</kbd>: 編輯設定檔案
<kbd>u</kbd>: 檢查更新
<kbd>&lt;enter&gt;</kbd>: 切換到最近使用的版本庫
<kbd>a</kbd>: 顯示所有分支日誌
</pre>
## 確認面板
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | 確認 | |
| `` <esc> `` | 關閉/取消 | |
<pre>
<kbd>&lt;enter&gt;</kbd>: 確認
<kbd>&lt;esc&gt;</kbd>: 關閉/取消
</pre>
## 遠端
| Key | Action | Info |
|-----|--------|-------------|
| `` <enter> `` | View branches | |
| `` n `` | 新增遠端 | |
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
| `` e `` | Edit | 編輯遠端 |
| `` f `` | 擷取 | 擷取遠端 |
| `` / `` | 搜尋 | |
<pre>
<kbd>f</kbd>: 擷取遠端
<kbd>n</kbd>: 新增遠端
<kbd>d</kbd>: 移除遠端
<kbd>e</kbd>: 編輯遠端
<kbd>/</kbd>: Filter the current view by text
</pre>
## 遠端分支
| Key | Action | Info |
|-----|--------|-------------|
| `` <c-o> `` | 複製分支名稱到剪貼簿 | |
| `` <space> `` | 檢出 | Checkout a new local branch based on the selected remote branch, or the remote branch as a detached head. |
| `` n `` | 新分支 | |
| `` M `` | 合併到當前檢出的分支 | Merge selected branch into currently checked out branch. |
| `` r `` | 將已檢出的分支變基至此分支 | Rebase the checked-out branch onto the selected branch. |
| `` d `` | Delete | Delete the remote branch from the remote. |
| `` u `` | Set as upstream | 將此分支設為當前分支之上游 |
| `` s `` | Sort order | |
| `` g `` | 檢視重設選項 | View reset options (soft/mixed/hard) for resetting onto selected item. |
| `` <enter> `` | 檢視提交 | |
| `` w `` | 檢視工作目錄選項 | |
| `` / `` | 搜尋 | |
<pre>
<kbd>&lt;c-o&gt;</kbd>: 複製分支名稱到剪貼簿
<kbd>&lt;space&gt;</kbd>: 檢出
<kbd>n</kbd>: 新分支
<kbd>M</kbd>: 合併到當前檢出的分支
<kbd>r</kbd>: 將已檢出的分支變基至此分支
<kbd>d</kbd>: Delete remote tag
<kbd>u</kbd>: 將此分支設為當前分支之上游
<kbd>s</kbd>: Sort order
<kbd>g</kbd>: 檢視重設選項
<kbd>w</kbd>: View worktree options
<kbd>&lt;enter&gt;</kbd>: 檢視提交
<kbd>/</kbd>: Filter the current view by text
</pre>

32
go.mod
View File

@@ -2,21 +2,24 @@ module github.com/jesseduffield/lazygit
go 1.21
toolchain go1.21.0
require (
github.com/adrg/xdg v0.4.0
github.com/OpenPeeDeeP/xdg v1.0.0
github.com/atotto/clipboard v0.1.4
github.com/aybabtme/humanlog v0.4.1
github.com/charmbracelet/glamour v0.6.0
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/creack/pty v1.1.11
github.com/fsmiamoto/git-todo-parser v0.0.5
github.com/gdamore/tcell/v2 v2.7.4
github.com/gdamore/tcell/v2 v2.7.1-0.20240103180601-96e29905643b
github.com/go-errors/errors v1.5.1
github.com/gookit/color v1.4.2
github.com/imdario/mergo v0.3.11
github.com/integrii/flaggy v1.4.0
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de
github.com/jesseduffield/gocui v0.3.1-0.20240103192639-2874168c14db
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
@@ -43,9 +46,13 @@ require (
)
require (
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/aymanbagabas/go-osc52 v1.0.3 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/fatih/color v1.9.0 // indirect
github.com/gdamore/encoding v1.0.0 // indirect
@@ -54,6 +61,7 @@ require (
github.com/go-logfmt/logfmt v0.5.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/invopop/jsonschema v0.10.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect
@@ -62,20 +70,26 @@ require (
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.11 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/microcosm-cc/bluemonday v1.0.21 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.13.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/ginkgo v1.10.3 // indirect
github.com/onsi/gomega v1.7.1 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/xanzy/ssh-agent v0.2.1 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
github.com/yuin/goldmark v1.5.2 // indirect
github.com/yuin/goldmark-emoji v1.0.1 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/term v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)

73
go.sum
View File

@@ -38,10 +38,12 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
github.com/OpenPeeDeeP/xdg v1.0.0 h1:UDLmNjCGFZZCaVMB74DqYEtXkHxnTxcr4FeJVF9uCn8=
github.com/OpenPeeDeeP/xdg v1.0.0/go.mod h1:tMoSueLQlMf0TCldjrJLNIjAc5qAOIcHt5REi88/Ygo=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
@@ -51,11 +53,17 @@ github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn
github.com/aybabtme/humanlog v0.4.1 h1:D8d9um55rrthJsP8IGSHBcti9lTb/XknmDAX6Zy8tek=
github.com/aybabtme/humanlog v0.4.1/go.mod h1:B0bnQX4FTSU3oftPMTTPvENCy8LqixLDvYJA9TUCAGo=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg=
github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM273bISc=
github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
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=
@@ -72,6 +80,8 @@ github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -89,8 +99,8 @@ github.com/fsmiamoto/git-todo-parser v0.0.5/go.mod h1:B+AgTbNE2BARvJqzXygThzqxLI
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
github.com/gdamore/tcell/v2 v2.7.1-0.20240103180601-96e29905643b h1:VkiXff8uJUkhjcxcLwwzQLYBCc+k5tJeOVx4W0qMYTk=
github.com/gdamore/tcell/v2 v2.7.1-0.20240103180601-96e29905643b/go.mod h1:hl/KtAANGBecfIPxk+FzKvThTqI84oplgbPEmVX60b8=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
@@ -168,6 +178,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
@@ -187,8 +199,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de h1:2ww1SWgakihE8hFxZ7L3agVeGpA6qwW5vdnhFUXKMQo=
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
github.com/jesseduffield/gocui v0.3.1-0.20240103192639-2874168c14db h1:ihJdYk85/XQLGiG3b6m8P2z+RUohRMtPmX74YR9IT8s=
github.com/jesseduffield/gocui v0.3.1-0.20240103192639-2874168c14db/go.mod h1:9zkyjnUmdL3+sUknJrQy/3HweUu8mVln/3J2wRF/l8M=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
@@ -234,18 +246,31 @@ github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mgutz/str v1.2.0 h1:4IzWSdIz9qPQWLfKZ0rJcV0jcUDpxvP4JVZ4GXQyvSw=
github.com/mgutz/str v1.2.0/go.mod h1:w1v0ofgLaJdoD0HpQ3fycxKD1WtxpjSo151pK/31q6w=
github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0=
github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -261,10 +286,11 @@ github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
@@ -285,6 +311,7 @@ github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKk
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -310,6 +337,10 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.5.2 h1:ALmeCk/px5FSm1MAcFBAsVKZjDuMVj8Tm7FFIlMJnqU=
github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os=
github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -325,8 +356,9 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -398,9 +430,10 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -466,19 +499,21 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
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=

View File

@@ -23,7 +23,6 @@ import (
"github.com/jesseduffield/lazygit/pkg/env"
"github.com/jesseduffield/lazygit/pkg/gui"
"github.com/jesseduffield/lazygit/pkg/i18n"
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
"github.com/jesseduffield/lazygit/pkg/logs"
"github.com/jesseduffield/lazygit/pkg/updates"
)
@@ -43,7 +42,7 @@ func Run(
common *common.Common,
startArgs appTypes.StartArgs,
) {
app, err := NewApp(config, startArgs.IntegrationTest, common)
app, err := NewApp(config, common)
if err == nil {
err = app.Run(startArgs)
@@ -95,7 +94,7 @@ func newLogger(cfg config.AppConfigurer) *logrus.Entry {
}
// NewApp bootstrap a new application
func NewApp(config config.AppConfigurer, test integrationTypes.IntegrationTest, common *common.Common) (*App, error) {
func NewApp(config config.AppConfigurer, common *common.Common) (*App, error) {
app := &App{
closers: []io.Closer{},
Config: config,
@@ -129,7 +128,7 @@ func NewApp(config config.AppConfigurer, test integrationTypes.IntegrationTest,
showRecentRepos = true
}
app.Gui, err = gui.NewGui(common, config, gitVersion, updater, showRecentRepos, dirName, test)
app.Gui, err = gui.NewGui(common, config, gitVersion, updater, showRecentRepos, dirName)
if err != nil {
return app, err
}

View File

@@ -34,8 +34,8 @@ const (
DaemonKindExitImmediately
DaemonKindCherryPick
DaemonKindMoveTodosUp
DaemonKindMoveTodosDown
DaemonKindMoveTodoUp
DaemonKindMoveTodoDown
DaemonKindInsertBreak
DaemonKindChangeTodoActions
DaemonKindMoveFixupCommitDown
@@ -56,8 +56,8 @@ func getInstruction() Instruction {
DaemonKindCherryPick: deserializeInstruction[*CherryPickCommitsInstruction],
DaemonKindChangeTodoActions: deserializeInstruction[*ChangeTodoActionsInstruction],
DaemonKindMoveFixupCommitDown: deserializeInstruction[*MoveFixupCommitDownInstruction],
DaemonKindMoveTodosUp: deserializeInstruction[*MoveTodosUpInstruction],
DaemonKindMoveTodosDown: deserializeInstruction[*MoveTodosDownInstruction],
DaemonKindMoveTodoUp: deserializeInstruction[*MoveTodoUpInstruction],
DaemonKindMoveTodoDown: deserializeInstruction[*MoveTodoDownInstruction],
DaemonKindInsertBreak: deserializeInstruction[*InsertBreakInstruction],
}
@@ -208,15 +208,13 @@ func (self *ChangeTodoActionsInstruction) SerializedInstructions() string {
func (self *ChangeTodoActionsInstruction) run(common *common.Common) error {
return handleInteractiveRebase(common, func(path string) error {
changes := lo.Map(self.Changes, func(c ChangeTodoAction, _ int) utils.TodoChange {
return utils.TodoChange{
Sha: c.Sha,
OldAction: todo.Pick,
NewAction: c.NewAction,
for _, c := range self.Changes {
if err := utils.EditRebaseTodo(path, c.Sha, todo.Pick, c.NewAction, getCommentChar()); err != nil {
return err
}
})
}
return utils.EditRebaseTodo(path, changes, getCommentChar())
return nil
})
}
@@ -249,65 +247,51 @@ func (self *MoveFixupCommitDownInstruction) run(common *common.Common) error {
})
}
type MoveTodosUpInstruction struct {
Shas []string
type MoveTodoUpInstruction struct {
Sha string
}
func NewMoveTodosUpInstruction(shas []string) Instruction {
return &MoveTodosUpInstruction{
Shas: shas,
func NewMoveTodoUpInstruction(sha string) Instruction {
return &MoveTodoUpInstruction{
Sha: sha,
}
}
func (self *MoveTodosUpInstruction) Kind() DaemonKind {
return DaemonKindMoveTodosUp
func (self *MoveTodoUpInstruction) Kind() DaemonKind {
return DaemonKindMoveTodoUp
}
func (self *MoveTodosUpInstruction) SerializedInstructions() string {
func (self *MoveTodoUpInstruction) SerializedInstructions() string {
return serializeInstruction(self)
}
func (self *MoveTodosUpInstruction) run(common *common.Common) error {
todosToMove := lo.Map(self.Shas, func(sha string, _ int) utils.Todo {
return utils.Todo{
Sha: sha,
Action: todo.Pick,
}
})
func (self *MoveTodoUpInstruction) run(common *common.Common) error {
return handleInteractiveRebase(common, func(path string) error {
return utils.MoveTodosUp(path, todosToMove, getCommentChar())
return utils.MoveTodoUp(path, self.Sha, todo.Pick, getCommentChar())
})
}
type MoveTodosDownInstruction struct {
Shas []string
type MoveTodoDownInstruction struct {
Sha string
}
func NewMoveTodosDownInstruction(shas []string) Instruction {
return &MoveTodosDownInstruction{
Shas: shas,
func NewMoveTodoDownInstruction(sha string) Instruction {
return &MoveTodoDownInstruction{
Sha: sha,
}
}
func (self *MoveTodosDownInstruction) Kind() DaemonKind {
return DaemonKindMoveTodosDown
func (self *MoveTodoDownInstruction) Kind() DaemonKind {
return DaemonKindMoveTodoDown
}
func (self *MoveTodosDownInstruction) SerializedInstructions() string {
func (self *MoveTodoDownInstruction) SerializedInstructions() string {
return serializeInstruction(self)
}
func (self *MoveTodosDownInstruction) run(common *common.Common) error {
todosToMove := lo.Map(self.Shas, func(sha string, _ int) utils.Todo {
return utils.Todo{
Sha: sha,
Action: todo.Pick,
}
})
func (self *MoveTodoDownInstruction) run(common *common.Common) error {
return handleInteractiveRebase(common, func(path string) error {
return utils.MoveTodosDown(path, todosToMove, getCommentChar())
return utils.MoveTodoDown(path, self.Sha, todo.Pick, getCommentChar())
})
}

View File

@@ -14,6 +14,7 @@ import (
"fmt"
"log"
"os"
"strings"
"github.com/jesseduffield/generics/maps"
"github.com/jesseduffield/lazycore/pkg/utils"
@@ -60,7 +61,7 @@ func generateAtDir(cheatsheetDir string) {
if err != nil {
log.Fatal(err)
}
mApp, _ := app.NewApp(mConfig, nil, common)
mApp, _ := app.NewApp(mConfig, common)
path := cheatsheetDir + "/Keybindings_" + lang + ".md"
file, err := os.Create(path)
if err != nil {
@@ -190,11 +191,11 @@ func formatSections(tr *i18n.TranslationSet, bindingSections []*bindingSection)
for _, section := range bindingSections {
content += formatTitle(section.title)
content += "| Key | Action | Info |\n"
content += "|-----|--------|-------------|\n"
content += "<pre>\n"
for _, binding := range section.bindings {
content += formatBinding(binding)
}
content += "</pre>\n"
}
return content
@@ -205,15 +206,19 @@ func formatTitle(title string) string {
}
func formatBinding(binding *types.Binding) string {
action := keybindings.LabelFromKey(binding.Key)
description := binding.Description
result := fmt.Sprintf(" <kbd>%s</kbd>: %s", escapeAngleBrackets(keybindings.LabelFromKey(binding.Key)), binding.Description)
if binding.Alternative != "" {
action += fmt.Sprintf(" (%s)", binding.Alternative)
result += fmt.Sprintf(" (%s)", binding.Alternative)
}
result += "\n"
// Use backticks for keyboard keys. Two backticks are needed with an inner space
// to escape a key that is itself a backtick.
return fmt.Sprintf("| `` %s `` | %s | %s |\n", action, description, binding.Tooltip)
return result
}
func escapeAngleBrackets(str string) string {
result := strings.ReplaceAll(str, ">", "&gt;")
result = strings.ReplaceAll(result, "<", "&lt;")
return result
}
func italicize(str string) string {

View File

@@ -2,9 +2,12 @@ package commands
import (
"os"
"path"
"path/filepath"
"strings"
"github.com/go-errors/errors"
"github.com/spf13/afero"
gogit "github.com/jesseduffield/go-git/v5"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
@@ -12,6 +15,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/commands/patch"
"github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/env"
"github.com/jesseduffield/lazygit/pkg/utils"
)
@@ -60,16 +64,41 @@ func NewGitCommand(
osCommand *oscommands.OSCommand,
gitConfig git_config.IGitConfig,
) (*GitCommand, error) {
repoPaths, err := git_commands.GetRepoPaths(osCommand.Cmd, version)
if err != nil {
return nil, errors.Errorf("Error getting repo paths: %v", err)
}
err = os.Chdir(repoPaths.WorktreePath())
currentPath, err := os.Getwd()
if err != nil {
return nil, utils.WrapError(err)
}
// converting to forward slashes for the sake of windows (which uses backwards slashes). We want everything
// to have forward slashes internally
currentPath = filepath.ToSlash(currentPath)
gitDir := env.GetGitDirEnv()
if gitDir != "" {
// we've been given the git directory explicitly so no need to navigate to it
_, err := cmn.Fs.Stat(gitDir)
if err != nil {
return nil, utils.WrapError(err)
}
} else {
// we haven't been given the git dir explicitly so we assume it's in the current working directory as `.git/` (or an ancestor directory)
rootDirectory, err := findWorktreeRoot(cmn.Fs, currentPath)
if err != nil {
return nil, utils.WrapError(err)
}
currentPath = rootDirectory
err = os.Chdir(rootDirectory)
if err != nil {
return nil, utils.WrapError(err)
}
}
repoPaths, err := git_commands.GetRepoPaths(cmn.Fs, currentPath)
if err != nil {
return nil, errors.Errorf("Error getting repo paths: %v", err)
}
repository, err := gogit.PlainOpenWithOptions(
repoPaths.WorktreeGitDirPath(),
&gogit.PlainOpenOptions{DetectDotGit: false, EnableDotGitCommonDir: true},
@@ -179,6 +208,32 @@ func NewGitCommandAux(
}
}
// this returns the root of the current worktree. So if you start lazygit from within
// a subdirectory of the worktree, it will start in the context of the root of that worktree
func findWorktreeRoot(fs afero.Fs, currentPath string) (string, error) {
for {
// we don't care if .git is a directory or a file: either is okay.
_, err := fs.Stat(path.Join(currentPath, ".git"))
if err == nil {
return currentPath, nil
}
if !os.IsNotExist(err) {
return "", utils.WrapError(err)
}
currentPath = path.Dir(currentPath)
atRoot := currentPath == path.Dir(currentPath)
if atRoot {
// we should never really land here: the code that creates GitCommand should
// verify we're in a git directory
return "", errors.New("Must open lazygit in a git repository")
}
}
}
func VerifyInGitRepo(osCommand *oscommands.OSCommand) error {
return osCommand.Cmd.New(git_commands.NewGitCmd("rev-parse").Arg("--git-dir").ToArgv()).DontLog().Run()
}

View File

@@ -28,17 +28,6 @@ func (self *BranchCommands) New(name string, base string) error {
return self.cmd.New(cmdArgs).Run()
}
// CreateWithUpstream creates a new branch with a given upstream, but without
// checking it out
func (self *BranchCommands) CreateWithUpstream(name string, upstream string) error {
cmdArgs := NewGitCmd("branch").
Arg("--track").
Arg(name, upstream).
ToArgv()
return self.cmd.New(cmdArgs).Run()
}
// CurrentBranchInfo get the current branch information.
func (self *BranchCommands) CurrentBranchInfo() (BranchInfo, error) {
branchName, err := self.cmd.New(
@@ -221,7 +210,7 @@ type MergeOpts struct {
func (self *BranchCommands) Merge(branchName string, opts MergeOpts) error {
cmdArgs := NewGitCmd("merge").
Arg("--no-edit").
Arg(strings.Fields(self.UserConfig.Git.Merging.Args)...).
ArgIf(self.UserConfig.Git.Merging.Args != "", self.UserConfig.Git.Merging.Args).
ArgIf(opts.FastForwardOnly, "--ff-only").
Arg(branchName).
ToArgv()

View File

@@ -127,19 +127,6 @@ func TestBranchMerge(t *testing.T) {
branchName: "mybranch",
expected: []string{"merge", "--no-edit", "--merging-args", "mybranch"},
},
{
testName: "multiple merging args",
userConfig: &config.UserConfig{
Git: config.GitConfig{
Merging: config.MergingConfig{
Args: "--arg1 --arg2", // it's up to the user what they put here
},
},
},
opts: MergeOpts{},
branchName: "mybranch",
expected: []string{"merge", "--no-edit", "--arg1", "--arg2", "mybranch"},
},
{
testName: "fast forward only",
userConfig: &config.UserConfig{},

View File

@@ -39,13 +39,13 @@ func (self *CommitCommands) SetAuthor(value string) error {
}
// Add a commit's coauthor using Github/Gitlab Co-authored-by metadata. Value is expected to be of the form 'Name <Email>'
func (self *CommitCommands) AddCoAuthor(sha string, author string) error {
func (self *CommitCommands) AddCoAuthor(sha string, value string) error {
message, err := self.GetCommitMessage(sha)
if err != nil {
return err
}
message = AddCoAuthorToMessage(message, author)
message = message + fmt.Sprintf("\nCo-authored-by: %s", value)
cmdArgs := NewGitCmd("commit").
Arg("--allow-empty", "--amend", "--only", "-m", message).
@@ -54,25 +54,6 @@ func (self *CommitCommands) AddCoAuthor(sha string, author string) error {
return self.cmd.New(cmdArgs).Run()
}
func AddCoAuthorToMessage(message string, author string) string {
subject, body, _ := strings.Cut(message, "\n")
return strings.TrimSpace(subject) + "\n\n" + AddCoAuthorToDescription(strings.TrimSpace(body), author)
}
func AddCoAuthorToDescription(description string, author string) string {
if description != "" {
lines := strings.Split(description, "\n")
if strings.HasPrefix(lines[len(lines)-1], "Co-authored-by:") {
description += "\n"
} else {
description += "\n\n"
}
}
return description + fmt.Sprintf("Co-authored-by: %s", author)
}
// ResetToCommit reset to commit
func (self *CommitCommands) ResetToCommit(sha string, strength string, envVars []string) error {
cmdArgs := NewGitCmd("reset").Arg("--"+strength, sha).ToArgv()
@@ -161,7 +142,7 @@ func (self *CommitCommands) GetCommitMessage(commitSha string) (string, error) {
ToArgv()
message, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
return strings.ReplaceAll(strings.TrimSpace(message), "\r\n", "\n"), err
return strings.TrimSpace(message), err
}
func (self *CommitCommands) GetCommitSubject(commitSha string) (string, error) {
@@ -258,7 +239,6 @@ func (self *CommitCommands) ShowCmdObj(sha string, filterPath string) oscommands
extDiffCmd := self.UserConfig.Git.Paging.ExternalDiffCommand
cmdArgs := NewGitCmd("show").
Config("diff.noprefix=false").
ConfigIf(extDiffCmd != "", "diff.external="+extDiffCmd).
ArgIfElse(extDiffCmd != "", "--ext-diff", "--no-ext-diff").
Arg("--submodule").
@@ -270,7 +250,6 @@ func (self *CommitCommands) ShowCmdObj(sha string, filterPath string) oscommands
Arg(sha).
ArgIf(self.AppState.IgnoreWhitespaceInDiffView, "--ignore-all-space").
ArgIf(filterPath != "", "--", filterPath).
Dir(self.repoPaths.worktreePath).
ToArgv()
return self.cmd.New(cmdArgs).DontLog()
@@ -297,21 +276,6 @@ func (self *CommitCommands) CreateFixupCommit(sha string) error {
return self.cmd.New(cmdArgs).Run()
}
// CreateAmendCommit creates a commit that changes the commit message of a previous commit
func (self *CommitCommands) CreateAmendCommit(originalSubject, newSubject, newDescription string, includeFileChanges bool) error {
description := newSubject
if newDescription != "" {
description += "\n\n" + newDescription
}
cmdArgs := NewGitCmd("commit").
Arg("-m", "amend! "+originalSubject).
Arg("-m", description).
ArgIf(!includeFileChanges, "--only", "--allow-empty").
ToArgv()
return self.cmd.New(cmdArgs).Run()
}
// a value of 0 means the head commit, 1 is the parent commit, etc
func (self *CommitCommands) GetCommitMessageFromHistory(value int) (string, error) {
cmdArgs := NewGitCmd("log").Arg("-1", fmt.Sprintf("--skip=%d", value), "--pretty=%H").

View File

@@ -24,7 +24,6 @@ func NewCommitFileLoader(common *common.Common, cmd oscommands.ICmdObjBuilder) *
// GetFilesInDiff get the specified commit files
func (self *CommitFileLoader) GetFilesInDiff(from string, to string, reverse bool) ([]*models.CommitFile, error) {
cmdArgs := NewGitCmd("diff").
Config("diff.noprefix=false").
Arg("--submodule").
Arg("--no-ext-diff").
Arg("--name-status").

View File

@@ -64,7 +64,6 @@ func NewCommitLoader(
type GetCommitsOptions struct {
Limit bool
FilterPath string
FilterAuthor string
IncludeRebaseCommits bool
RefName string // e.g. "HEAD" or "my_branch"
RefForPushedStatus string // the ref to use for determining pushed/unpushed status
@@ -254,7 +253,10 @@ func (self *CommitLoader) extractCommitFromLine(line string, showDivergence bool
}
func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode) ([]*models.Commit, error) {
commits := self.getRebasingCommits(rebaseMode)
commits, err := self.getRebasingCommits(rebaseMode)
if err != nil {
return nil, err
}
if len(commits) == 0 {
return nil, nil
@@ -275,7 +277,7 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode
).DontLog()
fullCommits := map[string]*models.Commit{}
err := cmdObj.RunAndProcessLines(func(line string) (bool, error) {
err = cmdObj.RunAndProcessLines(func(line string) (bool, error) {
commit := self.extractCommitFromLine(line, false)
fullCommits[commit.Sha] = commit
return false, nil
@@ -311,20 +313,73 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode
}
// getRebasingCommits obtains the commits that we're in the process of rebasing
func (self *CommitLoader) getRebasingCommits(rebaseMode enums.RebaseMode) ([]*models.Commit, error) {
switch rebaseMode {
case enums.REBASE_MODE_MERGING:
return self.getNormalRebasingCommits()
case enums.REBASE_MODE_INTERACTIVE:
return self.getInteractiveRebasingCommits()
default:
return nil, nil
}
}
func (self *CommitLoader) getNormalRebasingCommits() ([]*models.Commit, error) {
rewrittenCount := 0
bytesContent, err := self.readFile(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-apply/rewritten"))
if err == nil {
content := string(bytesContent)
rewrittenCount = len(strings.Split(content, "\n"))
}
// we know we're rebasing, so lets get all the files whose names have numbers
commits := []*models.Commit{}
err = self.walkFiles(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-apply"), func(path string, f os.FileInfo, err error) error {
if rewrittenCount > 0 {
rewrittenCount--
return nil
}
if err != nil {
return err
}
re := regexp.MustCompile(`^\d+$`)
if !re.MatchString(f.Name()) {
return nil
}
bytesContent, err := self.readFile(path)
if err != nil {
return err
}
content := string(bytesContent)
commit := self.commitFromPatch(content)
commits = append([]*models.Commit{commit}, commits...)
return nil
})
if err != nil {
return nil, err
}
return commits, nil
}
// git-rebase-todo example:
// pick ac446ae94ee560bdb8d1d057278657b251aaef17 ac446ae
// pick afb893148791a2fbd8091aeb81deba4930c73031 afb8931
func (self *CommitLoader) getRebasingCommits(rebaseMode enums.RebaseMode) []*models.Commit {
if rebaseMode != enums.REBASE_MODE_INTERACTIVE {
return nil
}
// git-rebase-todo.backup example:
// pick 49cbba374296938ea86bbd4bf4fee2f6ba5cccf6 third commit on master
// pick ac446ae94ee560bdb8d1d057278657b251aaef17 blah commit on master
// pick afb893148791a2fbd8091aeb81deba4930c73031 fourth commit on master
// getInteractiveRebasingCommits takes our git-rebase-todo and our git-rebase-todo.backup files
// and extracts out the sha and names of commits that we still have to go
// in the rebase:
func (self *CommitLoader) getInteractiveRebasingCommits() ([]*models.Commit, error) {
bytesContent, err := self.readFile(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo"))
if err != nil {
self.Log.Error(fmt.Sprintf("error occurred reading git-rebase-todo: %s", err.Error()))
// we assume an error means the file doesn't exist so we just return
return nil
return nil, nil
}
commits := []*models.Commit{}
@@ -332,7 +387,7 @@ func (self *CommitLoader) getRebasingCommits(rebaseMode enums.RebaseMode) []*mod
todos, err := todo.Parse(bytes.NewBuffer(bytesContent), self.config.GetCoreCommentChar())
if err != nil {
self.Log.Error(fmt.Sprintf("error occurred while parsing git-rebase-todo file: %s", err.Error()))
return nil
return nil, nil
}
// See if the current commit couldn't be applied because it conflicted; if
@@ -348,7 +403,7 @@ func (self *CommitLoader) getRebasingCommits(rebaseMode enums.RebaseMode) []*mod
for _, t := range todos {
if t.Command == todo.UpdateRef {
t.Msg = t.Ref
t.Msg = strings.TrimPrefix(t.Ref, "refs/heads/")
} else if t.Commit == "" {
// Command does not have a commit associated, skip
continue
@@ -361,7 +416,7 @@ func (self *CommitLoader) getRebasingCommits(rebaseMode enums.RebaseMode) []*mod
})
}
return commits
return commits, nil
}
func (self *CommitLoader) getConflictedCommit(todos []todo.Todo) string {
@@ -451,6 +506,22 @@ func (self *CommitLoader) getConflictedCommitImpl(todos []todo.Todo, doneTodos [
return lastTodo.Commit
}
// assuming the file starts like this:
// From e93d4193e6dd45ca9cf3a5a273d7ba6cd8b8fb20 Mon Sep 17 00:00:00 2001
// From: Lazygit Tester <test@example.com>
// Date: Wed, 5 Dec 2018 21:03:23 +1100
// Subject: second commit on master
func (self *CommitLoader) commitFromPatch(content string) *models.Commit {
lines := strings.Split(content, "\n")
sha := strings.Split(lines[0], " ")[1]
name := strings.TrimPrefix(lines[3], "Subject: ")
return &models.Commit{
Sha: sha,
Name: name,
Status: models.StatusRebasing,
}
}
func setCommitMergedStatuses(ancestor string, commits []*models.Commit) {
if ancestor == "" {
return
@@ -579,7 +650,7 @@ func (self *CommitLoader) getFirstPushedCommit(refName string) (string, error) {
// getLog gets the git log.
func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
gitLogOrder := self.AppState.GitLogOrder
config := self.UserConfig.Git.Log
refSpec := opts.RefName
if opts.RefToShowDivergenceFrom != "" {
@@ -588,12 +659,11 @@ func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
cmdArgs := NewGitCmd("log").
Arg(refSpec).
ArgIf(gitLogOrder != "default", "--"+gitLogOrder).
ArgIf(config.Order != "default", "--"+config.Order).
ArgIf(opts.All, "--all").
Arg("--oneline").
Arg(prettyFormat).
Arg("--abbrev=40").
ArgIf(opts.FilterAuthor != "", "--author="+opts.FilterAuthor).
ArgIf(opts.Limit, "-300").
ArgIf(opts.FilterPath != "", "--follow").
Arg("--no-show-signature").

View File

@@ -10,7 +10,6 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/stretchr/testify/assert"
)
@@ -306,8 +305,7 @@ func TestGetCommits(t *testing.T) {
scenario := scenario
t.Run(scenario.testName, func(t *testing.T) {
common := utils.NewDummyCommon()
common.AppState = &config.AppState{}
common.AppState.GitLogOrder = scenario.logOrder
common.UserConfig.Git.Log.Order = scenario.logOrder
builder := &CommitLoader{
Common: common,

View File

@@ -180,57 +180,6 @@ func TestCommitCreateFixupCommit(t *testing.T) {
}
}
func TestCommitCreateAmendCommit(t *testing.T) {
type scenario struct {
testName string
originalSubject string
newSubject string
newDescription string
includeFileChanges bool
runner *oscommands.FakeCmdObjRunner
}
scenarios := []scenario{
{
testName: "subject only",
originalSubject: "original subject",
newSubject: "new subject",
newDescription: "",
includeFileChanges: true,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"commit", "-m", "amend! original subject", "-m", "new subject"}, "", nil),
},
{
testName: "subject and description",
originalSubject: "original subject",
newSubject: "new subject",
newDescription: "new description",
includeFileChanges: true,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"commit", "-m", "amend! original subject", "-m", "new subject\n\nnew description"}, "", nil),
},
{
testName: "without file changes",
originalSubject: "original subject",
newSubject: "new subject",
newDescription: "",
includeFileChanges: false,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"commit", "-m", "amend! original subject", "-m", "new subject", "--only", "--allow-empty"}, "", nil),
},
}
for _, s := range scenarios {
s := s
t.Run(s.testName, func(t *testing.T) {
instance := buildCommitCommands(commonDeps{runner: s.runner})
err := instance.CreateAmendCommit(s.originalSubject, s.newSubject, s.newDescription, s.includeFileChanges)
assert.NoError(t, err)
s.runner.CheckForMissingCalls()
})
}
}
func TestCommitShowCmdObj(t *testing.T) {
type scenario struct {
testName string
@@ -248,7 +197,7 @@ func TestCommitShowCmdObj(t *testing.T) {
contextSize: 3,
ignoreWhitespace: false,
extDiffCmd: "",
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890"},
expected: []string{"show", "--no-ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890"},
},
{
testName: "Default case with filter path",
@@ -256,7 +205,7 @@ func TestCommitShowCmdObj(t *testing.T) {
contextSize: 3,
ignoreWhitespace: false,
extDiffCmd: "",
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890", "--", "file.txt"},
expected: []string{"show", "--no-ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890", "--", "file.txt"},
},
{
testName: "Show diff with custom context size",
@@ -264,7 +213,7 @@ func TestCommitShowCmdObj(t *testing.T) {
contextSize: 77,
ignoreWhitespace: false,
extDiffCmd: "",
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890"},
expected: []string{"show", "--no-ext-diff", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890"},
},
{
testName: "Show diff, ignoring whitespace",
@@ -272,7 +221,7 @@ func TestCommitShowCmdObj(t *testing.T) {
contextSize: 77,
ignoreWhitespace: true,
extDiffCmd: "",
expected: []string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890", "--ignore-all-space"},
expected: []string{"show", "--no-ext-diff", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890", "--ignore-all-space"},
},
{
testName: "Show diff with external diff command",
@@ -280,7 +229,7 @@ func TestCommitShowCmdObj(t *testing.T) {
contextSize: 3,
ignoreWhitespace: false,
extDiffCmd: "difft --color=always",
expected: []string{"-C", "/path/to/worktree", "-c", "diff.external=difft --color=always", "-c", "diff.noprefix=false", "show", "--ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890"},
expected: []string{"-c", "diff.external=difft --color=always", "show", "--ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890"},
},
}
@@ -294,10 +243,7 @@ func TestCommitShowCmdObj(t *testing.T) {
appState.DiffContextSize = s.contextSize
runner := oscommands.NewFakeRunner(t).ExpectGitArgs(s.expected, "", nil)
repoPaths := RepoPaths{
worktreePath: "/path/to/worktree",
}
instance := buildCommitCommands(commonDeps{userConfig: userConfig, appState: appState, runner: runner, repoPaths: &repoPaths})
instance := buildCommitCommands(commonDeps{userConfig: userConfig, appState: appState, runner: runner})
assert.NoError(t, instance.ShowCmdObj("1234567890", s.filterPath).Run())
runner.CheckForMissingCalls()
@@ -384,70 +330,3 @@ func TestGetCommitMessageFromHistory(t *testing.T) {
})
}
}
func TestAddCoAuthorToMessage(t *testing.T) {
scenarios := []struct {
name string
message string
expectedResult string
}{
{
// This never happens, I think it isn't possible to create a commit
// with an empty message. Just including it for completeness.
name: "Empty message",
message: "",
expectedResult: "\n\nCo-authored-by: John Doe <john@doe.com>",
},
{
name: "Just a subject, no body",
message: "Subject",
expectedResult: "Subject\n\nCo-authored-by: John Doe <john@doe.com>",
},
{
name: "Subject and body",
message: "Subject\n\nBody",
expectedResult: "Subject\n\nBody\n\nCo-authored-by: John Doe <john@doe.com>",
},
{
name: "Body already ending with a Co-authored-by line",
message: "Subject\n\nBody\n\nCo-authored-by: Jane Smith <jane@smith.com>",
expectedResult: "Subject\n\nBody\n\nCo-authored-by: Jane Smith <jane@smith.com>\nCo-authored-by: John Doe <john@doe.com>",
},
}
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
result := AddCoAuthorToMessage(s.message, "John Doe <john@doe.com>")
assert.Equal(t, s.expectedResult, result)
})
}
}
func TestAddCoAuthorToDescription(t *testing.T) {
scenarios := []struct {
name string
description string
expectedResult string
}{
{
name: "Empty description",
description: "",
expectedResult: "Co-authored-by: John Doe <john@doe.com>",
},
{
name: "Non-empty description",
description: "Body",
expectedResult: "Body\n\nCo-authored-by: John Doe <john@doe.com>",
},
{
name: "Description already ending with a Co-authored-by line",
description: "Body\n\nCo-authored-by: Jane Smith <jane@smith.com>",
expectedResult: "Body\n\nCo-authored-by: Jane Smith <jane@smith.com>\nCo-authored-by: John Doe <john@doe.com>",
},
}
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
result := AddCoAuthorToDescription(s.description, "John Doe <john@doe.com>")
assert.Equal(t, s.expectedResult, result)
})
}
}

View File

@@ -14,21 +14,14 @@ func NewDiffCommands(gitCommon *GitCommon) *DiffCommands {
func (self *DiffCommands) DiffCmdObj(diffArgs []string) oscommands.ICmdObj {
return self.cmd.New(
NewGitCmd("diff").
Config("diff.noprefix=false").
Arg("--submodule", "--no-ext-diff", "--color").
Arg(diffArgs...).
Dir(self.repoPaths.worktreePath).
ToArgv(),
NewGitCmd("diff").Arg("--submodule", "--no-ext-diff", "--color").Arg(diffArgs...).ToArgv(),
)
}
func (self *DiffCommands) internalDiffCmdObj(diffArgs ...string) *GitCommandBuilder {
return NewGitCmd("diff").
Config("diff.noprefix=false").
Arg("--no-ext-diff", "--no-color").
Arg(diffArgs...).
Dir(self.repoPaths.worktreePath)
Arg(diffArgs...)
}
func (self *DiffCommands) GetPathDiff(path string, staged bool) (string, error) {
@@ -89,7 +82,6 @@ func (self *DiffCommands) OpenDiffToolCmdObj(opts DiffToolCmdOptions) oscommands
func (self *DiffCommands) DiffIndexCmdObj(diffArgs ...string) oscommands.ICmdObj {
return self.cmd.New(
NewGitCmd("diff-index").
Config("diff.noprefix=false").
Arg("--submodule", "--no-ext-diff", "--no-color", "--patch").
Arg(diffArgs...).ToArgv(),
)

View File

@@ -8,7 +8,6 @@ import (
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)
type FileCommands struct {
@@ -76,21 +75,18 @@ func (self *FileCommands) GetEditCmdStrLegacy(filename string, lineNumber int) (
return utils.ResolvePlaceholderString(editCmdTemplate, templateValues), nil
}
func (self *FileCommands) GetEditCmdStr(filenames []string) (string, bool) {
func (self *FileCommands) GetEditCmdStr(filename string) (string, bool) {
// Legacy support for old config; to be removed at some point
if self.UserConfig.OS.Edit == "" && self.UserConfig.OS.EditCommandTemplate != "" {
// If multiple files are selected, we'll simply edit just the first one.
// It's not worth fixing this for the legacy support.
if cmdStr, err := self.GetEditCmdStrLegacy(filenames[0], 1); err == nil {
if cmdStr, err := self.GetEditCmdStrLegacy(filename, 1); err == nil {
return cmdStr, true
}
}
template, suspend := config.GetEditTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
quotedFilenames := lo.Map(filenames, func(filename string, _ int) string { return self.cmd.Quote(filename) })
templateValues := map[string]string{
"filename": strings.Join(quotedFilenames, " "),
"filename": self.cmd.Quote(filename),
}
cmdStr := utils.ResolvePlaceholderString(template, templateValues)

View File

@@ -177,9 +177,9 @@ func TestEditFileCmdStrLegacy(t *testing.T) {
}
}
func TestEditFilesCmd(t *testing.T) {
func TestEditFileCmd(t *testing.T) {
type scenario struct {
filenames []string
filename string
osConfig config.OSConfig
expectedCmdStr string
suspend bool
@@ -187,13 +187,13 @@ func TestEditFilesCmd(t *testing.T) {
scenarios := []scenario{
{
filenames: []string{"test"},
filename: "test",
osConfig: config.OSConfig{},
expectedCmdStr: `vim -- "test"`,
suspend: true,
},
{
filenames: []string{"test"},
filename: "test",
osConfig: config.OSConfig{
Edit: "nano {{filename}}",
},
@@ -201,21 +201,13 @@ func TestEditFilesCmd(t *testing.T) {
suspend: true,
},
{
filenames: []string{"file/with space"},
filename: "file/with space",
osConfig: config.OSConfig{
EditPreset: "sublime",
},
expectedCmdStr: `subl -- "file/with space"`,
suspend: false,
},
{
filenames: []string{"multiple", "files"},
osConfig: config.OSConfig{
EditPreset: "sublime",
},
expectedCmdStr: `subl -- "multiple" "files"`,
suspend: false,
},
}
for _, s := range scenarios {
@@ -226,7 +218,7 @@ func TestEditFilesCmd(t *testing.T) {
userConfig: userConfig,
})
cmdStr, suspend := instance.GetEditCmdStr(s.filenames)
cmdStr, suspend := instance.GetEditCmdStr(s.filename)
assert.Equal(t, s.expectedCmdStr, cmdStr)
assert.Equal(t, s.suspend, suspend)
}

View File

@@ -60,14 +60,6 @@ func (self *GitCommandBuilder) Dir(path string) *GitCommandBuilder {
return self
}
func (self *GitCommandBuilder) DirIf(condition bool, path string) *GitCommandBuilder {
if condition {
return self.Dir(path)
}
return self
}
// Note, you may prefer to use the Dir method instead of this one
func (self *GitCommandBuilder) Worktree(path string) *GitCommandBuilder {
// worktree arg comes before the command

View File

@@ -321,11 +321,7 @@ func (self *PatchCommands) PullPatchIntoNewCommit(
// only some lines of a range of adjacent added lines. To solve this, we
// get the diff of HEAD and the original commit and then apply that.
func (self *PatchCommands) diffHeadAgainstCommit(commit *models.Commit) (string, error) {
cmdArgs := NewGitCmd("diff").
Config("diff.noprefix=false").
Arg("--no-ext-diff").
Arg("HEAD.." + commit.Sha).
ToArgv()
cmdArgs := NewGitCmd("diff").Arg("HEAD.." + commit.Sha).ToArgv()
return self.cmd.New(cmdArgs).RunWithOutput()
}

View File

@@ -105,49 +105,58 @@ func (self *RebaseCommands) GenericAmend(commits []*models.Commit, index int, f
return self.ContinueRebase()
}
func (self *RebaseCommands) MoveCommitsDown(commits []*models.Commit, startIdx int, endIdx int) error {
baseShaOrRoot := getBaseShaOrRoot(commits, endIdx+2)
func (self *RebaseCommands) MoveCommitDown(commits []*models.Commit, index int) error {
baseShaOrRoot := getBaseShaOrRoot(commits, index+2)
shas := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) string {
return commit.Sha
})
sha := commits[index].Sha
msg := utils.ResolvePlaceholderString(
self.Tr.Log.MoveCommitDown,
map[string]string{
"shortSha": utils.ShortSha(sha),
},
)
self.os.LogCommand(msg, false)
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: baseShaOrRoot,
instruction: daemon.NewMoveTodosDownInstruction(shas),
instruction: daemon.NewMoveTodoDownInstruction(sha),
overrideEditor: true,
}).Run()
}
func (self *RebaseCommands) MoveCommitsUp(commits []*models.Commit, startIdx int, endIdx int) error {
baseShaOrRoot := getBaseShaOrRoot(commits, endIdx+1)
func (self *RebaseCommands) MoveCommitUp(commits []*models.Commit, index int) error {
baseShaOrRoot := getBaseShaOrRoot(commits, index+1)
shas := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) string {
return commit.Sha
})
sha := commits[index].Sha
msg := utils.ResolvePlaceholderString(
self.Tr.Log.MoveCommitUp,
map[string]string{
"shortSha": utils.ShortSha(sha),
},
)
self.os.LogCommand(msg, false)
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
baseShaOrRoot: baseShaOrRoot,
instruction: daemon.NewMoveTodosUpInstruction(shas),
instruction: daemon.NewMoveTodoUpInstruction(sha),
overrideEditor: true,
}).Run()
}
func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx int, endIdx int, action todo.TodoCommand) error {
baseIndex := endIdx + 1
func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, index int, action todo.TodoCommand) error {
baseIndex := index + 1
if action == todo.Squash || action == todo.Fixup {
baseIndex++
}
baseShaOrRoot := getBaseShaOrRoot(commits, baseIndex)
changes := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) daemon.ChangeTodoAction {
return daemon.ChangeTodoAction{
Sha: commit.Sha,
NewAction: action,
}
})
changes := []daemon.ChangeTodoAction{{
Sha: commits[index].Sha,
NewAction: action,
}}
self.os.LogCommand(logTodoChanges(changes), false)
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
@@ -191,7 +200,7 @@ func logTodoChanges(changes []daemon.ChangeTodoAction) string {
changeTodoStr := strings.Join(lo.Map(changes, func(c daemon.ChangeTodoAction, _ int) string {
return fmt.Sprintf("%s:%s", c.Sha, c.NewAction)
}), "\n")
return fmt.Sprintf("Changing TODO actions:\n%s", changeTodoStr)
return fmt.Sprintf("Changing TODO actions: %s", changeTodoStr)
}
type PrepareInteractiveRebaseCommandOpts struct {
@@ -272,59 +281,22 @@ func (self *RebaseCommands) AmendTo(commits []*models.Commit, commitIndex int) e
}).Run()
}
func todoFromCommit(commit *models.Commit) utils.Todo {
if commit.Action == todo.UpdateRef {
return utils.Todo{Ref: commit.Name, Action: commit.Action}
} else {
return utils.Todo{Sha: commit.Sha, Action: commit.Action}
}
}
// Sets the action for the given commits in the git-rebase-todo file
func (self *RebaseCommands) EditRebaseTodo(commits []*models.Commit, action todo.TodoCommand) error {
commitsWithAction := lo.Map(commits, func(commit *models.Commit, _ int) utils.TodoChange {
return utils.TodoChange{
Sha: commit.Sha,
OldAction: commit.Action,
NewAction: action,
}
})
// EditRebaseTodo sets the action for a given rebase commit in the git-rebase-todo file
func (self *RebaseCommands) EditRebaseTodo(commit *models.Commit, action todo.TodoCommand) error {
return utils.EditRebaseTodo(
filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo"),
commitsWithAction,
self.config.GetCoreCommentChar(),
)
filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo"), commit.Sha, commit.Action, action, self.config.GetCoreCommentChar())
}
func (self *RebaseCommands) DeleteUpdateRefTodos(commits []*models.Commit) error {
todosToDelete := lo.Map(commits, func(commit *models.Commit, _ int) utils.Todo {
return todoFromCommit(commit)
})
return utils.DeleteTodos(
filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo"),
todosToDelete,
self.config.GetCoreCommentChar(),
)
}
func (self *RebaseCommands) MoveTodosDown(commits []*models.Commit) error {
// MoveTodoDown moves a rebase todo item down by one position
func (self *RebaseCommands) MoveTodoDown(commit *models.Commit) error {
fileName := filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo")
todosToMove := lo.Map(commits, func(commit *models.Commit, _ int) utils.Todo {
return todoFromCommit(commit)
})
return utils.MoveTodosDown(fileName, todosToMove, self.config.GetCoreCommentChar())
return utils.MoveTodoDown(fileName, commit.Sha, commit.Action, self.config.GetCoreCommentChar())
}
func (self *RebaseCommands) MoveTodosUp(commits []*models.Commit) error {
// MoveTodoDown moves a rebase todo item down by one position
func (self *RebaseCommands) MoveTodoUp(commit *models.Commit) error {
fileName := filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo")
todosToMove := lo.Map(commits, func(commit *models.Commit, _ int) utils.Todo {
return todoFromCommit(commit)
})
return utils.MoveTodosUp(fileName, todosToMove, self.config.GetCoreCommentChar())
return utils.MoveTodoUp(fileName, commit.Sha, commit.Action, self.config.GetCoreCommentChar())
}
// SquashAllAboveFixupCommits squashes all fixup! commits above the given one
@@ -437,25 +409,23 @@ func (self *RebaseCommands) runSkipEditorCommand(cmdObj oscommands.ICmdObj) erro
}
// DiscardOldFileChanges discards changes to a file from an old commit
func (self *RebaseCommands) DiscardOldFileChanges(commits []*models.Commit, commitIndex int, filePaths []string) error {
func (self *RebaseCommands) DiscardOldFileChanges(commits []*models.Commit, commitIndex int, fileName string) error {
if err := self.BeginInteractiveRebaseForCommit(commits, commitIndex, false); err != nil {
return err
}
for _, filePath := range filePaths {
// check if file exists in previous commit (this command returns an error if the file doesn't exist)
cmdArgs := NewGitCmd("cat-file").Arg("-e", "HEAD^:"+filePath).ToArgv()
// check if file exists in previous commit (this command returns an error if the file doesn't exist)
cmdArgs := NewGitCmd("cat-file").Arg("-e", "HEAD^:"+fileName).ToArgv()
if err := self.cmd.New(cmdArgs).Run(); err != nil {
if err := self.os.Remove(filePath); err != nil {
return err
}
if err := self.workingTree.StageFile(filePath); err != nil {
return err
}
} else if err := self.workingTree.CheckoutFile("HEAD^", filePath); err != nil {
if err := self.cmd.New(cmdArgs).Run(); err != nil {
if err := self.os.Remove(fileName); err != nil {
return err
}
if err := self.workingTree.StageFile(fileName); err != nil {
return err
}
} else if err := self.workingTree.CheckoutFile("HEAD^", fileName); err != nil {
return err
}
// amend the commit

View File

@@ -111,7 +111,7 @@ func TestRebaseDiscardOldFileChanges(t *testing.T) {
gitConfigMockResponses map[string]string
commits []*models.Commit
commitIndex int
fileName []string
fileName string
runner *oscommands.FakeCmdObjRunner
test func(error)
}
@@ -122,7 +122,7 @@ func TestRebaseDiscardOldFileChanges(t *testing.T) {
gitConfigMockResponses: nil,
commits: []*models.Commit{},
commitIndex: 0,
fileName: []string{"test999.txt"},
fileName: "test999.txt",
runner: oscommands.NewFakeRunner(t),
test: func(err error) {
assert.Error(t, err)
@@ -133,7 +133,7 @@ func TestRebaseDiscardOldFileChanges(t *testing.T) {
gitConfigMockResponses: map[string]string{"commit.gpgsign": "true"},
commits: []*models.Commit{{Name: "commit", Sha: "123456"}},
commitIndex: 0,
fileName: []string{"test999.txt"},
fileName: "test999.txt",
runner: oscommands.NewFakeRunner(t),
test: func(err error) {
assert.Error(t, err)
@@ -147,7 +147,7 @@ func TestRebaseDiscardOldFileChanges(t *testing.T) {
{Name: "commit2", Sha: "abcdef"},
},
commitIndex: 0,
fileName: []string{"test999.txt"},
fileName: "test999.txt",
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"rebase", "--interactive", "--autostash", "--keep-empty", "--no-autosquash", "--rebase-merges", "abcdef"}, "", nil).
ExpectGitArgs([]string{"cat-file", "-e", "HEAD^:test999.txt"}, "", nil).

View File

@@ -23,7 +23,7 @@ func NewReflogCommitLoader(common *common.Common, cmd oscommands.ICmdObjBuilder)
// GetReflogCommits only returns the new reflog commits since the given lastReflogCommit
// if none is passed (i.e. it's value is nil) then we get all the reflog commits
func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit, filterPath string, filterAuthor string) ([]*models.Commit, bool, error) {
func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit, filterPath string) ([]*models.Commit, bool, error) {
commits := make([]*models.Commit, 0)
cmdArgs := NewGitCmd("log").
@@ -31,7 +31,6 @@ func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit
Arg("-g").
Arg("--abbrev=40").
Arg("--format=%h%x00%ct%x00%gs%x00%p").
ArgIf(filterAuthor != "", "--author="+filterAuthor).
ArgIf(filterPath != "", "--follow", "--", filterPath).
ToArgv()

View File

@@ -25,7 +25,6 @@ func TestGetReflogCommits(t *testing.T) {
runner *oscommands.FakeCmdObjRunner
lastReflogCommit *models.Commit
filterPath string
filterAuthor string
expectedCommits []*models.Commit
expectedOnlyObtainedNew bool
expectedError error
@@ -137,31 +136,6 @@ func TestGetReflogCommits(t *testing.T) {
expectedOnlyObtainedNew: true,
expectedError: nil,
},
{
testName: "when passing filterAuthor",
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-c", "log.showSignature=false", "log", "-g", "--abbrev=40", "--format=%h%x00%ct%x00%gs%x00%p", "--author=John Doe <john@doe.com>"}, reflogOutput, nil),
lastReflogCommit: &models.Commit{
Sha: "c3c4b66b64c97ffeecde",
Name: "checkout: moving from B to A",
Status: models.StatusReflog,
UnixTimestamp: 1643150483,
Parents: []string{"51baa8c1"},
},
filterAuthor: "John Doe <john@doe.com>",
expectedCommits: []*models.Commit{
{
Sha: "c3c4b66b64c97ffeecde",
Name: "checkout: moving from A to B",
Status: models.StatusReflog,
UnixTimestamp: 1643150483,
Parents: []string{"51baa8c1"},
},
},
expectedOnlyObtainedNew: true,
expectedError: nil,
},
{
testName: "when command returns error",
runner: oscommands.NewFakeRunner(t).
@@ -183,7 +157,7 @@ func TestGetReflogCommits(t *testing.T) {
cmd: oscommands.NewDummyCmdObjBuilder(scenario.runner),
}
commits, onlyObtainednew, err := builder.GetReflogCommits(scenario.lastReflogCommit, scenario.filterPath, scenario.filterAuthor)
commits, onlyObtainednew, err := builder.GetReflogCommits(scenario.lastReflogCommit, scenario.filterPath)
assert.Equal(t, scenario.expectedOnlyObtainedNew, onlyObtainednew)
assert.Equal(t, scenario.expectedError, err)
t.Logf("actual commits: \n%s", litter.Sdump(commits))

View File

@@ -1,18 +1,21 @@
package git_commands
import (
"fmt"
ioFs "io/fs"
"os"
"path"
"path/filepath"
"strings"
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/jesseduffield/lazygit/pkg/env"
"github.com/samber/lo"
"github.com/spf13/afero"
)
type RepoPaths struct {
currentPath string
worktreePath string
worktreeGitDirPath string
repoPath string
@@ -20,7 +23,12 @@ type RepoPaths struct {
repoName string
}
var gitPathFormatVersion GitVersion = GitVersion{2, 31, 0, ""}
// Current working directory of the program. Currently, this will always
// be the same as WorktreePath(), but in future we may support running
// lazygit from inside a subdirectory of the worktree.
func (self *RepoPaths) CurrentPath() string {
return self.currentPath
}
// Path to the current worktree. If we're in the main worktree, this will
// be the same as RepoPath()
@@ -57,6 +65,7 @@ func (self *RepoPaths) RepoName() string {
// Returns the repo paths for a typical repo
func MockRepoPaths(currentPath string) *RepoPaths {
return &RepoPaths{
currentPath: currentPath,
worktreePath: currentPath,
worktreeGitDirPath: path.Join(currentPath, ".git"),
repoPath: currentPath,
@@ -66,41 +75,44 @@ func MockRepoPaths(currentPath string) *RepoPaths {
}
func GetRepoPaths(
cmd oscommands.ICmdObjBuilder,
version *GitVersion,
fs afero.Fs,
currentPath string,
) (*RepoPaths, error) {
gitDirOutput, err := callGitRevParse(cmd, version, "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree")
return getRepoPathsAux(afero.NewOsFs(), resolveSymlink, currentPath)
}
func getRepoPathsAux(
fs afero.Fs,
resolveSymlinkFn func(string) (string, error),
currentPath string,
) (*RepoPaths, error) {
worktreePath := currentPath
repoGitDirPath, repoPath, err := getCurrentRepoGitDirPath(fs, resolveSymlinkFn, currentPath)
if err != nil {
return nil, err
return nil, errors.Errorf("failed to get repo git dir path: %v", err)
}
gitDirResults := strings.Split(utils.NormalizeLinefeeds(gitDirOutput), "\n")
worktreePath := gitDirResults[0]
worktreeGitDirPath := gitDirResults[1]
repoGitDirPath := gitDirResults[2]
if version.IsOlderThanVersion(&gitPathFormatVersion) {
repoGitDirPath, err = filepath.Abs(repoGitDirPath)
var worktreeGitDirPath string
if env.GetWorkTreeEnv() != "" {
// This env is set when you pass --work-tree to lazygit. In that case,
// we're not dealing with a linked work-tree, we're dealing with a 'specified'
// worktree (for lack of a better term). In this case, the worktree has no
// .git file and it just contains a bunch of files: it has no idea it's
// pointed to by a bare repo. As such it does not have its own git dir within
// the bare repo's git dir. Instead, we just use the bare repo's git dir.
worktreeGitDirPath = repoGitDirPath
} else {
var err error
worktreeGitDirPath, err = getWorktreeGitDirPath(fs, currentPath)
if err != nil {
return nil, err
return nil, errors.Errorf("failed to get worktree git dir path: %v", err)
}
}
// If we're in a submodule, --show-superproject-working-tree will return
// a value, meaning gitDirResults will be length 4. In that case
// return the worktree path as the repoPath. Otherwise we're in a
// normal repo or a worktree so return the parent of the git common
// dir (repoGitDirPath)
isSubmodule := len(gitDirResults) == 4
var repoPath string
if isSubmodule {
repoPath = worktreePath
} else {
repoPath = path.Dir(repoGitDirPath)
}
repoName := path.Base(repoPath)
return &RepoPaths{
currentPath: currentPath,
worktreePath: worktreePath,
worktreeGitDirPath: worktreeGitDirPath,
repoPath: repoPath,
@@ -109,31 +121,124 @@ func GetRepoPaths(
}, nil
}
func callGitRevParse(
cmd oscommands.ICmdObjBuilder,
version *GitVersion,
gitRevArgs ...string,
) (string, error) {
return callGitRevParseWithDir(cmd, version, "", gitRevArgs...)
// Returns the path of the git-dir for the worktree. For linked worktrees, the worktree has
// a .git file that points to the git-dir (which itself lives in the git-dir
// of the repo)
func getWorktreeGitDirPath(fs afero.Fs, worktreePath string) (string, error) {
// if .git is a file, we're in a linked worktree, otherwise we're in
// the main worktree
dotGitPath := path.Join(worktreePath, ".git")
gitFileInfo, err := fs.Stat(dotGitPath)
if err != nil {
return "", err
}
if gitFileInfo.IsDir() {
return dotGitPath, nil
}
return linkedWorktreeGitDirPath(fs, worktreePath)
}
func callGitRevParseWithDir(
cmd oscommands.ICmdObjBuilder,
version *GitVersion,
dir string,
gitRevArgs ...string,
) (string, error) {
gitRevParse := NewGitCmd("rev-parse").ArgIf(version.IsAtLeastVersion(&gitPathFormatVersion), "--path-format=absolute").Arg(gitRevArgs...)
if dir != "" {
gitRevParse.Dir(dir)
func linkedWorktreeGitDirPath(fs afero.Fs, worktreePath string) (string, error) {
dotGitPath := path.Join(worktreePath, ".git")
gitFileContents, err := afero.ReadFile(fs, dotGitPath)
if err != nil {
return "", err
}
gitCmd := cmd.New(gitRevParse.ToArgv()).DontLog()
res, err := gitCmd.RunWithOutput()
if err != nil {
return "", errors.Errorf("'%s' failed: %v", gitCmd.ToString(), err)
// The file will have `gitdir: /path/to/.git/worktrees/<worktree-name>`
gitDirLine := lo.Filter(strings.Split(string(gitFileContents), "\n"), func(line string, _ int) bool {
return strings.HasPrefix(line, "gitdir: ")
})
if len(gitDirLine) == 0 {
return "", errors.New(fmt.Sprintf("%s is a file which suggests we are in a submodule or a worktree but the file's contents do not contain a gitdir pointing to the actual .git directory", dotGitPath))
}
return strings.TrimSpace(res), nil
gitDir := strings.TrimPrefix(gitDirLine[0], "gitdir: ")
gitDir = filepath.Clean(gitDir)
// For windows support
gitDir = filepath.ToSlash(gitDir)
return gitDir, nil
}
func getCurrentRepoGitDirPath(
fs afero.Fs,
resolveSymlinkFn func(string) (string, error),
currentPath string,
) (string, string, error) {
var unresolvedGitPath string
if env.GetGitDirEnv() != "" {
unresolvedGitPath = env.GetGitDirEnv()
} else {
unresolvedGitPath = path.Join(currentPath, ".git")
}
gitPath, err := resolveSymlinkFn(unresolvedGitPath)
if err != nil {
return "", "", err
}
// check if .git is a file or a directory
gitFileInfo, err := fs.Stat(gitPath)
if err != nil {
return "", "", err
}
if gitFileInfo.IsDir() {
// must be in the main worktree
return gitPath, path.Dir(gitPath), nil
}
// either in a submodule, or worktree
worktreeGitPath, err := linkedWorktreeGitDirPath(fs, currentPath)
if err != nil {
return "", "", errors.Errorf("could not find git dir for %s: %v", currentPath, err)
}
_, err = fs.Stat(worktreeGitPath)
if err != nil {
if os.IsNotExist(err) {
// hardcoding error to get around windows-specific error message
return "", "", errors.Errorf("could not find git dir for %s. %s does not exist", currentPath, worktreeGitPath)
}
return "", "", errors.Errorf("could not find git dir for %s: %v", currentPath, err)
}
// confirm whether the next directory up is the worktrees directory
parent := path.Dir(worktreeGitPath)
if path.Base(parent) == "worktrees" {
gitDirPath := path.Dir(parent)
return gitDirPath, path.Dir(gitDirPath), nil
}
// Unlike worktrees, submodules can be nested arbitrarily deep, so we check
// if the `modules` directory is anywhere up the chain.
if strings.Contains(worktreeGitPath, "/modules/") {
// For submodules, we just return the path directly
return worktreeGitPath, currentPath, nil
}
// If this error causes issues, we could relax the constraint and just always
// return the path
return "", "", errors.Errorf("could not find git dir for %s: the path '%s' is not under `worktrees` or `modules` directories", currentPath, worktreeGitPath)
}
// takes a path containing a symlink and returns the true path
func resolveSymlink(path string) (string, error) {
l, err := os.Lstat(path)
if err != nil {
return "", err
}
if l.Mode()&os.ModeSymlink == 0 {
return path, nil
}
return filepath.EvalSymlinks(path)
}
// Returns the paths of linked worktrees

View File

@@ -1,50 +1,34 @@
package git_commands
import (
"fmt"
"strings"
"testing"
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
)
type (
argFn func() []string
errFn func(getRevParseArgs argFn) error
)
func mockResolveSymlinkFn(p string) (string, error) { return p, nil }
type Scenario struct {
Name string
BeforeFunc func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn)
BeforeFunc func(fs afero.Fs)
Path string
Expected *RepoPaths
Err errFn
Err error
}
func TestGetRepoPaths(t *testing.T) {
func TestGetRepoPathsAux(t *testing.T) {
scenarios := []Scenario{
{
Name: "typical case",
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
BeforeFunc: func(fs afero.Fs) {
// setup for main worktree
expectedOutput := []string{
// --show-toplevel
"/path/to/repo",
// --git-dir
"/path/to/repo/.git",
// --git-common-dir
"/path/to/repo/.git",
// --show-superproject-working-tree
}
runner.ExpectGitArgs(
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree"),
strings.Join(expectedOutput, "\n"),
nil)
_ = fs.MkdirAll("/path/to/repo/.git", 0o755)
},
Path: "/path/to/repo",
Expected: &RepoPaths{
currentPath: "/path/to/repo",
worktreePath: "/path/to/repo",
worktreeGitDirPath: "/path/to/repo/.git",
repoPath: "/path/to/repo",
@@ -53,26 +37,71 @@ func TestGetRepoPaths(t *testing.T) {
},
Err: nil,
},
{
Name: "linked worktree",
BeforeFunc: func(fs afero.Fs) {
// setup for linked worktree
_ = fs.MkdirAll("/path/to/repo/.git/worktrees/worktree1", 0o755)
_ = afero.WriteFile(fs, "/path/to/repo/worktree1/.git", []byte("gitdir: /path/to/repo/.git/worktrees/worktree1"), 0o644)
},
Path: "/path/to/repo/worktree1",
Expected: &RepoPaths{
currentPath: "/path/to/repo/worktree1",
worktreePath: "/path/to/repo/worktree1",
worktreeGitDirPath: "/path/to/repo/.git/worktrees/worktree1",
repoPath: "/path/to/repo",
repoGitDirPath: "/path/to/repo/.git",
repoName: "repo",
},
Err: nil,
},
{
Name: "worktree with trailing separator in path",
BeforeFunc: func(fs afero.Fs) {
// setup for linked worktree
_ = fs.MkdirAll("/path/to/repo/.git/worktrees/worktree1", 0o755)
_ = afero.WriteFile(fs, "/path/to/repo/worktree1/.git", []byte("gitdir: /path/to/repo/.git/worktrees/worktree1/"), 0o644)
},
Path: "/path/to/repo/worktree1",
Expected: &RepoPaths{
currentPath: "/path/to/repo/worktree1",
worktreePath: "/path/to/repo/worktree1",
worktreeGitDirPath: "/path/to/repo/.git/worktrees/worktree1",
repoPath: "/path/to/repo",
repoGitDirPath: "/path/to/repo/.git",
repoName: "repo",
},
Err: nil,
},
{
Name: "worktree .git file missing gitdir directive",
BeforeFunc: func(fs afero.Fs) {
_ = fs.MkdirAll("/path/to/repo/.git/worktrees/worktree2", 0o755)
_ = afero.WriteFile(fs, "/path/to/repo/worktree2/.git", []byte("blah"), 0o644)
},
Path: "/path/to/repo/worktree2",
Expected: nil,
Err: errors.New("failed to get repo git dir path: could not find git dir for /path/to/repo/worktree2: /path/to/repo/worktree2/.git is a file which suggests we are in a submodule or a worktree but the file's contents do not contain a gitdir pointing to the actual .git directory"),
},
{
Name: "worktree .git file gitdir directive points to a non-existing directory",
BeforeFunc: func(fs afero.Fs) {
_ = fs.MkdirAll("/path/to/repo/.git/worktrees/worktree2", 0o755)
_ = afero.WriteFile(fs, "/path/to/repo/worktree2/.git", []byte("gitdir: /nonexistant"), 0o644)
},
Path: "/path/to/repo/worktree2",
Expected: nil,
Err: errors.New("failed to get repo git dir path: could not find git dir for /path/to/repo/worktree2. /nonexistant does not exist"),
},
{
Name: "submodule",
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
expectedOutput := []string{
// --show-toplevel
"/path/to/repo/submodule1",
// --git-dir
"/path/to/repo/.git/modules/submodule1",
// --git-common-dir
"/path/to/repo/.git/modules/submodule1",
// --show-superproject-working-tree
"/path/to/repo",
}
runner.ExpectGitArgs(
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree"),
strings.Join(expectedOutput, "\n"),
nil)
BeforeFunc: func(fs afero.Fs) {
_ = fs.MkdirAll("/path/to/repo/.git/modules/submodule1", 0o755)
_ = afero.WriteFile(fs, "/path/to/repo/submodule1/.git", []byte("gitdir: /path/to/repo/.git/modules/submodule1"), 0o644)
},
Path: "/path/to/repo/submodule1",
Expected: &RepoPaths{
currentPath: "/path/to/repo/submodule1",
worktreePath: "/path/to/repo/submodule1",
worktreeGitDirPath: "/path/to/repo/.git/modules/submodule1",
repoPath: "/path/to/repo/submodule1",
@@ -82,52 +111,49 @@ func TestGetRepoPaths(t *testing.T) {
Err: nil,
},
{
Name: "git rev-parse returns an error",
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
runner.ExpectGitArgs(
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree"),
"",
errors.New("fatal: invalid gitfile format: /path/to/repo/worktree2/.git"))
Name: "submodule in nested directory",
BeforeFunc: func(fs afero.Fs) {
_ = fs.MkdirAll("/path/to/repo/.git/modules/my/submodule1", 0o755)
_ = afero.WriteFile(fs, "/path/to/repo/my/submodule1/.git", []byte("gitdir: /path/to/repo/.git/modules/my/submodule1"), 0o644)
},
Path: "/path/to/repo/worktree2",
Path: "/path/to/repo/my/submodule1",
Expected: &RepoPaths{
currentPath: "/path/to/repo/my/submodule1",
worktreePath: "/path/to/repo/my/submodule1",
worktreeGitDirPath: "/path/to/repo/.git/modules/my/submodule1",
repoPath: "/path/to/repo/my/submodule1",
repoGitDirPath: "/path/to/repo/.git/modules/my/submodule1",
repoName: "submodule1",
},
Err: nil,
},
{
Name: "submodule git dir not under .git/modules",
BeforeFunc: func(fs afero.Fs) {
_ = fs.MkdirAll("/random/submodule1", 0o755)
_ = afero.WriteFile(fs, "/path/to/repo/my/submodule1/.git", []byte("gitdir: /random/submodule1"), 0o644)
},
Path: "/path/to/repo/my/submodule1",
Expected: nil,
Err: func(getRevParseArgs argFn) error {
args := strings.Join(getRevParseArgs(), " ")
return errors.New(
fmt.Sprintf("'git %v --show-toplevel --absolute-git-dir --git-common-dir --show-superproject-working-tree' failed: fatal: invalid gitfile format: /path/to/repo/worktree2/.git", args),
)
},
Err: errors.New("failed to get repo git dir path: could not find git dir for /path/to/repo/my/submodule1: the path '/random/submodule1' is not under `worktrees` or `modules` directories"),
},
}
for _, s := range scenarios {
s := s
t.Run(s.Name, func(t *testing.T) {
runner := oscommands.NewFakeRunner(t)
cmd := oscommands.NewDummyCmdObjBuilder(runner)
fs := afero.NewMemMapFs()
version, err := GetGitVersion(oscommands.NewDummyOSCommand())
if err != nil {
t.Fatal(err)
}
getRevParseArgs := func() []string {
args := []string{"rev-parse"}
if version.IsAtLeast(2, 31, 0) {
args = append(args, "--path-format=absolute")
}
return args
}
// prepare the filesystem for the scenario
s.BeforeFunc(runner, getRevParseArgs)
s.BeforeFunc(fs)
repoPaths, err := GetRepoPaths(cmd, version)
// run the function with the scenario path
repoPaths, err := getRepoPathsAux(fs, mockResolveSymlinkFn, s.Path)
// check the error and the paths
if s.Err != nil {
scenarioErr := s.Err(getRevParseArgs)
assert.Error(t, err)
assert.EqualError(t, err, scenarioErr.Error())
assert.EqualError(t, err, s.Err.Error())
} else {
assert.Nil(t, err)
assert.Equal(t, s.Expected, repoPaths)

View File

@@ -88,7 +88,6 @@ func (self *StashCommands) ShowStashEntryCmdObj(index int) oscommands.ICmdObj {
Arg(fmt.Sprintf("--unified=%d", self.AppState.DiffContextSize)).
ArgIf(self.AppState.IgnoreWhitespaceInDiffView, "--ignore-all-space").
Arg(fmt.Sprintf("stash@{%d}", index)).
Dir(self.repoPaths.worktreePath).
ToArgv()
return self.cmd.New(cmdArgs).DontLog()

View File

@@ -112,21 +112,21 @@ func TestStashStashEntryCmdObj(t *testing.T) {
index: 5,
contextSize: 3,
ignoreWhitespace: false,
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "--color=always", "--unified=3", "stash@{5}"},
expected: []string{"git", "stash", "show", "-p", "--stat", "--color=always", "--unified=3", "stash@{5}"},
},
{
testName: "Show diff with custom context size",
index: 5,
contextSize: 77,
ignoreWhitespace: false,
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "--color=always", "--unified=77", "stash@{5}"},
expected: []string{"git", "stash", "show", "-p", "--stat", "--color=always", "--unified=77", "stash@{5}"},
},
{
testName: "Default case",
index: 5,
contextSize: 3,
ignoreWhitespace: true,
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "--color=always", "--unified=3", "--ignore-all-space", "stash@{5}"},
expected: []string{"git", "stash", "show", "-p", "--stat", "--color=always", "--unified=3", "--ignore-all-space", "stash@{5}"},
},
}
@@ -137,10 +137,7 @@ func TestStashStashEntryCmdObj(t *testing.T) {
appState := &config.AppState{}
appState.IgnoreWhitespaceInDiffView = s.ignoreWhitespace
appState.DiffContextSize = s.contextSize
repoPaths := RepoPaths{
worktreePath: "/path/to/worktree",
}
instance := buildStashCommands(commonDeps{userConfig: userConfig, appState: appState, repoPaths: &repoPaths})
instance := buildStashCommands(commonDeps{userConfig: userConfig, appState: appState})
cmdStr := instance.ShowStashEntryCmdObj(s.index).Args()
assert.Equal(t, s.expected, cmdStr)

View File

@@ -26,12 +26,8 @@ func NewSubmoduleCommands(gitCommon *GitCommon) *SubmoduleCommands {
}
}
func (self *SubmoduleCommands) GetConfigs(parentModule *models.SubmoduleConfig) ([]*models.SubmoduleConfig, error) {
gitModulesPath := ".gitmodules"
if parentModule != nil {
gitModulesPath = filepath.Join(parentModule.FullPath(), gitModulesPath)
}
file, err := os.Open(gitModulesPath)
func (self *SubmoduleCommands) GetConfigs() ([]*models.SubmoduleConfig, error) {
file, err := os.Open(".gitmodules")
if err != nil {
if os.IsNotExist(err) {
return nil, nil
@@ -55,27 +51,21 @@ func (self *SubmoduleCommands) GetConfigs(parentModule *models.SubmoduleConfig)
}
configs := []*models.SubmoduleConfig{}
lastConfigIdx := -1
for scanner.Scan() {
line := scanner.Text()
if name, ok := firstMatch(line, `\[submodule "(.*)"\]`); ok {
configs = append(configs, &models.SubmoduleConfig{
Name: name, ParentModule: parentModule,
})
lastConfigIdx = len(configs) - 1
configs = append(configs, &models.SubmoduleConfig{Name: name})
continue
}
if lastConfigIdx != -1 {
if len(configs) > 0 {
lastConfig := configs[len(configs)-1]
if path, ok := firstMatch(line, `\s*path\s*=\s*(.*)\s*`); ok {
configs[lastConfigIdx].Path = path
nestedConfigs, err := self.GetConfigs(configs[lastConfigIdx])
if err == nil {
configs = append(configs, nestedConfigs...)
}
lastConfig.Path = path
} else if url, ok := firstMatch(line, `\s*url\s*=\s*(.*)\s*`); ok {
configs[lastConfigIdx].Url = url
lastConfig.Url = url
}
}
}
@@ -87,12 +77,12 @@ func (self *SubmoduleCommands) Stash(submodule *models.SubmoduleConfig) error {
// if the path does not exist then it hasn't yet been initialized so we'll swallow the error
// because the intention here is to have no dirty worktree state
if _, err := os.Stat(submodule.Path); os.IsNotExist(err) {
self.Log.Infof("submodule path %s does not exist, returning", submodule.FullPath())
self.Log.Infof("submodule path %s does not exist, returning", submodule.Path)
return nil
}
cmdArgs := NewGitCmd("stash").
Dir(submodule.FullPath()).
Dir(submodule.Path).
Arg("--include-untracked").
ToArgv()
@@ -100,13 +90,8 @@ func (self *SubmoduleCommands) Stash(submodule *models.SubmoduleConfig) error {
}
func (self *SubmoduleCommands) Reset(submodule *models.SubmoduleConfig) error {
parentDir := ""
if submodule.ParentModule != nil {
parentDir = submodule.ParentModule.FullPath()
}
cmdArgs := NewGitCmd("submodule").
Arg("update", "--init", "--force", "--", submodule.Path).
DirIf(parentDir != "", parentDir).
ToArgv()
return self.cmd.New(cmdArgs).Run()
@@ -122,20 +107,6 @@ func (self *SubmoduleCommands) UpdateAll() error {
func (self *SubmoduleCommands) Delete(submodule *models.SubmoduleConfig) error {
// based on https://gist.github.com/myusuf3/7f645819ded92bda6677
if submodule.ParentModule != nil {
wd, err := os.Getwd()
if err != nil {
return err
}
err = os.Chdir(submodule.ParentModule.FullPath())
if err != nil {
return err
}
defer func() { _ = os.Chdir(wd) }()
}
if err := self.cmd.New(
NewGitCmd("submodule").
Arg("deinit", "--force", "--", submodule.Path).ToArgv(),
@@ -170,7 +141,7 @@ func (self *SubmoduleCommands) Delete(submodule *models.SubmoduleConfig) error {
// We may in fact want to use the repo's git dir path but git docs say not to
// mix submodules and worktrees anyway.
return os.RemoveAll(submodule.GitDirPath(self.repoPaths.repoGitDirPath))
return os.RemoveAll(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "modules", submodule.Path))
}
func (self *SubmoduleCommands) Add(name string, path string, url string) error {
@@ -187,24 +158,10 @@ func (self *SubmoduleCommands) Add(name string, path string, url string) error {
return self.cmd.New(cmdArgs).Run()
}
func (self *SubmoduleCommands) UpdateUrl(submodule *models.SubmoduleConfig, newUrl string) error {
if submodule.ParentModule != nil {
wd, err := os.Getwd()
if err != nil {
return err
}
err = os.Chdir(submodule.ParentModule.FullPath())
if err != nil {
return err
}
defer func() { _ = os.Chdir(wd) }()
}
func (self *SubmoduleCommands) UpdateUrl(name string, path string, newUrl string) error {
setUrlCmdStr := NewGitCmd("config").
Arg(
"--file", ".gitmodules", "submodule."+submodule.Name+".url", newUrl,
"--file", ".gitmodules", "submodule."+name+".url", newUrl,
).
ToArgv()
@@ -213,7 +170,7 @@ func (self *SubmoduleCommands) UpdateUrl(submodule *models.SubmoduleConfig, newU
return err
}
syncCmdStr := NewGitCmd("submodule").Arg("sync", "--", submodule.Path).
syncCmdStr := NewGitCmd("submodule").Arg("sync", "--", path).
ToArgv()
if err := self.cmd.New(syncCmdStr).Run(); err != nil {

View File

@@ -57,20 +57,21 @@ func (self *WorkingTreeCommands) UnstageAll() error {
// UnStageFile unstages a file
// we accept an array of filenames for the cases where a file has been renamed i.e.
// we accept the current name and the previous name
func (self *WorkingTreeCommands) UnStageFile(paths []string, tracked bool) error {
if tracked {
return self.UnstageTrackedFiles(paths)
} else {
return self.UnstageUntrackedFiles(paths)
func (self *WorkingTreeCommands) UnStageFile(fileNames []string, reset bool) error {
for _, name := range fileNames {
var cmdArgs []string
if reset {
cmdArgs = NewGitCmd("reset").Arg("HEAD", "--", name).ToArgv()
} else {
cmdArgs = NewGitCmd("rm").Arg("--cached", "--force", "--", name).ToArgv()
}
err := self.cmd.New(cmdArgs).Run()
if err != nil {
return err
}
}
}
func (self *WorkingTreeCommands) UnstageTrackedFiles(paths []string) error {
return self.cmd.New(NewGitCmd("reset").Arg("HEAD", "--").Arg(paths...).ToArgv()).Run()
}
func (self *WorkingTreeCommands) UnstageUntrackedFiles(paths []string) error {
return self.cmd.New(NewGitCmd("rm").Arg("--cached", "--force", "--").Arg(paths...).ToArgv()).Run()
return nil
}
func (self *WorkingTreeCommands) BeforeAndAfterFileForRename(file *models.File) (*models.File, *models.File, error) {
@@ -164,7 +165,6 @@ func (self *WorkingTreeCommands) DiscardAllFileChanges(file *models.File) error
if file.Added {
return self.os.RemoveFile(file.Name)
}
return self.DiscardUnstagedFileChanges(file)
}
@@ -172,8 +172,6 @@ type IFileNode interface {
ForEachFile(cb func(*models.File) error) error
GetFilePathsMatching(test func(*models.File) bool) []string
GetPath() string
// Returns file if the node is not a directory, otherwise returns nil
GetFile() *models.File
}
func (self *WorkingTreeCommands) DiscardAllDirChanges(node IFileNode) error {
@@ -182,24 +180,13 @@ func (self *WorkingTreeCommands) DiscardAllDirChanges(node IFileNode) error {
}
func (self *WorkingTreeCommands) DiscardUnstagedDirChanges(node IFileNode) error {
file := node.GetFile()
if file == nil {
if err := self.RemoveUntrackedDirFiles(node); err != nil {
return err
}
if err := self.RemoveUntrackedDirFiles(node); err != nil {
return err
}
cmdArgs := NewGitCmd("checkout").Arg("--", node.GetPath()).ToArgv()
if err := self.cmd.New(cmdArgs).Run(); err != nil {
return err
}
} else {
if file.Added && !file.HasStagedChanges {
return self.os.RemoveFile(file.Name)
}
if err := self.DiscardUnstagedFileChanges(file); err != nil {
return err
}
cmdArgs := NewGitCmd("checkout").Arg("--", node.GetPath()).ToArgv()
if err := self.cmd.New(cmdArgs).Run(); err != nil {
return err
}
return nil
@@ -220,6 +207,7 @@ func (self *WorkingTreeCommands) RemoveUntrackedDirFiles(node IFileNode) error {
return nil
}
// DiscardUnstagedFileChanges directly
func (self *WorkingTreeCommands) DiscardUnstagedFileChanges(file *models.File) error {
cmdArgs := NewGitCmd("checkout").Arg("--", file.Name).ToArgv()
return self.cmd.New(cmdArgs).Run()
@@ -267,7 +255,6 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain
ArgIf(noIndex, "/dev/null").
Arg(node.GetPath()).
ArgIf(prevPath != "", prevPath).
Dir(self.repoPaths.worktreePath).
ToArgv()
return self.cmd.New(cmdArgs).DontLog()
@@ -291,7 +278,6 @@ func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reve
useExtDiff := extDiffCmd != "" && !plain
cmdArgs := NewGitCmd("diff").
Config("diff.noprefix=false").
ConfigIf(useExtDiff, "diff.external="+extDiffCmd).
ArgIfElse(useExtDiff, "--ext-diff", "--no-ext-diff").
Arg("--submodule").
@@ -304,7 +290,6 @@ func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reve
ArgIf(!plain && self.AppState.IgnoreWhitespaceInDiffView, "--ignore-all-space").
Arg("--").
Arg(fileName).
Dir(self.repoPaths.worktreePath).
ToArgv()
return self.cmd.New(cmdArgs).DontLog()
@@ -343,7 +328,7 @@ func (self *WorkingTreeCommands) RemoveUntrackedFiles() error {
// ResetAndClean removes all unstaged changes and removes all untracked files
func (self *WorkingTreeCommands) ResetAndClean() error {
submoduleConfigs, err := self.submodule.GetConfigs(nil)
submoduleConfigs, err := self.submodule.GetConfigs()
if err != nil {
return err
}

View File

@@ -231,7 +231,7 @@ func TestWorkingTreeDiff(t *testing.T) {
ignoreWhitespace: false,
contextSize: 3,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--", "test.txt"}, expectedResult, nil),
ExpectGitArgs([]string{"diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--", "test.txt"}, expectedResult, nil),
},
{
testName: "cached",
@@ -245,7 +245,7 @@ func TestWorkingTreeDiff(t *testing.T) {
ignoreWhitespace: false,
contextSize: 3,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--cached", "--", "test.txt"}, expectedResult, nil),
ExpectGitArgs([]string{"diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--cached", "--", "test.txt"}, expectedResult, nil),
},
{
testName: "plain",
@@ -259,7 +259,7 @@ func TestWorkingTreeDiff(t *testing.T) {
ignoreWhitespace: false,
contextSize: 3,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=never", "--", "test.txt"}, expectedResult, nil),
ExpectGitArgs([]string{"diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=never", "--", "test.txt"}, expectedResult, nil),
},
{
testName: "File not tracked and file has no staged changes",
@@ -273,7 +273,7 @@ func TestWorkingTreeDiff(t *testing.T) {
ignoreWhitespace: false,
contextSize: 3,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--no-index", "--", "/dev/null", "test.txt"}, expectedResult, nil),
ExpectGitArgs([]string{"diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--no-index", "--", "/dev/null", "test.txt"}, expectedResult, nil),
},
{
testName: "Default case (ignore whitespace)",
@@ -287,7 +287,7 @@ func TestWorkingTreeDiff(t *testing.T) {
ignoreWhitespace: true,
contextSize: 3,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--ignore-all-space", "--", "test.txt"}, expectedResult, nil),
ExpectGitArgs([]string{"diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--ignore-all-space", "--", "test.txt"}, expectedResult, nil),
},
{
testName: "Show diff with custom context size",
@@ -301,7 +301,7 @@ func TestWorkingTreeDiff(t *testing.T) {
ignoreWhitespace: false,
contextSize: 17,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=17", "--color=always", "--", "test.txt"}, expectedResult, nil),
ExpectGitArgs([]string{"diff", "--no-ext-diff", "--submodule", "--unified=17", "--color=always", "--", "test.txt"}, expectedResult, nil),
},
}
@@ -312,11 +312,8 @@ func TestWorkingTreeDiff(t *testing.T) {
appState := &config.AppState{}
appState.IgnoreWhitespaceInDiffView = s.ignoreWhitespace
appState.DiffContextSize = s.contextSize
repoPaths := RepoPaths{
worktreePath: "/path/to/worktree",
}
instance := buildWorkingTreeCommands(commonDeps{runner: s.runner, userConfig: userConfig, appState: appState, repoPaths: &repoPaths})
instance := buildWorkingTreeCommands(commonDeps{runner: s.runner, userConfig: userConfig, appState: appState})
result := instance.WorktreeFileDiff(s.file, s.plain, s.cached)
assert.Equal(t, expectedResult, result)
s.runner.CheckForMissingCalls()
@@ -348,7 +345,7 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
ignoreWhitespace: false,
contextSize: 3,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--no-renames", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
ExpectGitArgs([]string{"diff", "--no-ext-diff", "--submodule", "--unified=3", "--no-renames", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
},
{
testName: "Show diff with custom context size",
@@ -359,7 +356,7 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
ignoreWhitespace: false,
contextSize: 123,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--submodule", "--unified=123", "--no-renames", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
ExpectGitArgs([]string{"diff", "--no-ext-diff", "--submodule", "--unified=123", "--no-renames", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
},
{
testName: "Default case (ignore whitespace)",
@@ -370,7 +367,7 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
ignoreWhitespace: true,
contextSize: 3,
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-C", "/path/to/worktree", "-c", "diff.noprefix=false", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--no-renames", "--color=always", "1234567890", "0987654321", "--ignore-all-space", "--", "test.txt"}, expectedResult, nil),
ExpectGitArgs([]string{"diff", "--no-ext-diff", "--submodule", "--unified=3", "--no-renames", "--color=always", "1234567890", "0987654321", "--ignore-all-space", "--", "test.txt"}, expectedResult, nil),
},
}
@@ -381,11 +378,8 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
appState := &config.AppState{}
appState.IgnoreWhitespaceInDiffView = s.ignoreWhitespace
appState.DiffContextSize = s.contextSize
repoPaths := RepoPaths{
worktreePath: "/path/to/worktree",
}
instance := buildWorkingTreeCommands(commonDeps{runner: s.runner, userConfig: userConfig, appState: appState, repoPaths: &repoPaths})
instance := buildWorkingTreeCommands(commonDeps{runner: s.runner, userConfig: userConfig, appState: appState})
result, err := instance.ShowFileDiff(s.from, s.to, s.reverse, "test.txt", s.plain)
assert.NoError(t, err)

View File

@@ -4,7 +4,6 @@ import (
iofs "io/fs"
"path/filepath"
"strings"
"sync"
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/commands/models"
@@ -58,14 +57,18 @@ func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
isCurrent := path == worktreePath
isPathMissing := self.pathExists(path)
var gitDir string
gitDir, err := getWorktreeGitDirPath(self.Fs, path)
if err != nil {
self.Log.Warnf("Could not find git dir for worktree %s: %v", path, err)
}
current = &models.Worktree{
IsMain: isMain,
IsCurrent: isCurrent,
IsPathMissing: isPathMissing,
Path: path,
// we defer populating GitDir until a loop below so that
// we can parallelize the calls to git rev-parse
GitDir: "",
GitDir: gitDir,
}
} else if strings.HasPrefix(splitLine, "branch ") {
branch := strings.SplitN(splitLine, " ", 2)[1]
@@ -73,28 +76,6 @@ func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
}
}
wg := sync.WaitGroup{}
wg.Add(len(worktrees))
for _, worktree := range worktrees {
worktree := worktree
go utils.Safe(func() {
defer wg.Done()
if worktree.IsPathMissing {
return
}
gitDir, err := callGitRevParseWithDir(self.cmd, self.version, worktree.Path, "--absolute-git-dir")
if err != nil {
self.Log.Warnf("Could not find git dir for worktree %s: %v", worktree.Path, err)
return
}
worktree.GitDir = gitDir
})
}
wg.Wait()
names := getUniqueNamesFromPaths(lo.Map(worktrees, func(worktree *models.Worktree, _ int) string {
return worktree.Path
}))

View File

@@ -14,7 +14,7 @@ func TestGetWorktrees(t *testing.T) {
type scenario struct {
testName string
repoPaths *RepoPaths
before func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn)
before func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs)
expectedWorktrees []*models.Worktree
expectedErr string
}
@@ -26,7 +26,7 @@ func TestGetWorktrees(t *testing.T) {
repoPath: "/path/to/repo",
worktreePath: "/path/to/repo",
},
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn) {
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs) {
runner.ExpectGitArgs([]string{"worktree", "list", "--porcelain"},
`worktree /path/to/repo
HEAD d85cc9d281fa6ae1665c68365fc70e75e82a042d
@@ -34,8 +34,6 @@ branch refs/heads/mybranch
`,
nil)
gitArgsMainWorktree := append(append([]string{"-C", "/path/to/repo"}, getRevParseArgs()...), "--absolute-git-dir")
runner.ExpectGitArgs(gitArgsMainWorktree, "/path/to/repo/.git", nil)
_ = fs.MkdirAll("/path/to/repo/.git", 0o755)
},
expectedWorktrees: []*models.Worktree{
@@ -57,7 +55,7 @@ branch refs/heads/mybranch
repoPath: "/path/to/repo",
worktreePath: "/path/to/repo",
},
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn) {
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs) {
runner.ExpectGitArgs([]string{"worktree", "list", "--porcelain"},
`worktree /path/to/repo
HEAD d85cc9d281fa6ae1665c68365fc70e75e82a042d
@@ -68,10 +66,6 @@ HEAD 775955775e79b8f5b4c4b56f82fbf657e2d5e4de
branch refs/heads/mybranch-worktree
`,
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)
@@ -106,7 +100,7 @@ branch refs/heads/mybranch-worktree
repoPath: "/path/to/repo",
worktreePath: "/path/to/repo",
},
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn) {
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs) {
runner.ExpectGitArgs([]string{"worktree", "list", "--porcelain"},
`worktree /path/to/worktree
HEAD 775955775e79b8f5b4c4b56f82fbf657e2d5e4de
@@ -135,7 +129,7 @@ branch refs/heads/missingbranch
repoPath: "/path/to/repo",
worktreePath: "/path/to/repo-worktree",
},
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn) {
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs) {
runner.ExpectGitArgs([]string{"worktree", "list", "--porcelain"},
`worktree /path/to/repo
HEAD d85cc9d281fa6ae1665c68365fc70e75e82a042d
@@ -146,10 +140,6 @@ HEAD 775955775e79b8f5b4c4b56f82fbf657e2d5e4de
branch refs/heads/mybranch-worktree
`,
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)
@@ -185,23 +175,10 @@ branch refs/heads/mybranch-worktree
t.Run(s.testName, func(t *testing.T) {
runner := oscommands.NewFakeRunner(t)
fs := afero.NewMemMapFs()
version, err := GetGitVersion(oscommands.NewDummyOSCommand())
if err != nil {
t.Fatal(err)
}
getRevParseArgs := func() []string {
args := []string{"rev-parse"}
if version.IsAtLeast(2, 31, 0) {
args = append(args, "--path-format=absolute")
}
return args
}
s.before(runner, fs, getRevParseArgs)
s.before(runner, fs)
loader := &WorktreeLoader{
GitCommon: buildGitCommon(commonDeps{runner: runner, fs: fs, repoPaths: s.repoPaths, gitVersion: version}),
GitCommon: buildGitCommon(commonDeps{runner: runner, fs: fs, repoPaths: s.repoPaths}),
}
worktrees, err := loader.GetWorktrees()

74
pkg/commands/git_test.go Normal file
View File

@@ -0,0 +1,74 @@
package commands
import (
"testing"
"github.com/go-errors/errors"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
)
func TestFindWorktreeRoot(t *testing.T) {
type scenario struct {
testName string
currentPath string
before func(fs afero.Fs)
expectedPath string
expectedErr string
}
scenarios := []scenario{
{
testName: "at root of worktree",
currentPath: "/path/to/repo",
before: func(fs afero.Fs) {
_ = fs.MkdirAll("/path/to/repo/.git", 0o755)
},
expectedPath: "/path/to/repo",
expectedErr: "",
},
{
testName: "inside worktree",
currentPath: "/path/to/repo/subdir",
before: func(fs afero.Fs) {
_ = fs.MkdirAll("/path/to/repo/.git", 0o755)
_ = fs.MkdirAll("/path/to/repo/subdir", 0o755)
},
expectedPath: "/path/to/repo",
expectedErr: "",
},
{
testName: "not in a git repo",
currentPath: "/path/to/dir",
before: func(fs afero.Fs) {},
expectedPath: "",
expectedErr: "Must open lazygit in a git repository",
},
{
testName: "In linked worktree",
currentPath: "/path/to/worktree",
before: func(fs afero.Fs) {
_ = fs.MkdirAll("/path/to/worktree", 0o755)
_ = afero.WriteFile(fs, "/path/to/worktree/.git", []byte("blah"), 0o755)
},
expectedPath: "/path/to/worktree",
expectedErr: "",
},
}
for _, s := range scenarios {
s := s
t.Run(s.testName, func(t *testing.T) {
fs := afero.NewMemMapFs()
s.before(fs)
root, err := findWorktreeRoot(fs, s.currentPath)
if s.expectedErr != "" {
assert.EqualError(t, errors.New(s.expectedErr), err.Error())
} else {
assert.NoError(t, err)
assert.Equal(t, s.expectedPath, root)
}
})
}
}

View File

@@ -15,10 +15,6 @@ func (r *Remote) ID() string {
return r.RefName()
}
func (r *Remote) URN() string {
return "remote-" + r.ID()
}
func (r *Remote) Description() string {
return r.RefName()
}

View File

@@ -1,33 +1,13 @@
package models
import "path/filepath"
type SubmoduleConfig struct {
Name string
Path string
Url string
ParentModule *SubmoduleConfig // nil if top-level
}
func (r *SubmoduleConfig) FullName() string {
if r.ParentModule != nil {
return r.ParentModule.FullName() + "/" + r.Name
}
return r.Name
}
func (r *SubmoduleConfig) FullPath() string {
if r.ParentModule != nil {
return r.ParentModule.FullPath() + "/" + r.Path
}
return r.Path
}
func (r *SubmoduleConfig) RefName() string {
return r.FullName()
return r.Name
}
func (r *SubmoduleConfig) ID() string {
@@ -37,12 +17,3 @@ func (r *SubmoduleConfig) ID() string {
func (r *SubmoduleConfig) Description() string {
return r.RefName()
}
func (r *SubmoduleConfig) GitDirPath(repoGitDirPath string) string {
parentPath := repoGitDirPath
if r.ParentModule != nil {
parentPath = r.ParentModule.GitDirPath(repoGitDirPath)
}
return filepath.Join(parentPath, "modules", r.Name)
}

View File

@@ -27,14 +27,8 @@ type CmdObjBuilder struct {
var _ ICmdObjBuilder = &CmdObjBuilder{}
func (self *CmdObjBuilder) New(args []string) ICmdObj {
cmdObj := self.NewWithEnviron(args, os.Environ())
return cmdObj
}
// A command with explicit environment from env
func (self *CmdObjBuilder) NewWithEnviron(args []string, env []string) ICmdObj {
cmd := exec.Command(args[0], args[1:]...)
cmd.Env = env
cmd.Env = os.Environ()
return &CmdObj{
cmd: cmd,

View File

@@ -14,6 +14,11 @@ type patchPresenter struct {
// if true, all following fields are ignored
plain bool
isFocused bool
// first line index for selected cursor range
firstLineIndex int
// last line index for selected cursor range
lastLineIndex int
// line indices for tagged lines (e.g. lines added to a custom patch)
incLineIndices *set.Set[int]
}
@@ -39,6 +44,11 @@ func formatRangePlain(patch *Patch, startIdx int, endIdx int) string {
}
type FormatViewOpts struct {
IsFocused bool
// first line index for selected cursor range
FirstLineIndex int
// last line index for selected cursor range
LastLineIndex int
// line indices for tagged lines (e.g. lines added to a custom patch)
IncLineIndices *set.Set[int]
}
@@ -53,6 +63,9 @@ func formatView(patch *Patch, opts FormatViewOpts) string {
presenter := &patchPresenter{
patch: patch,
plain: false,
isFocused: opts.IsFocused,
firstLineIndex: opts.FirstLineIndex,
lastLineIndex: opts.LastLineIndex,
incLineIndices: includedLineIndices,
}
return presenter.format()
@@ -99,6 +112,7 @@ func (self *patchPresenter) format() string {
self.formatLineAux(
hunk.headerContext,
theme.DefaultTextColor,
lineIdx,
false,
),
)
@@ -125,17 +139,23 @@ func (self *patchPresenter) patchLineStyle(patchLine *PatchLine) style.TextStyle
func (self *patchPresenter) formatLine(str string, textStyle style.TextStyle, index int) string {
included := self.incLineIndices.Includes(index)
return self.formatLineAux(str, textStyle, included)
return self.formatLineAux(str, textStyle, index, included)
}
// 'selected' means you've got it highlighted with your cursor
// 'included' means the line has been included in the patch (only applicable when
// building a patch)
func (self *patchPresenter) formatLineAux(str string, textStyle style.TextStyle, included bool) string {
func (self *patchPresenter) formatLineAux(str string, textStyle style.TextStyle, index int, included bool) string {
if self.plain {
return str
}
selected := self.isFocused && index >= self.firstLineIndex && index <= self.lastLineIndex
if selected {
textStyle = textStyle.MergeStyle(theme.SelectedRangeBgColor)
}
firstCharStyle := textStyle
if included {
firstCharStyle = firstCharStyle.MergeStyle(style.BgGreen)

View File

@@ -80,15 +80,13 @@ func (p *PatchBuilder) PatchToApply(reverse bool) string {
}
func (p *PatchBuilder) addFileWhole(info *fileInfo) {
if info.mode != WHOLE {
info.mode = WHOLE
lineCount := len(strings.Split(info.diff, "\n"))
// add every line index
// TODO: add tests and then use lo.Range to simplify
info.includedLineIndices = make([]int, lineCount)
for i := 0; i < lineCount; i++ {
info.includedLineIndices[i] = i
}
info.mode = WHOLE
lineCount := len(strings.Split(info.diff, "\n"))
// add every line index
// TODO: add tests and then use lo.Range to simplify
info.includedLineIndices = make([]int, lineCount)
for i := 0; i < lineCount; i++ {
info.includedLineIndices[i] = i
}
}
@@ -199,7 +197,9 @@ func (p *PatchBuilder) RenderPatchForFile(filename string, plain bool, reverse b
if plain {
return patch.FormatPlain()
} else {
return patch.FormatView(FormatViewOpts{})
return patch.FormatView(FormatViewOpts{
IsFocused: false,
})
}
}

View File

@@ -12,11 +12,3 @@ const (
REBASE_MODE_REBASING
REBASE_MODE_MERGING
)
func (self RebaseMode) IsMerging() bool {
return self == REBASE_MODE_MERGING
}
func (self RebaseMode) IsRebasing() bool {
return self == REBASE_MODE_INTERACTIVE || self == REBASE_MODE_NORMAL || self == REBASE_MODE_REBASING
}

View File

@@ -13,6 +13,7 @@ type Common struct {
Tr *i18n.TranslationSet
UserConfig *config.UserConfig
AppState *config.AppState
Version string
Debug bool
// for interacting with the filesystem. We use afero rather than the default
// `os` package for the sake of mocking the filesystem in tests

View File

@@ -6,7 +6,7 @@ import (
"path/filepath"
"strings"
"github.com/adrg/xdg"
"github.com/OpenPeeDeeP/xdg"
"github.com/jesseduffield/lazygit/pkg/utils/yaml_utils"
yaml "github.com/jesseduffield/yaml"
)
@@ -80,17 +80,6 @@ func NewAppConfig(
return nil, err
}
// Temporary: the defaults for these are set to empty strings in
// getDefaultAppState so that we can migrate them from userConfig (which is
// now deprecated). Once we remove the user configs, we can remove this code
// and set the proper defaults in getDefaultAppState.
if appState.GitLogOrder == "" {
appState.GitLogOrder = userConfig.Git.Log.Order
}
if appState.GitLogShowGraph == "" {
appState.GitLogShowGraph = userConfig.Git.Log.ShowGraph
}
appConfig := &AppConfig{
Name: name,
Version: version,
@@ -113,9 +102,21 @@ func isCustomConfigFile(path string) bool {
}
func ConfigDir() string {
_, filePath := findConfigFile("config.yml")
legacyConfigDirectory := configDirForVendor("jesseduffield")
if _, err := os.Stat(legacyConfigDirectory); !os.IsNotExist(err) {
return legacyConfigDirectory
}
configDirectory := configDirForVendor("")
return configDirectory
}
return filepath.Dir(filePath)
func configDirForVendor(vendor string) string {
envConfigDir := os.Getenv("CONFIG_DIR")
if envConfigDir != "" {
return envConfigDir
}
configDirs := xdg.New(vendor, "lazygit")
return configDirs.ConfigHome()
}
func findOrCreateConfigDir() (string, error) {
@@ -243,42 +244,17 @@ func (c *AppConfig) GetTempDir() string {
return c.TempDir
}
// findConfigFile looks for a possibly existing config file.
// This function does NOT create any folders or files.
func findConfigFile(filename string) (exists bool, path string) {
if envConfigDir := os.Getenv("CONFIG_DIR"); envConfigDir != "" {
return true, filepath.Join(envConfigDir, filename)
func configFilePath(filename string) (string, error) {
folder, err := findOrCreateConfigDir()
if err != nil {
return "", err
}
// look for jesseduffield/lazygit/filename in XDG_CONFIG_HOME and XDG_CONFIG_DIRS
legacyConfigPath, err := xdg.SearchConfigFile(filepath.Join("jesseduffield", "lazygit", filename))
if err == nil {
return true, legacyConfigPath
}
// look for lazygit/filename in XDG_CONFIG_HOME and XDG_CONFIG_DIRS
configFilepath, err := xdg.SearchConfigFile(filepath.Join("lazygit", filename))
if err == nil {
return true, configFilepath
}
return false, filepath.Join(xdg.ConfigHome, "lazygit", filename)
return filepath.Join(folder, filename), nil
}
var ConfigFilename = "config.yml"
// stateFilePath looks for a possibly existing state file.
// if none exist, the default path is returned and all parent directories are created.
func stateFilePath(filename string) (string, error) {
exists, legacyStateFile := findConfigFile(filename)
if exists {
return legacyStateFile, nil
}
// looks for XDG_STATE_HOME/lazygit/filename
return xdg.StateFile(filepath.Join("lazygit", filename))
}
// ConfigFilename returns the filename of the default config file
func (c *AppConfig) ConfigFilename() string {
return filepath.Join(c.UserConfigDir, ConfigFilename)
@@ -291,7 +267,7 @@ func (c *AppConfig) SaveAppState() error {
return err
}
filepath, err := stateFilePath(stateFileName)
filepath, err := configFilePath("state.yml")
if err != nil {
return err
}
@@ -305,13 +281,11 @@ func (c *AppConfig) SaveAppState() error {
return err
}
var stateFileName = "state.yml"
// loadAppState loads recorded AppState from file
func loadAppState() (*AppState, error) {
appState := getDefaultAppState()
filepath, err := stateFilePath(stateFileName)
filepath, err := configFilePath("state.yml")
if err != nil {
if os.IsPermission(err) {
// apparently when people have read-only permissions they prefer us to fail silently
@@ -343,7 +317,9 @@ type AppState struct {
LastUpdateCheck int64
RecentRepos []string
StartupPopupVersion int
LastVersion string // this is the last version the user was using, for the purpose of showing release notes
// Version of lazygit when the user last opened the app. We track this
// so we can show release notes when the user opens the app after an update
Version string
// these are for custom commands typed in directly, not for custom commands in the lazygit config
CustomCommandsHistory []string
@@ -352,15 +328,6 @@ type AppState struct {
DiffContextSize int
LocalBranchSortOrder string
RemoteBranchSortOrder string
// One of: 'date-order' | 'author-date-order' | 'topo-order' | 'default'
// 'topo-order' makes it easier to read the git log graph, but commits may not
// appear chronologically. See https://git-scm.com/docs/
GitLogOrder string
// This determines whether the git graph is rendered in the commits panel
// One of 'always' | 'never' | 'when-maximised'
GitLogShowGraph string
}
func getDefaultAppState() *AppState {
@@ -368,12 +335,9 @@ func getDefaultAppState() *AppState {
LastUpdateCheck: 0,
RecentRepos: []string{},
StartupPopupVersion: 0,
LastVersion: "",
DiffContextSize: 3,
LocalBranchSortOrder: "recency",
RemoteBranchSortOrder: "alphabetical",
GitLogOrder: "", // should be "topo-order" eventually
GitLogShowGraph: "", // should be "always" eventually
}
}
@@ -382,5 +346,5 @@ func LogPath() (string, error) {
return os.Getenv("LAZYGIT_LOG_PATH"), nil
}
return stateFilePath("development.log")
return configFilePath("development.log")
}

View File

@@ -12,9 +12,16 @@ func isWSL() bool {
func isContainer() bool {
data, err := os.ReadFile("/proc/1/cgroup")
return err == nil && (strings.Contains(string(data), "docker") ||
if strings.Contains(string(data), "docker") ||
strings.Contains(string(data), "/lxc/") ||
os.Getenv("CONTAINER") != "")
[]string{string(data)}[0] != "systemd" &&
[]string{string(data)}[0] != "init" ||
os.Getenv("container") != "" {
return err == nil && true
}
return err == nil && false
}
// GetPlatformDefaultConfig gets the defaults for the platform

View File

@@ -65,13 +65,6 @@ func getPreset(osConfig *OSConfig, guessDefaultEditor func() string) *editPreset
"nano": standardTerminalEditorPreset("nano"),
"kakoune": standardTerminalEditorPreset("kak"),
"helix": {
editTemplate: "helix -- {{filename}}",
editAtLineTemplate: "helix -- {{filename}}:{{line}}",
editAtLineAndWaitTemplate: "helix -- {{filename}}:{{line}}",
openDirInEditorTemplate: "helix -- {{dir}}",
suspend: true,
},
"helix (hx)": {
editTemplate: "hx -- {{filename}}",
editAtLineTemplate: "hx -- {{filename}}:{{line}}",
editAtLineAndWaitTemplate: "hx -- {{filename}}:{{line}}",
@@ -110,12 +103,11 @@ func getPreset(osConfig *OSConfig, guessDefaultEditor func() string) *editPreset
// Some of our presets have a different name than the editor they are using.
editorToPreset := map[string]string{
"kak": "kakoune",
"helix": "helix",
"hx": "helix (hx)",
"code": "vscode",
"subl": "sublime",
"xed": "xcode",
"kak": "kakoune",
"hx": "helix",
"code": "vscode",
"subl": "sublime",
"xed": "xcode",
}
presetName := osConfig.EditPreset

View File

@@ -121,8 +121,6 @@ type GuiConfig struct {
// One of: '2' | '3' | empty string (default)
// If empty, do not show icons.
NerdFontsVersion string `yaml:"nerdFontsVersion" jsonschema:"enum=2,enum=3,enum="`
// If true (default), file icons are shown in the file views. Only relevant if NerdFontsVersion is not empty.
ShowFileIcons bool `yaml:"showFileIcons"`
// If true, show commit hashes alongside branch names in the branches view.
ShowBranchCommitHash bool `yaml:"showBranchCommitHash"`
// Height of the command log view
@@ -142,13 +140,6 @@ type GuiConfig struct {
// Whether to stack UI components on top of each other.
// One of 'auto' (default) | 'always' | 'never'
PortraitMode string `yaml:"portraitMode"`
// How things are filtered when typing '/'.
// One of 'substring' (default) | 'fuzzy'
FilterMode string `yaml:"filterMode" jsonschema:"enum=substring,enum=fuzzy"`
}
func (c *GuiConfig) UseFuzzySearch() bool {
return c.FilterMode == "fuzzy"
}
type ThemeConfig struct {
@@ -163,6 +154,9 @@ type ThemeConfig struct {
// Background color of selected line.
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#highlighting-the-selected-line
SelectedLineBgColor []string `yaml:"selectedLineBgColor" jsonschema:"minItems=1,uniqueItems=true"`
// Background color of selected range
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#highlighting-the-selected-line
SelectedRangeBgColor []string `yaml:"selectedRangeBgColor" jsonschema:"minItems=1,uniqueItems=true"`
// Foreground color of copied commit
CherryPickedCommitFgColor []string `yaml:"cherryPickedCommitFgColor" jsonschema:"minItems=1,uniqueItems=true"`
// Background color of copied commit
@@ -214,9 +208,6 @@ type GitConfig struct {
ParseEmoji bool `yaml:"parseEmoji"`
// Config for showing the log in the commits view
Log LogConfig `yaml:"log"`
// When copying commit hashes to the clipboard, truncate them to this
// length. Set to 40 to disable truncation.
TruncateCopiedCommitHashesTo int `yaml:"truncateCopiedCommitHashesTo"`
}
type PagerType string
@@ -246,10 +237,6 @@ type PagingConfig struct {
type CommitConfig struct {
// If true, pass '--signoff' flag when committing
SignOff bool `yaml:"signOff"`
// Automatic WYSIWYG wrapping of the commit message as you type
AutoWrapCommitMessage bool `yaml:"autoWrapCommitMessage"`
// If autoWrapCommitMessage is true, the width to wrap to
AutoWrapWidth int `yaml:"autoWrapWidth"`
}
type MergingConfig struct {
@@ -261,17 +248,13 @@ type MergingConfig struct {
}
type LogConfig struct {
// One of: 'date-order' | 'author-date-order' | 'topo-order' | 'default'
// One of: 'date-order' | 'author-date-order' | 'topo-order | default'
// 'topo-order' makes it easier to read the git log graph, but commits may not
// appear chronologically. See https://git-scm.com/docs/
//
// Deprecated: Configure this with `Log menu -> Commit sort order` (<c-l> in the commits window by default).
Order string `yaml:"order" jsonschema:"deprecated,enum=date-order,enum=author-date-order,enum=topo-order,enum=default,deprecated"`
Order string `yaml:"order" jsonschema:"enum=date-order,enum=author-date-order,enum=topo-order,enum=default"`
// This determines whether the git graph is rendered in the commits panel
// One of 'always' | 'never' | 'when-maximised'
//
// Deprecated: Configure this with `Log menu -> Show git graph` (<c-l> in the commits window by default).
ShowGraph string `yaml:"showGraph" jsonschema:"deprecated,enum=always,enum=never,enum=when-maximised"`
ShowGraph string `yaml:"showGraph" jsonschema:"enum=always,enum=never,enum=when-maximised"`
// displays the whole git graph by default in the commits view (equivalent to passing the `--all` argument to `git log`)
ShowWholeGraph bool `yaml:"showWholeGraph"`
}
@@ -291,18 +274,17 @@ type UpdateConfig struct {
}
type KeybindingConfig struct {
Universal KeybindingUniversalConfig `yaml:"universal"`
Status KeybindingStatusConfig `yaml:"status"`
Files KeybindingFilesConfig `yaml:"files"`
Branches KeybindingBranchesConfig `yaml:"branches"`
Worktrees KeybindingWorktreesConfig `yaml:"worktrees"`
Commits KeybindingCommitsConfig `yaml:"commits"`
AmendAttribute KeybindingAmendAttributeConfig `yaml:"amendAttribute"`
Stash KeybindingStashConfig `yaml:"stash"`
CommitFiles KeybindingCommitFilesConfig `yaml:"commitFiles"`
Main KeybindingMainConfig `yaml:"main"`
Submodules KeybindingSubmodulesConfig `yaml:"submodules"`
CommitMessage KeybindingCommitMessageConfig `yaml:"commitMessage"`
Universal KeybindingUniversalConfig `yaml:"universal"`
Status KeybindingStatusConfig `yaml:"status"`
Files KeybindingFilesConfig `yaml:"files"`
Branches KeybindingBranchesConfig `yaml:"branches"`
Worktrees KeybindingWorktreesConfig `yaml:"worktrees"`
Commits KeybindingCommitsConfig `yaml:"commits"`
Stash KeybindingStashConfig `yaml:"stash"`
CommitFiles KeybindingCommitFilesConfig `yaml:"commitFiles"`
Main KeybindingMainConfig `yaml:"main"`
Submodules KeybindingSubmodulesConfig `yaml:"submodules"`
CommitMessage KeybindingCommitMessageConfig `yaml:"commitMessage"`
}
// damn looks like we have some inconsistencies here with -alt and -alt1
@@ -322,9 +304,6 @@ type KeybindingUniversalConfig struct {
ScrollRight string `yaml:"scrollRight"`
GotoTop string `yaml:"gotoTop"`
GotoBottom string `yaml:"gotoBottom"`
ToggleRangeSelect string `yaml:"toggleRangeSelect"`
RangeSelectDown string `yaml:"rangeSelectDown"`
RangeSelectUp string `yaml:"rangeSelectUp"`
PrevBlock string `yaml:"prevBlock"`
NextBlock string `yaml:"nextBlock"`
PrevBlockAlt string `yaml:"prevBlock-alt"`
@@ -439,6 +418,7 @@ type KeybindingCommitsConfig struct {
PickCommit string `yaml:"pickCommit"`
RevertCommit string `yaml:"revertCommit"`
CherryPickCopy string `yaml:"cherryPickCopy"`
CherryPickCopyRange string `yaml:"cherryPickCopyRange"`
PasteCommits string `yaml:"pasteCommits"`
MarkCommitAsBaseForRebase string `yaml:"markCommitAsBaseForRebase"`
CreateTag string `yaml:"tagCommit"`
@@ -448,13 +428,6 @@ type KeybindingCommitsConfig struct {
OpenLogMenu string `yaml:"openLogMenu"`
OpenInBrowser string `yaml:"openInBrowser"`
ViewBisectOptions string `yaml:"viewBisectOptions"`
StartInteractiveRebase string `yaml:"startInteractiveRebase"`
}
type KeybindingAmendAttributeConfig struct {
ResetAuthor string `yaml:"resetAuthor"`
SetAuthor string `yaml:"setAuthor"`
AddCoAuthor string `yaml:"addCoAuthor"`
}
type KeybindingStashConfig struct {
@@ -467,9 +440,11 @@ type KeybindingCommitFilesConfig struct {
}
type KeybindingMainConfig struct {
ToggleSelectHunk string `yaml:"toggleSelectHunk"`
PickBothHunks string `yaml:"pickBothHunks"`
EditSelectHunk string `yaml:"editSelectHunk"`
ToggleDragSelect string `yaml:"toggleDragSelect"`
ToggleDragSelectAlt string `yaml:"toggleDragSelect-alt"`
ToggleSelectHunk string `yaml:"toggleSelectHunk"`
PickBothHunks string `yaml:"pickBothHunks"`
EditSelectHunk string `yaml:"editSelectHunk"`
}
type KeybindingSubmodulesConfig struct {
@@ -479,7 +454,7 @@ type KeybindingSubmodulesConfig struct {
}
type KeybindingCommitMessageConfig struct {
CommitMenu string `yaml:"commitMenu"`
SwitchToEditor string `yaml:"switchToEditor"`
}
// OSConfig contains config on the level of the os
@@ -645,6 +620,7 @@ func GetDefaultConfig() *UserConfig {
InactiveBorderColor: []string{"default"},
OptionsTextColor: []string{"blue"},
SelectedLineBgColor: []string{"blue"},
SelectedRangeBgColor: []string{"blue"},
CherryPickedCommitBgColor: []string{"cyan"},
CherryPickedCommitFgColor: []string{"blue"},
MarkedBaseCommitBgColor: []string{"yellow"},
@@ -662,7 +638,6 @@ func GetDefaultConfig() *UserConfig {
ShowRandomTip: true,
ShowIcons: false,
NerdFontsVersion: "",
ShowFileIcons: true,
ShowBranchCommitHash: false,
CommandLogSize: 8,
SplitDiff: "auto",
@@ -670,7 +645,6 @@ func GetDefaultConfig() *UserConfig {
Border: "rounded",
AnimateExplosion: true,
PortraitMode: "auto",
FilterMode: "substring",
},
Git: GitConfig{
Paging: PagingConfig{
@@ -680,9 +654,7 @@ func GetDefaultConfig() *UserConfig {
ExternalDiffCommand: "",
},
Commit: CommitConfig{
SignOff: false,
AutoWrapCommitMessage: true,
AutoWrapWidth: 72,
SignOff: false,
},
Merging: MergingConfig{
ManualCommit: false,
@@ -690,20 +662,19 @@ func GetDefaultConfig() *UserConfig {
},
Log: LogConfig{
Order: "topo-order",
ShowGraph: "always",
ShowGraph: "when-maximised",
ShowWholeGraph: false,
},
SkipHookPrefix: "WIP",
MainBranches: []string{"master", "main"},
AutoFetch: true,
AutoRefresh: true,
FetchAll: true,
BranchLogCmd: "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --",
AllBranchesLogCmd: "git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium",
DisableForcePushing: false,
CommitPrefixes: map[string]CommitPrefixConfig(nil),
ParseEmoji: false,
TruncateCopiedCommitHashesTo: 12,
SkipHookPrefix: "WIP",
MainBranches: []string{"master", "main"},
AutoFetch: true,
AutoRefresh: true,
FetchAll: true,
BranchLogCmd: "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --",
AllBranchesLogCmd: "git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium",
DisableForcePushing: false,
CommitPrefixes: map[string]CommitPrefixConfig(nil),
ParseEmoji: false,
},
Refresher: RefresherConfig{
RefreshInterval: 10,
@@ -732,9 +703,6 @@ func GetDefaultConfig() *UserConfig {
ScrollRight: "L",
GotoTop: "<",
GotoBottom: ">",
ToggleRangeSelect: "v",
RangeSelectDown: "<s-down>",
RangeSelectUp: "<s-up>",
PrevBlock: "<left>",
NextBlock: "<right>",
PrevBlockAlt: "h",
@@ -843,8 +811,9 @@ func GetDefaultConfig() *UserConfig {
ResetCommitAuthor: "a",
PickCommit: "p",
RevertCommit: "t",
CherryPickCopy: "C",
PasteCommits: "V",
CherryPickCopy: "c",
CherryPickCopyRange: "C",
PasteCommits: "v",
MarkCommitAsBaseForRebase: "B",
CreateTag: "T",
CheckoutCommit: "<space>",
@@ -853,12 +822,6 @@ func GetDefaultConfig() *UserConfig {
OpenLogMenu: "<c-l>",
OpenInBrowser: "o",
ViewBisectOptions: "b",
StartInteractiveRebase: "i",
},
AmendAttribute: KeybindingAmendAttributeConfig{
ResetAuthor: "a",
SetAuthor: "A",
AddCoAuthor: "c",
},
Stash: KeybindingStashConfig{
PopStash: "g",
@@ -868,9 +831,11 @@ func GetDefaultConfig() *UserConfig {
CheckoutCommitFile: "c",
},
Main: KeybindingMainConfig{
ToggleSelectHunk: "a",
PickBothHunks: "b",
EditSelectHunk: "E",
ToggleDragSelect: "v",
ToggleDragSelectAlt: "V",
ToggleSelectHunk: "a",
PickBothHunks: "b",
EditSelectHunk: "E",
},
Submodules: KeybindingSubmodulesConfig{
Init: "i",
@@ -878,7 +843,7 @@ func GetDefaultConfig() *UserConfig {
BulkMenu: "b",
},
CommitMessage: KeybindingCommitMessageConfig{
CommitMenu: "<c-o>",
SwitchToEditor: "<c-o>",
},
},
OS: OSConfig{},

View File

@@ -8,7 +8,6 @@ type Docs struct {
Undoing string
Config string
Tutorial string
CustomPatchDemo string
}
var Links = struct {
@@ -28,10 +27,9 @@ var Links = struct {
CustomPagers: "https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md",
CustomKeybindings: "https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md",
CustomCommands: "https://github.com/jesseduffield/lazygit/wiki/Custom-Commands-Compendium",
Keybindings: "https://github.com/jesseduffield/lazygit/blob/%s/docs/keybindings",
Keybindings: "https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings",
Undoing: "https://github.com/jesseduffield/lazygit/blob/master/docs/Undoing.md",
Config: "https://github.com/jesseduffield/lazygit/blob/%s/docs/Config.md",
Config: "https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md",
Tutorial: "https://youtu.be/VDXvbHZYeKY",
CustomPatchDemo: "https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches",
},
}

View File

@@ -245,6 +245,8 @@ func (self *ContextMgr) ActivateContext(c types.Context, opts types.OnFocusOpts)
self.gui.c.GocuiGui().Cursor = v.Editable
self.gui.renderContextOptionsMap(c)
if err := c.HandleFocus(opts); err != nil {
return err
}

View File

@@ -59,6 +59,15 @@ func NewBranchesContext(c *ContextCommon) *BranchesContext {
return self
}
func (self *BranchesContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}
func (self *BranchesContext) GetSelectedRef() types.Ref {
branch := self.GetSelected()
if branch == nil {

View File

@@ -4,7 +4,6 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
@@ -34,8 +33,7 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
return [][]string{{style.FgRed.Sprint("(none)")}}
}
showFileIcons := icons.IsIconEnabled() && c.UserConfig.Gui.ShowFileIcons
lines := presentation.RenderCommitFileTree(viewModel, c.Git().Patch.PatchBuilder, showFileIcons)
lines := presentation.RenderCommitFileTree(viewModel, c.Modes().Diffing.Ref, c.Git().Patch.PatchBuilder)
return lo.Map(lines, func(line string, _ int) []string {
return []string{line}
})
@@ -65,13 +63,22 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
}
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
ctx.GetList().SetSelection(selectedLineIdx)
ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
return ctx.HandleFocus(types.OnFocusOpts{})
}))
return ctx
}
func (self *CommitFilesContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}
func (self *CommitFilesContext) GetDiffTerminals() []string {
return []string{self.GetRef().RefName()}
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)
type CommitMessageContext struct {
@@ -111,10 +112,11 @@ func (self *CommitMessageContext) SetPanelState(
self.GetView().Title = summaryTitle
self.c.Views().CommitDescription.Title = descriptionTitle
self.c.Views().CommitDescription.Subtitle = utils.ResolvePlaceholderString(self.c.Tr.CommitDescriptionSubTitle,
subtitleTemplate := lo.Ternary(onSwitchToEditor != nil, self.c.Tr.CommitDescriptionSubTitle, self.c.Tr.CommitDescriptionSubTitleNoSwitch)
self.c.Views().CommitDescription.Subtitle = utils.ResolvePlaceholderString(subtitleTemplate,
map[string]string{
"togglePanelKeyBinding": keybindings.Label(self.c.UserConfig.Keybinding.Universal.TogglePanel),
"commitMenuKeybinding": keybindings.Label(self.c.UserConfig.Keybinding.CommitMessage.CommitMenu),
"togglePanelKeyBinding": keybindings.Label(self.c.UserConfig.Keybinding.Universal.TogglePanel),
"switchToEditorKeyBinding": keybindings.Label(self.c.UserConfig.Keybinding.CommitMessage.SwitchToEditor),
})
}

View File

@@ -31,18 +31,18 @@ func (self *FilteredList[T]) GetFilter() string {
return self.filter
}
func (self *FilteredList[T]) SetFilter(filter string, useFuzzySearch bool) {
func (self *FilteredList[T]) SetFilter(filter string) {
self.filter = filter
self.applyFilter(useFuzzySearch)
self.applyFilter()
}
func (self *FilteredList[T]) ClearFilter() {
self.SetFilter("", false)
self.SetFilter("")
}
func (self *FilteredList[T]) ReApplyFilter(useFuzzySearch bool) {
self.applyFilter(useFuzzySearch)
func (self *FilteredList[T]) ReApplyFilter() {
self.applyFilter()
}
func (self *FilteredList[T]) IsFiltering() bool {
@@ -76,7 +76,7 @@ func (self *fuzzySource[T]) Len() int {
return len(self.list)
}
func (self *FilteredList[T]) applyFilter(useFuzzySearch bool) {
func (self *FilteredList[T]) applyFilter() {
self.mutex.Lock()
defer self.mutex.Unlock()
@@ -88,7 +88,7 @@ func (self *FilteredList[T]) applyFilter(useFuzzySearch bool) {
getFilterFields: self.getFilterFields,
}
matches := utils.FindFrom(self.filter, source, useFuzzySearch)
matches := fuzzy.FindFrom(self.filter, source)
self.filteredIndices = lo.Map(matches, func(match fuzzy.Match, _ int) int {
return match.Index
})

View File

@@ -1,12 +1,12 @@
package context
type FilteredListViewModel[T HasID] struct {
type FilteredListViewModel[T any] struct {
*FilteredList[T]
*ListViewModel[T]
*SearchHistory
}
func NewFilteredListViewModel[T HasID](getList func() []T, getFilterFields func(T) []string) *FilteredListViewModel[T] {
func NewFilteredListViewModel[T any](getList func() []T, getFilterFields func(T) []string) *FilteredListViewModel[T] {
filteredList := NewFilteredList(getList, getFilterFields)
self := &FilteredListViewModel[T]{
@@ -31,5 +31,5 @@ func (self *FilteredListViewModel[T]) ClearFilter() {
self.FilteredList.ClearFilter()
self.SetSelection(unfilteredIndex)
self.SetSelectedLineIdx(unfilteredIndex)
}

View File

@@ -32,14 +32,6 @@ func (self *ListContextTrait) FocusLine() {
self.GetViewTrait().FocusPoint(
self.ModelIndexToViewIndex(self.list.GetSelectedLineIdx()))
selectRangeIndex, isSelectingRange := self.list.GetRangeStartIdx()
if isSelectingRange {
selectRangeIndex = self.ModelIndexToViewIndex(selectRangeIndex)
self.GetViewTrait().SetRangeSelectStart(selectRangeIndex)
} else {
self.GetViewTrait().CancelRangeSelect()
}
// If FocusPoint() caused the view to scroll (because the selected line
// was out of view before), we need to rerender the view port again.
// This can happen when pressing , or . to scroll by pages, or < or > to
@@ -92,7 +84,7 @@ func (self *ListContextTrait) HandleFocusLost(opts types.OnFocusLostOpts) error
// OnFocus assumes that the content of the context has already been rendered to the view. OnRender is the function which actually renders the content to the view
func (self *ListContextTrait) HandleRender() error {
self.list.ClampSelection()
self.list.RefreshSelectedIdx()
content := self.renderLines(-1, -1)
self.GetViewTrait().SetContent(content)
self.c.Render()
@@ -102,7 +94,7 @@ func (self *ListContextTrait) HandleRender() error {
}
func (self *ListContextTrait) OnSearchSelect(selectedLineIdx int) error {
self.GetList().SetSelection(selectedLineIdx)
self.GetList().SetSelectedLineIdx(selectedLineIdx)
return self.HandleFocus(types.OnFocusOpts{})
}
@@ -118,8 +110,3 @@ func (self *ListContextTrait) IsItemVisible(item types.HasUrn) bool {
}
return false
}
// By default, list contexts supporta range select
func (self *ListContextTrait) RangeSelectEnabled() bool {
return true
}

View File

@@ -9,17 +9,10 @@ import (
"github.com/stretchr/testify/assert"
)
// wrapping string in my own type to give it an ID method which is required for list items
type mystring string
func (self mystring) ID() string {
return string(self)
}
func TestListRenderer_renderLines(t *testing.T) {
scenarios := []struct {
name string
modelStrings []mystring
modelStrings []string
nonModelIndices []int
startIdx int
endIdx int
@@ -27,7 +20,7 @@ func TestListRenderer_renderLines(t *testing.T) {
}{
{
name: "Render whole list",
modelStrings: []mystring{"a", "b", "c"},
modelStrings: []string{"a", "b", "c"},
startIdx: 0,
endIdx: 3,
expectedOutput: `
@@ -37,7 +30,7 @@ func TestListRenderer_renderLines(t *testing.T) {
},
{
name: "Partial list, beginning",
modelStrings: []mystring{"a", "b", "c"},
modelStrings: []string{"a", "b", "c"},
startIdx: 0,
endIdx: 2,
expectedOutput: `
@@ -46,7 +39,7 @@ func TestListRenderer_renderLines(t *testing.T) {
},
{
name: "Partial list, end",
modelStrings: []mystring{"a", "b", "c"},
modelStrings: []string{"a", "b", "c"},
startIdx: 1,
endIdx: 3,
expectedOutput: `
@@ -55,7 +48,7 @@ func TestListRenderer_renderLines(t *testing.T) {
},
{
name: "Pass an endIdx greater than the model length",
modelStrings: []mystring{"a", "b", "c"},
modelStrings: []string{"a", "b", "c"},
startIdx: 2,
endIdx: 5,
expectedOutput: `
@@ -63,7 +56,7 @@ func TestListRenderer_renderLines(t *testing.T) {
},
{
name: "Whole list with section headers",
modelStrings: []mystring{"a", "b", "c"},
modelStrings: []string{"a", "b", "c"},
nonModelIndices: []int{1, 3},
startIdx: 0,
endIdx: 5,
@@ -76,7 +69,7 @@ func TestListRenderer_renderLines(t *testing.T) {
},
{
name: "Multiple consecutive headers",
modelStrings: []mystring{"a", "b", "c"},
modelStrings: []string{"a", "b", "c"},
nonModelIndices: []int{0, 0, 2, 2, 2},
startIdx: 0,
endIdx: 8,
@@ -92,7 +85,7 @@ func TestListRenderer_renderLines(t *testing.T) {
},
{
name: "Partial list with headers, beginning",
modelStrings: []mystring{"a", "b", "c"},
modelStrings: []string{"a", "b", "c"},
nonModelIndices: []int{1, 3},
startIdx: 0,
endIdx: 3,
@@ -103,7 +96,7 @@ func TestListRenderer_renderLines(t *testing.T) {
},
{
name: "Partial list with headers, end (beyond end index)",
modelStrings: []mystring{"a", "b", "c"},
modelStrings: []string{"a", "b", "c"},
nonModelIndices: []int{1, 3},
startIdx: 2,
endIdx: 7,
@@ -115,7 +108,7 @@ func TestListRenderer_renderLines(t *testing.T) {
}
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
viewModel := NewListViewModel[mystring](func() []mystring { return s.modelStrings })
viewModel := NewListViewModel[string](func() []string { return s.modelStrings })
var getNonModelItems func() []*NonModelItem
if s.nonModelIndices != nil {
getNonModelItems = func() []*NonModelItem {
@@ -131,7 +124,7 @@ func TestListRenderer_renderLines(t *testing.T) {
list: viewModel,
getDisplayStrings: func(startIdx int, endIdx int) [][]string {
return lo.Map(s.modelStrings[startIdx:endIdx],
func(s mystring, _ int) []string { return []string{string(s)} })
func(s string, _ int) []string { return []string{s} })
},
getNonModelItems: getNonModelItems,
}
@@ -145,12 +138,6 @@ func TestListRenderer_renderLines(t *testing.T) {
}
}
type myint int
func (self myint) ID() string {
return fmt.Sprint(int(self))
}
func TestListRenderer_ModelIndexToViewIndex_and_back(t *testing.T) {
scenarios := []struct {
name string
@@ -235,8 +222,8 @@ func TestListRenderer_ModelIndexToViewIndex_and_back(t *testing.T) {
assert.Equal(t, len(s.modelIndices), len(s.expectedViewIndices))
assert.Equal(t, len(s.viewIndices), len(s.expectedModelIndices))
modelInts := lo.Map(lo.Range(s.numModelItems), func(i int, _ int) myint { return myint(i) })
viewModel := NewListViewModel[myint](func() []myint { return modelInts })
modelInts := lo.Range(s.numModelItems)
viewModel := NewListViewModel[int](func() []int { return modelInts })
var getNonModelItems func() []*NonModelItem
if s.nonModelIndices != nil {
getNonModelItems = func() []*NonModelItem {
@@ -249,7 +236,7 @@ func TestListRenderer_ModelIndexToViewIndex_and_back(t *testing.T) {
list: viewModel,
getDisplayStrings: func(startIdx int, endIdx int) [][]string {
return lo.Map(modelInts[startIdx:endIdx],
func(i myint, _ int) []string { return []string{fmt.Sprint(i)} })
func(i int, _ int) []string { return []string{fmt.Sprint(i)} })
},
getNonModelItems: getNonModelItems,
}

View File

@@ -3,28 +3,27 @@ package context
import (
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
type HasID interface {
ID() string
}
type ListViewModel[T HasID] struct {
type ListViewModel[T any] struct {
*traits.ListCursor
getModel func() []T
}
func NewListViewModel[T HasID](getModel func() []T) *ListViewModel[T] {
func NewListViewModel[T any](getModel func() []T) *ListViewModel[T] {
self := &ListViewModel[T]{
getModel: getModel,
}
self.ListCursor = traits.NewListCursor(func() int { return len(getModel()) })
self.ListCursor = traits.NewListCursor(self)
return self
}
func (self *ListViewModel[T]) Len() int {
return len(self.getModel())
}
func (self *ListViewModel[T]) GetSelected() T {
if self.Len() == 0 {
return Zero[T]()
@@ -33,34 +32,6 @@ func (self *ListViewModel[T]) GetSelected() T {
return self.getModel()[self.GetSelectedLineIdx()]
}
func (self *ListViewModel[T]) GetSelectedItemId() string {
if self.Len() == 0 {
return ""
}
return self.GetSelected().ID()
}
func (self *ListViewModel[T]) GetSelectedItems() ([]T, int, int) {
if self.Len() == 0 {
return nil, -1, -1
}
startIdx, endIdx := self.GetSelectionRange()
return self.getModel()[startIdx : endIdx+1], startIdx, endIdx
}
func (self *ListViewModel[T]) GetSelectedItemIds() ([]string, int, int) {
selectedItems, startIdx, endIdx := self.GetSelectedItems()
ids := lo.Map(selectedItems, func(item T, _ int) string {
return item.ID()
})
return ids, startIdx, endIdx
}
func (self *ListViewModel[T]) GetItems() []T {
return self.getModel()
}

View File

@@ -38,14 +38,14 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
}
showYouAreHereLabel := c.Model().WorkingTreeStateAtLastCommitRefresh == enums.REBASE_MODE_REBASING
hasRebaseUpdateRefsConfig := c.Git().Config.GetRebaseUpdateRefs()
showBranchMarkerForHeadCommit := c.Git().Config.GetRebaseUpdateRefs()
return presentation.GetCommitListDisplayStrings(
c.Common,
c.Model().Commits,
c.Model().Branches,
c.Model().CheckedOutBranch,
hasRebaseUpdateRefsConfig,
showBranchMarkerForHeadCommit,
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
c.Modes().CherryPicking.SelectedShaSet(),
c.Modes().Diffing.Ref,
@@ -85,13 +85,22 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
}
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
ctx.GetList().SetSelection(selectedLineIdx)
ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
return ctx.HandleFocus(types.OnFocusOpts{})
}))
return ctx
}
func (self *LocalCommitsContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}
type LocalCommitsViewModel struct {
*ListViewModel[*models.Commit]
@@ -156,8 +165,7 @@ func shouldShowGraph(c *ContextCommon) bool {
return false
}
value := c.GetAppState().GitLogShowGraph
value := c.UserConfig.Git.Log.ShowGraph
switch value {
case "always":
return true

View File

@@ -45,6 +45,16 @@ func NewMenuContext(
}
}
// TODO: remove this thing.
func (self *MenuContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.Label
}
type MenuViewModel struct {
c *ContextCommon
menuItems []*types.MenuItem
@@ -80,7 +90,7 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
return lo.Map(menuItems, func(item *types.MenuItem, _ int) []string {
displayStrings := item.LabelColumns
if item.DisabledReason != nil {
if item.DisabledReason != "" {
displayStrings[0] = style.FgDefault.SetStrikethrough().Sprint(displayStrings[0])
}
@@ -88,17 +98,30 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
return displayStrings
}
// These keys are used for general navigation so we'll strike them out to
// avoid confusion
reservedKeys := []string{
self.c.UserConfig.Keybinding.Universal.Confirm,
self.c.UserConfig.Keybinding.Universal.Select,
self.c.UserConfig.Keybinding.Universal.Return,
self.c.UserConfig.Keybinding.Universal.StartSearch,
}
keyLabel := keybindings.LabelFromKey(item.Key)
displayStrings = utils.Prepend(displayStrings, style.FgCyan.Sprint(keyLabel))
keyStyle := style.FgCyan
if lo.Contains(reservedKeys, keyLabel) {
keyStyle = style.FgDefault.SetStrikethrough()
}
displayStrings = utils.Prepend(displayStrings, keyStyle.Sprint(keyLabel))
return displayStrings
})
}
func (self *MenuViewModel) GetNonModelItems() []*NonModelItem {
// Don't display section headers when we are filtering, and the filter mode
// is fuzzy. The reason is that filtering changes the order of the items
// (they are sorted by best match), so all the sections would be messed up.
if self.FilteredListViewModel.IsFiltering() && self.c.UserConfig.Gui.UseFuzzySearch() {
// Don't display section headers when we are filtering. The reason is that
// filtering changes the order of the items (they are sorted by best match),
// so all the sections would be messed up.
if self.FilteredListViewModel.IsFiltering() {
return []*NonModelItem{}
}
@@ -149,13 +172,8 @@ func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Bin
}
func (self *MenuContext) OnMenuPress(selectedItem *types.MenuItem) error {
if selectedItem != nil && selectedItem.DisabledReason != nil {
if selectedItem.DisabledReason.ShowErrorInPanel {
return self.c.ErrorMsg(selectedItem.DisabledReason.Text)
}
self.c.ErrorToast(self.c.Tr.DisabledMenuItemPrefix + selectedItem.DisabledReason.Text)
return nil
if selectedItem != nil && selectedItem.DisabledReason != "" {
return self.c.ErrorMsg(selectedItem.DisabledReason)
}
if err := self.c.PopContext(); err != nil {
@@ -172,8 +190,3 @@ func (self *MenuContext) OnMenuPress(selectedItem *types.MenuItem) error {
return nil
}
// There is currently no need to use range-select in a menu so we're disabling it.
func (self *MenuContext) RangeSelectEnabled() bool {
return false
}

View File

@@ -68,8 +68,8 @@ func (self *MergeConflictsContext) IsUserScrolling() bool {
return self.viewModel.userVerticalScrolling
}
func (self *MergeConflictsContext) RenderAndFocus() error {
self.setContent()
func (self *MergeConflictsContext) RenderAndFocus(isFocused bool) error {
self.setContent(isFocused)
self.FocusSelection()
self.c.Render()
@@ -77,41 +77,30 @@ func (self *MergeConflictsContext) RenderAndFocus() error {
return nil
}
func (self *MergeConflictsContext) Render() error {
self.setContent()
func (self *MergeConflictsContext) Render(isFocused bool) error {
self.setContent(isFocused)
self.c.Render()
return nil
}
func (self *MergeConflictsContext) GetContentToRender() string {
func (self *MergeConflictsContext) GetContentToRender(isFocused bool) string {
if self.GetState() == nil {
return ""
}
return mergeconflicts.ColoredConflictFile(self.GetState())
return mergeconflicts.ColoredConflictFile(self.GetState(), isFocused)
}
func (self *MergeConflictsContext) setContent() {
self.GetView().SetContent(self.GetContentToRender())
func (self *MergeConflictsContext) setContent(isFocused bool) {
self.GetView().SetContent(self.GetContentToRender(isFocused))
}
func (self *MergeConflictsContext) FocusSelection() {
if !self.IsUserScrolling() {
_ = self.GetView().SetOriginY(self.GetOriginY())
}
self.SetSelectedLineRange()
}
func (self *MergeConflictsContext) SetSelectedLineRange() {
startIdx, endIdx := self.GetState().GetSelectedRange()
view := self.GetView()
originY := view.OriginY()
// As far as the view is concerned, we are always selecting a range
view.SetRangeSelectStart(startIdx)
view.SetCursorY(endIdx - originY)
}
func (self *MergeConflictsContext) GetOriginY() int {

View File

@@ -115,10 +115,7 @@ func (self *PatchExplorerContext) FocusSelection() {
_ = view.SetOriginY(newOriginY)
startIdx, endIdx := state.SelectedRange()
// As far as the view is concerned, we are always selecting a range
view.SetRangeSelectStart(startIdx)
view.SetCursorY(endIdx - newOriginY)
view.SetCursorY(state.GetSelectedLineIdx() - newOriginY)
}
func (self *PatchExplorerContext) GetContentToRender(isFocused bool) string {

View File

@@ -59,6 +59,15 @@ func NewReflogCommitsContext(c *ContextCommon) *ReflogCommitsContext {
}
}
func (self *ReflogCommitsContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}
func (self *ReflogCommitsContext) CanRebase() bool {
return false
}

View File

@@ -4,7 +4,6 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
type RemoteBranchesContext struct {
@@ -54,6 +53,15 @@ func NewRemoteBranchesContext(
}
}
func (self *RemoteBranchesContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}
func (self *RemoteBranchesContext) GetSelectedRef() types.Ref {
remoteBranch := self.GetSelected()
if remoteBranch == nil {
@@ -62,16 +70,6 @@ func (self *RemoteBranchesContext) GetSelectedRef() types.Ref {
return remoteBranch
}
func (self *RemoteBranchesContext) GetSelectedRefs() ([]types.Ref, int, int) {
items, startIdx, endIdx := self.GetSelectedItems()
refs := lo.Map(items, func(item *models.RemoteBranch, _ int) types.Ref {
return item
})
return refs, startIdx, endIdx
}
func (self *RemoteBranchesContext) GetDiffTerminals() []string {
itemId := self.GetSelectedItemId()

View File

@@ -25,8 +25,7 @@ func NewRemotesContext(c *ContextCommon) *RemotesContext {
)
getDisplayStrings := func(_ int, _ int) [][]string {
return presentation.GetRemoteListDisplayStrings(
viewModel.GetItems(), c.Modes().Diffing.Ref, c.State().GetItemOperation, c.Tr)
return presentation.GetRemoteListDisplayStrings(viewModel.GetItems(), c.Modes().Diffing.Ref)
}
return &RemotesContext{
@@ -48,6 +47,15 @@ func NewRemotesContext(c *ContextCommon) *RemotesContext {
}
}
func (self *RemotesContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}
func (self *RemotesContext) GetDiffTerminals() []string {
itemId := self.GetSelectedItemId()

View File

@@ -49,6 +49,15 @@ func NewStashContext(
}
}
func (self *StashContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}
func (self *StashContext) CanRebase() bool {
return false
}

View File

@@ -55,13 +55,13 @@ func NewSubCommitsContext(
if viewModel.GetShowBranchHeads() {
branches = c.Model().Branches
}
hasRebaseUpdateRefsConfig := c.Git().Config.GetRebaseUpdateRefs()
showBranchMarkerForHeadCommit := c.Git().Config.GetRebaseUpdateRefs()
return presentation.GetCommitListDisplayStrings(
c.Common,
c.Model().SubCommits,
branches,
viewModel.GetRef().RefName(),
hasRebaseUpdateRefsConfig,
showBranchMarkerForHeadCommit,
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
c.Modes().CherryPicking.SelectedShaSet(),
c.Modes().Diffing.Ref,
@@ -134,7 +134,7 @@ func NewSubCommitsContext(
}
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
ctx.GetList().SetSelection(selectedLineIdx)
ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
return ctx.HandleFocus(types.OnFocusOpts{})
}))
@@ -175,6 +175,15 @@ func (self *SubCommitsViewModel) GetShowBranchHeads() bool {
return self.showBranchHeads
}
func (self *SubCommitsContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}
func (self *SubCommitsContext) CanRebase() bool {
return false
}

View File

@@ -17,7 +17,7 @@ func NewSubmodulesContext(c *ContextCommon) *SubmodulesContext {
viewModel := NewFilteredListViewModel(
func() []*models.SubmoduleConfig { return c.Model().Submodules },
func(submodule *models.SubmoduleConfig) []string {
return []string{submodule.FullName()}
return []string{submodule.Name}
},
)
@@ -43,3 +43,12 @@ func NewSubmodulesContext(c *ContextCommon) *SubmodulesContext {
},
}
}
func (self *SubmodulesContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}

View File

@@ -63,9 +63,18 @@ func NewSuggestionsContext(
}
}
func (self *SuggestionsContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.Value
}
func (self *SuggestionsContext) SetSuggestions(suggestions []*types.Suggestion) {
self.State.Suggestions = suggestions
self.SetSelection(0)
self.SetSelectedLineIdx(0)
self.c.ResetViewOrigin(self.GetView())
_ = self.HandleRender()
}
@@ -81,8 +90,3 @@ func (self *SuggestionsContext) RefreshSuggestions() {
}
})
}
// There is currently no need to use range-select in the suggestions view so we're disabling it.
func (self *SuggestionsContext) RangeSelectEnabled() bool {
return false
}

View File

@@ -52,6 +52,15 @@ func NewTagsContext(
}
}
func (self *TagsContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}
func (self *TagsContext) GetSelectedRef() types.Ref {
tag := self.GetSelected()
if tag == nil {

View File

@@ -5,36 +5,17 @@ import (
"github.com/jesseduffield/lazygit/pkg/utils"
)
type RangeSelectMode int
const (
// None means we are not selecting a range
RangeSelectModeNone RangeSelectMode = iota
// Sticky range select is started by pressing 'v', then the range is expanded
// when you move up or down. It is cancelled by pressing 'v' again.
RangeSelectModeSticky
// Nonsticky range select is started by pressing shift+arrow and cancelled
// when pressing up/down without shift, or by pressing 'v'
RangeSelectModeNonSticky
)
type ListCursor struct {
selectedIdx int
rangeSelectMode RangeSelectMode
// value is ignored when rangeSelectMode is RangeSelectModeNone
rangeStartIdx int
// Get the length of the list. We use this to clamp the selection so that
// the selected index is always valid
getLength func() int
type HasLength interface {
Len() int
}
func NewListCursor(getLength func() int) *ListCursor {
return &ListCursor{
selectedIdx: 0,
rangeStartIdx: 0,
rangeSelectMode: RangeSelectModeNone,
getLength: getLength,
}
type ListCursor struct {
selectedIdx int
list HasLength
}
func NewListCursor(list HasLength) *ListCursor {
return &ListCursor{selectedIdx: 0, list: list}
}
var _ types.IListCursor = (*ListCursor)(nil)
@@ -43,135 +24,25 @@ func (self *ListCursor) GetSelectedLineIdx() int {
return self.selectedIdx
}
// Sets the selected line index. Note, you probably don't want to use this directly,
// because it doesn't affect the range select mode or range start index. You should only
// use this for navigation situations where e.g. the user wants to jump to the top of
// a list while in range select mode so that the selection ends up being between
// the top of the list and the previous selection
func (self *ListCursor) SetSelectedLineIdx(value int) {
self.selectedIdx = self.clampValue(value)
}
// Sets the selected index and cancels the range. You almost always want to use
// this instead of SetSelectedLineIdx. For example, if you want to jump the cursor
// to the top of a list after checking out a branch, you should use this method,
// or you may end up with a large range selection from the previous cursor position
// to the top of the list.
func (self *ListCursor) SetSelection(value int) {
self.selectedIdx = self.clampValue(value)
self.CancelRangeSelect()
}
func (self *ListCursor) SetSelectionRangeAndMode(selectedIdx, rangeStartIdx int, mode RangeSelectMode) {
self.selectedIdx = self.clampValue(selectedIdx)
self.rangeStartIdx = self.clampValue(rangeStartIdx)
if mode == RangeSelectModeNonSticky && selectedIdx == rangeStartIdx {
self.rangeSelectMode = RangeSelectModeNone
} else {
self.rangeSelectMode = mode
}
}
// Returns the selectedIdx, the rangeStartIdx, and the mode of the current selection.
func (self *ListCursor) GetSelectionRangeAndMode() (int, int, RangeSelectMode) {
if self.IsSelectingRange() {
return self.selectedIdx, self.rangeStartIdx, self.rangeSelectMode
} else {
return self.selectedIdx, self.selectedIdx, self.rangeSelectMode
}
}
func (self *ListCursor) clampValue(value int) int {
clampedValue := -1
length := self.getLength()
if length > 0 {
clampedValue = utils.Clamp(value, 0, length-1)
if self.list.Len() > 0 {
clampedValue = utils.Clamp(value, 0, self.list.Len()-1)
}
return clampedValue
self.selectedIdx = clampedValue
}
// Moves the cursor up or down by the given amount.
// If we are in non-sticky range select mode, this will cancel the range select
func (self *ListCursor) MoveSelectedLine(change int) {
if self.rangeSelectMode == RangeSelectModeNonSticky {
self.CancelRangeSelect()
}
self.SetSelectedLineIdx(self.selectedIdx + change)
// moves the cursor up or down by the given amount
func (self *ListCursor) MoveSelectedLine(delta int) {
self.SetSelectedLineIdx(self.selectedIdx + delta)
}
// Moves the cursor up or down by the given amount, and also moves the range start
// index by the same amount
func (self *ListCursor) MoveSelection(delta int) {
self.selectedIdx = self.clampValue(self.selectedIdx + delta)
if self.IsSelectingRange() {
self.rangeStartIdx = self.clampValue(self.rangeStartIdx + delta)
}
}
// To be called when the model might have shrunk so that our selection is not out of bounds
func (self *ListCursor) ClampSelection() {
self.selectedIdx = self.clampValue(self.selectedIdx)
self.rangeStartIdx = self.clampValue(self.rangeStartIdx)
// to be called when the model might have shrunk so that our selection is not not out of bounds
func (self *ListCursor) RefreshSelectedIdx() {
self.SetSelectedLineIdx(self.selectedIdx)
}
func (self *ListCursor) Len() int {
// The length of the model slice can change at any time, so the selection may
// become out of bounds. To reduce the likelihood of this, we clamp the selection
// whenever we obtain the length of the model.
self.ClampSelection()
return self.getLength()
}
func (self *ListCursor) GetRangeStartIdx() (int, bool) {
if self.IsSelectingRange() {
return self.rangeStartIdx, true
}
return 0, false
}
func (self *ListCursor) CancelRangeSelect() {
self.rangeSelectMode = RangeSelectModeNone
}
// Returns true if we are in range select mode. Note that we may be in range select
// mode and still only selecting a single item. See AreMultipleItemsSelected below.
func (self *ListCursor) IsSelectingRange() bool {
return self.rangeSelectMode != RangeSelectModeNone
}
// Returns true if we are in range select mode and selecting multiple items
func (self *ListCursor) AreMultipleItemsSelected() bool {
startIdx, endIdx := self.GetSelectionRange()
return startIdx != endIdx
}
func (self *ListCursor) GetSelectionRange() (int, int) {
if self.IsSelectingRange() {
return utils.SortRange(self.selectedIdx, self.rangeStartIdx)
}
return self.selectedIdx, self.selectedIdx
}
func (self *ListCursor) ToggleStickyRange() {
if self.IsSelectingRange() {
self.CancelRangeSelect()
} else {
self.rangeStartIdx = self.selectedIdx
self.rangeSelectMode = RangeSelectModeSticky
}
}
func (self *ListCursor) ExpandNonStickyRange(change int) {
if !self.IsSelectingRange() {
self.rangeStartIdx = self.selectedIdx
}
self.rangeSelectMode = RangeSelectModeNonSticky
self.SetSelectedLineIdx(self.selectedIdx + change)
return self.list.Len()
}

View File

@@ -21,14 +21,6 @@ func (self *ViewTrait) FocusPoint(yIdx int) {
self.view.FocusPoint(self.view.OriginX(), yIdx)
}
func (self *ViewTrait) SetRangeSelectStart(yIdx int) {
self.view.SetRangeSelectStart(yIdx)
}
func (self *ViewTrait) CancelRangeSelect() {
self.view.CancelRangeSelect()
}
func (self *ViewTrait) SetViewPortContent(content string) {
_, y := self.view.Origin()
self.view.OverwriteLines(y, content)

View File

@@ -4,7 +4,6 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
@@ -25,8 +24,7 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
)
getDisplayStrings := func(_ int, _ int) [][]string {
showFileIcons := icons.IsIconEnabled() && c.UserConfig.Gui.ShowFileIcons
lines := presentation.RenderFileTree(viewModel, c.Model().Submodules, showFileIcons)
lines := presentation.RenderFileTree(viewModel, c.Modes().Diffing.Ref, c.Model().Submodules)
return lo.Map(lines, func(line string, _ int) []string {
return []string{line}
})
@@ -52,9 +50,18 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
}
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
ctx.GetList().SetSelection(selectedLineIdx)
ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
return ctx.HandleFocus(types.OnFocusOpts{})
}))
return ctx
}
func (self *WorkingTreeContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}

View File

@@ -46,3 +46,12 @@ func NewWorktreesContext(c *ContextCommon) *WorktreesContext {
},
}
}
func (self *WorktreesContext) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}

View File

@@ -16,9 +16,6 @@ func (gui *Gui) Helpers() *helpers.Helpers {
return gui.helpers
}
// Note, the order of controllers determines the order in which keybindings appear
// in the keybinding menu: the earlier that the controller is attached to a context,
// the lower in the list the keybindings will appear.
func (gui *Gui) resetHelpersAndControllers() {
helperCommon := gui.c
recordDirectoryHelper := helpers.NewRecordDirectoryHelper(helperCommon)
@@ -38,14 +35,10 @@ func (gui *Gui) resetHelpersAndControllers() {
getCommitDescription := func() string {
return strings.TrimSpace(gui.Views.CommitDescription.TextArea.GetContent())
}
getUnwrappedCommitDescription := func() string {
return strings.TrimSpace(gui.Views.CommitDescription.TextArea.GetUnwrappedContent())
}
commitsHelper := helpers.NewCommitsHelper(helperCommon,
getCommitSummary,
setCommitSummary,
getCommitDescription,
getUnwrappedCommitDescription,
setCommitDescription,
)
@@ -179,6 +172,7 @@ func (gui *Gui) resetHelpersAndControllers() {
branchesController := controllers.NewBranchesController(common)
gitFlowController := controllers.NewGitFlowController(common)
filesRemoveController := controllers.NewFilesRemoveController(common)
stashController := controllers.NewStashController(common)
commitFilesController := controllers.NewCommitFilesController(common)
patchExplorerControllerFactory := controllers.NewPatchExplorerControllerFactory(common)
@@ -206,18 +200,6 @@ func (gui *Gui) resetHelpersAndControllers() {
controllers.AttachControllers(context, searchControllerFactory.Create(context))
}
for _, context := range []controllers.CanViewWorktreeOptions{
gui.State.Contexts.LocalCommits,
gui.State.Contexts.ReflogCommits,
gui.State.Contexts.SubCommits,
gui.State.Contexts.Stash,
gui.State.Contexts.Branches,
gui.State.Contexts.RemoteBranches,
gui.State.Contexts.Tags,
} {
controllers.AttachControllers(context, controllers.NewWorktreeOptionsController(common, context))
}
// allow for navigating between side window contexts
for _, context := range []types.Context{
gui.State.Contexts.Status,
@@ -266,6 +248,18 @@ func (gui *Gui) resetHelpersAndControllers() {
controllers.AttachControllers(context, controllers.NewBasicCommitsController(common, context))
}
for _, context := range []controllers.CanViewWorktreeOptions{
gui.State.Contexts.LocalCommits,
gui.State.Contexts.ReflogCommits,
gui.State.Contexts.SubCommits,
gui.State.Contexts.Stash,
gui.State.Contexts.Branches,
gui.State.Contexts.RemoteBranches,
gui.State.Contexts.Tags,
} {
controllers.AttachControllers(context, controllers.NewWorktreeOptionsController(common, context))
}
controllers.AttachControllers(gui.State.Contexts.ReflogCommits,
reflogCommitsController,
)
@@ -303,6 +297,7 @@ func (gui *Gui) resetHelpersAndControllers() {
controllers.AttachControllers(gui.State.Contexts.Files,
filesController,
filesRemoveController,
)
controllers.AttachControllers(gui.State.Contexts.Tags,
@@ -313,6 +308,11 @@ func (gui *Gui) resetHelpersAndControllers() {
submodulesController,
)
controllers.AttachControllers(gui.State.Contexts.LocalCommits,
localCommitsController,
bisectController,
)
controllers.AttachControllers(gui.State.Contexts.Branches,
branchesController,
gitFlowController,
@@ -376,11 +376,11 @@ func (gui *Gui) resetHelpersAndControllers() {
)
controllers.AttachControllers(gui.State.Contexts.Global,
syncController,
undoController,
globalController,
contextLinesController,
jumpToSideWindowController,
syncController,
)
controllers.AttachControllers(gui.State.Contexts.Snake,

View File

@@ -5,9 +5,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
)
// This controller is for all contexts that contain a list of commits.
@@ -16,85 +14,63 @@ var _ types.IController = &BasicCommitsController{}
type ContainsCommits interface {
types.Context
types.IListContext
GetSelected() *models.Commit
GetSelectedItems() ([]*models.Commit, int, int)
GetCommits() []*models.Commit
GetSelectedLineIdx() int
}
type BasicCommitsController struct {
baseController
*ListControllerTrait[*models.Commit]
c *ControllerCommon
context ContainsCommits
}
func NewBasicCommitsController(c *ControllerCommon, context ContainsCommits) *BasicCommitsController {
func NewBasicCommitsController(controllerCommon *ControllerCommon, context ContainsCommits) *BasicCommitsController {
return &BasicCommitsController{
baseController: baseController{},
c: c,
c: controllerCommon,
context: context,
ListControllerTrait: NewListControllerTrait[*models.Commit](
c,
context,
context.GetSelected,
context.GetSelectedItems,
),
}
}
func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
bindings := []*types.Binding{
{
Key: opts.GetKey(opts.Config.Commits.CheckoutCommit),
Handler: self.withItem(self.checkout),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.Checkout,
Tooltip: self.c.Tr.CheckoutCommitTooltip,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Commits.CheckoutCommit),
Handler: self.checkSelected(self.checkout),
Description: self.c.Tr.CheckoutCommit,
},
{
Key: opts.GetKey(opts.Config.Commits.CopyCommitAttributeToClipboard),
Handler: self.withItem(self.copyCommitAttribute),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.CopyCommitAttributeToClipboard,
Tooltip: self.c.Tr.CopyCommitAttributeToClipboardTooltip,
OpensMenu: true,
Key: opts.GetKey(opts.Config.Commits.CopyCommitAttributeToClipboard),
Handler: self.checkSelected(self.copyCommitAttribute),
Description: self.c.Tr.CopyCommitAttributeToClipboard,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Commits.OpenInBrowser),
Handler: self.withItem(self.openInBrowser),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.OpenCommitInBrowser,
Key: opts.GetKey(opts.Config.Commits.OpenInBrowser),
Handler: self.checkSelected(self.openInBrowser),
Description: self.c.Tr.OpenCommitInBrowser,
},
{
Key: opts.GetKey(opts.Config.Universal.New),
Handler: self.withItem(self.newBranch),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.CreateNewBranchFromCommit,
Key: opts.GetKey(opts.Config.Universal.New),
Handler: self.checkSelected(self.newBranch),
Description: self.c.Tr.CreateNewBranchFromCommit,
},
{
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
Handler: self.withItem(self.createResetMenu),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.ViewResetOptions,
Tooltip: self.c.Tr.ResetTooltip,
OpensMenu: true,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
Handler: self.checkSelected(self.createResetMenu),
Description: self.c.Tr.ViewResetOptions,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Commits.CherryPickCopy),
Handler: self.withItem(self.copyRange),
GetDisabledReason: self.require(self.itemRangeSelected(self.canCopyCommits)),
Description: self.c.Tr.CherryPickCopy,
Tooltip: utils.ResolvePlaceholderString(self.c.Tr.CherryPickCopyTooltip,
map[string]string{
"paste": keybindings.Label(opts.Config.Commits.PasteCommits),
"escape": keybindings.Label(opts.Config.Universal.Return),
},
),
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Commits.CherryPickCopy),
Handler: self.checkSelected(self.copy),
Description: self.c.Tr.CherryPickCopy,
},
{
Key: opts.GetKey(opts.Config.Commits.CherryPickCopyRange),
Handler: self.checkSelected(self.copyRange),
Description: self.c.Tr.CherryPickCopyRange,
},
{
Key: opts.GetKey(opts.Config.Commits.ResetCherryPick),
@@ -102,24 +78,30 @@ func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
Description: self.c.Tr.ResetCherryPick,
},
{
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
Handler: self.withItem(self.openDiffTool),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.OpenDiffTool,
},
// 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,
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
Handler: self.checkSelected(self.openDiffTool),
Description: self.c.Tr.OpenDiffTool,
},
}
return bindings
}
func (self *BasicCommitsController) checkSelected(callback func(*models.Commit) error) func() error {
return func() error {
commit := self.context.GetSelected()
if commit == nil {
return nil
}
return callback(commit)
}
}
func (self *BasicCommitsController) Context() types.Context {
return self.context
}
func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) error {
return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.Actions.CopyCommitAttributeToClipboard,
@@ -175,7 +157,7 @@ func (self *BasicCommitsController) copyCommitSHAToClipboard(commit *models.Comm
return self.c.Error(err)
}
self.c.Toast(fmt.Sprintf("'%s' %s", commit.Sha, self.c.Tr.CopiedToClipboard))
self.c.Toast(self.c.Tr.CommitSHACopiedToClipboard)
return nil
}
@@ -289,32 +271,12 @@ func (self *BasicCommitsController) checkout(commit *models.Commit) error {
})
}
func (self *BasicCommitsController) copy(commit *models.Commit) error {
return self.c.Helpers().CherryPick.Copy(commit, self.context.GetCommits(), self.context)
}
func (self *BasicCommitsController) copyRange(*models.Commit) error {
return self.c.Helpers().CherryPick.CopyRange(self.context.GetCommits(), self.context)
}
func (self *BasicCommitsController) canCopyCommits(selectedCommits []*models.Commit, startIdx int, endIdx int) *types.DisabledReason {
for _, commit := range selectedCommits {
if commit.Sha == "" {
return &types.DisabledReason{Text: self.c.Tr.CannotCherryPickNonCommit, ShowErrorInPanel: true}
}
if commit.IsMerge() {
return &types.DisabledReason{Text: self.c.Tr.CannotCherryPickMergeCommit, ShowErrorInPanel: true}
}
}
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 self.c.ErrorMsg(msg)
return self.c.Helpers().CherryPick.CopyRange(self.context.GetSelectedLineIdx(), self.context.GetCommits(), self.context)
}
func (self *BasicCommitsController) openDiffTool(commit *models.Commit) error {

View File

@@ -14,24 +14,17 @@ import (
type BisectController struct {
baseController
*ListControllerTrait[*models.Commit]
c *ControllerCommon
}
var _ types.IController = &BisectController{}
func NewBisectController(
c *ControllerCommon,
common *ControllerCommon,
) *BisectController {
return &BisectController{
baseController: baseController{},
c: c,
ListControllerTrait: NewListControllerTrait[*models.Commit](
c,
c.Contexts().LocalCommits,
c.Contexts().LocalCommits.GetSelected,
c.Contexts().LocalCommits.GetSelectedItems,
),
c: common,
}
}
@@ -39,7 +32,7 @@ func (self *BisectController) GetKeybindings(opts types.KeybindingsOpts) []*type
bindings := []*types.Binding{
{
Key: opts.GetKey(opts.Config.Commits.ViewBisectOptions),
Handler: opts.Guards.OutsideFilterMode(self.withItem(self.openMenu)),
Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.openMenu)),
Description: self.c.Tr.ViewBisectOptions,
OpensMenu: true,
},
@@ -77,19 +70,9 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
// If we have a current sha already, then we always want to use that one. If
// not, we're still picking the initial commits before we really start, so
// use the selected commit in that case.
bisecting := info.GetCurrentSha() != ""
shaToMark := lo.Ternary(bisecting, info.GetCurrentSha(), commit.Sha)
shaToMark := lo.Ternary(info.GetCurrentSha() != "", info.GetCurrentSha(), commit.Sha)
shortShaToMark := utils.ShortSha(shaToMark)
// For marking a commit as bad, when we're not already bisecting, we require
// a single item selected, but once we are bisecting, it doesn't matter because
// the action applies to the HEAD commit rather than the selected commit.
var singleItemIfNotBisecting *types.DisabledReason
if !bisecting {
singleItemIfNotBisecting = self.require(self.singleItemSelected())()
}
menuItems := []*types.MenuItem{
{
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortShaToMark, info.NewTerm()),
@@ -101,8 +84,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
return self.afterMark(selectCurrentAfter, waitToReselect)
},
DisabledReason: singleItemIfNotBisecting,
Key: 'b',
Key: 'b',
},
{
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortShaToMark, info.OldTerm()),
@@ -114,8 +96,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
return self.afterMark(selectCurrentAfter, waitToReselect)
},
DisabledReason: singleItemIfNotBisecting,
Key: 'g',
Key: 'g',
},
{
Label: fmt.Sprintf(self.c.Tr.Bisect.SkipCurrent, shortShaToMark),
@@ -127,8 +108,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
return self.afterMark(selectCurrentAfter, waitToReselect)
},
DisabledReason: singleItemIfNotBisecting,
Key: 's',
Key: 's',
},
}
if info.GetCurrentSha() != "" && info.GetCurrentSha() != commit.Sha {
@@ -142,8 +122,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
return self.afterMark(selectCurrentAfter, waitToReselect)
},
DisabledReason: self.require(self.singleItemSelected())(),
Key: 'S',
Key: 'S',
}))
}
menuItems = append(menuItems, lo.ToPtr(types.MenuItem{
@@ -178,8 +157,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
},
DisabledReason: self.require(self.singleItemSelected())(),
Key: 'b',
Key: 'b',
},
{
Label: fmt.Sprintf(self.c.Tr.Bisect.MarkStart, commit.ShortSha(), info.OldTerm()),
@@ -195,8 +173,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
},
DisabledReason: self.require(self.singleItemSelected())(),
Key: 'g',
Key: 'g',
},
{
Label: self.c.Tr.Bisect.ChooseTerms,
@@ -288,7 +265,7 @@ func (self *BisectController) selectCurrentBisectCommit() {
// find index of commit with that sha, move cursor to that.
for i, commit := range self.c.Model().Commits {
if commit.Sha == info.GetCurrentSha() {
self.context().SetSelection(i)
self.context().SetSelectedLineIdx(i)
_ = self.context().HandleFocus(types.OnFocusOpts{})
break
}
@@ -296,6 +273,21 @@ func (self *BisectController) selectCurrentBisectCommit() {
}
}
func (self *BisectController) checkSelected(callback func(*models.Commit) error) func() error {
return func() error {
commit := self.context().GetSelected()
if commit == nil {
return nil
}
return callback(commit)
}
}
func (self *BisectController) Context() types.Context {
return self.context()
}
func (self *BisectController) context() *context.LocalCommitsContext {
return self.c.Contexts().LocalCommits
}

View File

@@ -17,147 +17,109 @@ import (
type BranchesController struct {
baseController
*ListControllerTrait[*models.Branch]
c *ControllerCommon
}
var _ types.IController = &BranchesController{}
func NewBranchesController(
c *ControllerCommon,
common *ControllerCommon,
) *BranchesController {
return &BranchesController{
baseController: baseController{},
c: c,
ListControllerTrait: NewListControllerTrait[*models.Branch](
c,
c.Contexts().Branches,
c.Contexts().Branches.GetSelected,
c.Contexts().Branches.GetSelectedItems,
),
c: common,
}
}
func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
return []*types.Binding{
{
Key: opts.GetKey(opts.Config.Universal.Select),
Handler: self.withItem(self.press),
GetDisabledReason: self.require(
self.singleItemSelected(),
self.notPulling,
),
Description: self.c.Tr.Checkout,
Tooltip: self.c.Tr.CheckoutTooltip,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Universal.Select),
Handler: self.checkSelected(self.press),
GetDisabledReason: self.getDisabledReasonForPress,
Description: self.c.Tr.Checkout,
},
{
Key: opts.GetKey(opts.Config.Universal.New),
Handler: self.withItem(self.newBranch),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.NewBranch,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Universal.New),
Handler: self.checkSelected(self.newBranch),
Description: self.c.Tr.NewBranch,
},
{
Key: opts.GetKey(opts.Config.Branches.CreatePullRequest),
Handler: self.withItem(self.handleCreatePullRequest),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.CreatePullRequest,
Key: opts.GetKey(opts.Config.Branches.CreatePullRequest),
Handler: self.checkSelected(self.handleCreatePullRequest),
Description: self.c.Tr.CreatePullRequest,
},
{
Key: opts.GetKey(opts.Config.Branches.ViewPullRequestOptions),
Handler: self.withItem(self.handleCreatePullRequestMenu),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.CreatePullRequestOptions,
OpensMenu: true,
Key: opts.GetKey(opts.Config.Branches.ViewPullRequestOptions),
Handler: self.checkSelected(self.handleCreatePullRequestMenu),
Description: self.c.Tr.CreatePullRequestOptions,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Branches.CopyPullRequestURL),
Handler: self.copyPullRequestURL,
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.CopyPullRequestURL,
Key: opts.GetKey(opts.Config.Branches.CopyPullRequestURL),
Handler: self.copyPullRequestURL,
Description: self.c.Tr.CopyPullRequestURL,
},
{
Key: opts.GetKey(opts.Config.Branches.CheckoutBranchByName),
Handler: self.checkoutByName,
Description: self.c.Tr.CheckoutByName,
Tooltip: self.c.Tr.CheckoutByNameTooltip,
},
{
Key: opts.GetKey(opts.Config.Branches.ForceCheckoutBranch),
Handler: self.forceCheckout,
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.ForceCheckout,
Tooltip: self.c.Tr.ForceCheckoutTooltip,
Key: opts.GetKey(opts.Config.Branches.ForceCheckoutBranch),
Handler: self.forceCheckout,
Description: self.c.Tr.ForceCheckout,
},
{
Key: opts.GetKey(opts.Config.Universal.Remove),
Handler: self.withItem(self.delete),
GetDisabledReason: self.require(self.singleItemSelected(self.branchIsReal)),
Description: self.c.Tr.Delete,
Tooltip: self.c.Tr.BranchDeleteTooltip,
OpensMenu: true,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Universal.Remove),
Handler: self.checkSelectedAndReal(self.delete),
Description: self.c.Tr.ViewDeleteOptions,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
Handler: opts.Guards.OutsideFilterMode(self.rebase),
GetDisabledReason: self.require(
self.singleItemSelected(self.notRebasingOntoSelf),
),
Description: self.c.Tr.RebaseBranch,
Tooltip: self.c.Tr.RebaseBranchTooltip,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
Handler: opts.Guards.OutsideFilterMode(self.rebase),
Description: self.c.Tr.RebaseBranch,
GetDisabledReason: self.getDisabledReasonForRebase,
},
{
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
Handler: opts.Guards.OutsideFilterMode(self.merge),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.Merge,
Tooltip: self.c.Tr.MergeBranchTooltip,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
Handler: opts.Guards.OutsideFilterMode(self.merge),
Description: self.c.Tr.MergeIntoCurrentBranch,
},
{
Key: opts.GetKey(opts.Config.Branches.FastForward),
Handler: self.withItem(self.fastForward),
GetDisabledReason: self.require(self.singleItemSelected(self.branchIsReal)),
Description: self.c.Tr.FastForward,
Tooltip: self.c.Tr.FastForwardTooltip,
Key: opts.GetKey(opts.Config.Branches.FastForward),
Handler: self.checkSelectedAndReal(self.fastForward),
Description: self.c.Tr.FastForward,
},
{
Key: opts.GetKey(opts.Config.Branches.CreateTag),
Handler: self.withItem(self.createTag),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.NewTag,
Key: opts.GetKey(opts.Config.Branches.CreateTag),
Handler: self.checkSelected(self.createTag),
Description: self.c.Tr.CreateTag,
},
{
Key: opts.GetKey(opts.Config.Branches.SortOrder),
Handler: self.createSortMenu,
Description: self.c.Tr.SortOrder,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
Handler: self.withItem(self.createResetMenu),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.ViewResetOptions,
OpensMenu: true,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
Handler: self.checkSelected(self.createResetMenu),
Description: self.c.Tr.ViewResetOptions,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Branches.RenameBranch),
Handler: self.withItem(self.rename),
GetDisabledReason: self.require(self.singleItemSelected(self.branchIsReal)),
Description: self.c.Tr.RenameBranch,
Key: opts.GetKey(opts.Config.Branches.RenameBranch),
Handler: self.checkSelectedAndReal(self.rename),
Description: self.c.Tr.RenameBranch,
},
{
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
Handler: self.withItem(self.viewUpstreamOptions),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.ViewBranchUpstreamOptions,
Tooltip: self.c.Tr.ViewBranchUpstreamOptionsTooltip,
ShortDescription: self.c.Tr.Upstream,
OpensMenu: true,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
Handler: self.checkSelected(self.viewUpstreamOptions),
Description: self.c.Tr.ViewBranchUpstreamOptions,
Tooltip: self.c.Tr.ViewBranchUpstreamOptionsTooltip,
OpensMenu: true,
},
}
}
@@ -203,6 +165,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
ShowBranchHeads: false,
})
},
Key: 'v',
}
unsetUpstreamItem := &types.MenuItem{
@@ -301,13 +264,13 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
}
if !selectedBranch.IsTrackingRemote() {
unsetUpstreamItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
unsetUpstreamItem.DisabledReason = self.c.Tr.UpstreamNotSetError
}
if !selectedBranch.RemoteBranchStoredLocally() {
viewDivergenceItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
upstreamResetItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
upstreamRebaseItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
viewDivergenceItem.DisabledReason = self.c.Tr.UpstreamNotSetError
upstreamResetItem.DisabledReason = self.c.Tr.UpstreamNotSetError
upstreamRebaseItem.DisabledReason = self.c.Tr.UpstreamNotSetError
}
options := []*types.MenuItem{
@@ -346,16 +309,16 @@ func (self *BranchesController) press(selectedBranch *models.Branch) error {
return self.c.Helpers().Refs.CheckoutRef(selectedBranch.Name, types.CheckoutRefOptions{})
}
func (self *BranchesController) notPulling() *types.DisabledReason {
func (self *BranchesController) getDisabledReasonForPress() string {
currentBranch := self.c.Helpers().Refs.GetCheckedOutRef()
if currentBranch != nil {
op := self.c.State().GetItemOperation(currentBranch)
if op == types.ItemOperationFastForwarding || op == types.ItemOperationPulling {
return &types.DisabledReason{Text: self.c.Tr.CantCheckoutBranchWhilePulling}
return self.c.Tr.CantCheckoutBranchWhilePulling
}
}
return nil
return ""
}
func (self *BranchesController) worktreeForBranch(branch *models.Branch) (*models.Worktree, bool) {
@@ -436,10 +399,6 @@ func (self *BranchesController) checkoutByName() error {
FindSuggestionsFunc: self.c.Helpers().Suggestions.GetRefsSuggestionsFunc(),
HandleConfirm: func(response string) error {
self.c.LogAction("Checkout branch")
_, branchName, found := self.c.Helpers().Refs.ParseRemoteBranchName(response)
if found {
return self.c.Helpers().Refs.CheckoutRemoteBranch(response, branchName)
}
return self.c.Helpers().Refs.CheckoutRef(response, types.CheckoutRefOptions{
OnRefNotFound: func(ref string) error {
return self.c.Confirm(types.ConfirmOpts{
@@ -466,8 +425,8 @@ func (self *BranchesController) createNewBranchWithName(newBranchName string) er
return self.c.Error(err)
}
self.context().SetSelection(0)
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, KeepBranchSelectionIndex: true})
self.context().SetSelectedLineIdx(0)
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
}
func (self *BranchesController) checkedOutByOtherWorktree(branch *models.Branch) bool {
@@ -566,7 +525,7 @@ func (self *BranchesController) delete(branch *models.Branch) error {
},
}
if checkedOutBranch.Name == branch.Name {
localDeleteItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.CantDeleteCheckOutBranch}
localDeleteItem.DisabledReason = self.c.Tr.CantDeleteCheckOutBranch
}
remoteDeleteItem := &types.MenuItem{
@@ -577,7 +536,7 @@ func (self *BranchesController) delete(branch *models.Branch) error {
},
}
if !branch.IsTrackingRemote() || branch.UpstreamGone {
remoteDeleteItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
remoteDeleteItem.DisabledReason = self.c.Tr.UpstreamNotSetError
}
menuTitle := utils.ResolvePlaceholderString(
@@ -603,14 +562,14 @@ func (self *BranchesController) rebase() error {
return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName)
}
func (self *BranchesController) notRebasingOntoSelf(branch *models.Branch) *types.DisabledReason {
selectedBranchName := branch.Name
func (self *BranchesController) getDisabledReasonForRebase() string {
selectedBranchName := self.context().GetSelected().Name
checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef().Name
if selectedBranchName == checkedOutBranch {
return &types.DisabledReason{Text: self.c.Tr.CantRebaseOntoSelf}
return self.c.Tr.CantRebaseOntoSelf
}
return nil
return ""
}
func (self *BranchesController) fastForward(branch *models.Branch) error {
@@ -669,7 +628,7 @@ func (self *BranchesController) createSortMenu() error {
if self.c.GetAppState().LocalBranchSortOrder != sortOrder {
self.c.GetAppState().LocalBranchSortOrder = sortOrder
self.c.SaveAppStateAndLogError()
self.c.Contexts().Branches.SetSelection(0)
self.c.Contexts().Branches.SetSelectedLineIdx(0)
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}})
}
return nil
@@ -700,7 +659,7 @@ func (self *BranchesController) rename(branch *models.Branch) error {
// now that we've got our stuff again we need to find that branch and reselect it.
for i, newBranch := range self.c.Model().Branches {
if newBranch.Name == newBranchName {
self.context().SetSelection(i)
self.context().SetSelectedLineIdx(i)
if err := self.context().HandleRender(); err != nil {
return err
}
@@ -795,10 +754,24 @@ func (self *BranchesController) createPullRequest(from string, to string) error
return nil
}
func (self *BranchesController) branchIsReal(branch *models.Branch) *types.DisabledReason {
if !branch.IsRealBranch() {
return &types.DisabledReason{Text: self.c.Tr.SelectedItemIsNotABranch}
}
func (self *BranchesController) checkSelected(callback func(*models.Branch) error) func() error {
return func() error {
selectedItem := self.context().GetSelected()
if selectedItem == nil {
return nil
}
return nil
return callback(selectedItem)
}
}
func (self *BranchesController) checkSelectedAndReal(callback func(*models.Branch) error) func() error {
return func() error {
selectedItem := self.context().GetSelected()
if selectedItem == nil || !selectedItem.IsRealBranch() {
return nil
}
return callback(selectedItem)
}
}

View File

@@ -12,11 +12,11 @@ type CommandLogController struct {
var _ types.IController = &CommandLogController{}
func NewCommandLogController(
c *ControllerCommon,
common *ControllerCommon,
) *CommandLogController {
return &CommandLogController{
baseController: baseController{},
c: c,
c: common,
}
}

View File

@@ -13,11 +13,11 @@ type CommitDescriptionController struct {
var _ types.IController = &CommitMessageController{}
func NewCommitDescriptionController(
c *ControllerCommon,
common *ControllerCommon,
) *CommitDescriptionController {
return &CommitDescriptionController{
baseController: baseController{},
c: c,
c: common,
}
}
@@ -36,8 +36,8 @@ func (self *CommitDescriptionController) GetKeybindings(opts types.KeybindingsOp
Handler: self.confirm,
},
{
Key: opts.GetKey(opts.Config.CommitMessage.CommitMenu),
Handler: self.openCommitMenu,
Key: opts.GetKey(opts.Config.CommitMessage.SwitchToEditor),
Handler: self.switchToEditor,
},
}
@@ -64,7 +64,6 @@ func (self *CommitDescriptionController) confirm() error {
return self.c.Helpers().Commits.HandleCommitConfirm()
}
func (self *CommitDescriptionController) openCommitMenu() error {
authorSuggestion := self.c.Helpers().Suggestions.GetAuthorsSuggestionsFunc()
return self.c.Helpers().Commits.OpenCommitMenu(authorSuggestion)
func (self *CommitDescriptionController) switchToEditor() error {
return self.c.Helpers().Commits.SwitchToEditor()
}

View File

@@ -3,7 +3,6 @@ package controllers
import (
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -15,11 +14,11 @@ type CommitMessageController struct {
var _ types.IController = &CommitMessageController{}
func NewCommitMessageController(
c *ControllerCommon,
common *ControllerCommon,
) *CommitMessageController {
return &CommitMessageController{
baseController: baseController{},
c: c,
c: common,
}
}
@@ -48,8 +47,8 @@ func (self *CommitMessageController) GetKeybindings(opts types.KeybindingsOpts)
Handler: self.switchToCommitDescription,
},
{
Key: opts.GetKey(opts.Config.CommitMessage.CommitMenu),
Handler: self.openCommitMenu,
Key: opts.GetKey(opts.Config.CommitMessage.SwitchToEditor),
Handler: self.switchToEditor,
},
}
@@ -89,6 +88,10 @@ func (self *CommitMessageController) switchToCommitDescription() error {
return nil
}
func (self *CommitMessageController) switchToEditor() error {
return self.c.Helpers().Commits.SwitchToEditor()
}
func (self *CommitMessageController) handleCommitIndexChange(value int) error {
currentIndex := self.context().GetSelectedIndex()
newIndex := currentIndex + value
@@ -97,7 +100,7 @@ func (self *CommitMessageController) handleCommitIndexChange(value int) error {
self.c.Helpers().Commits.SetMessageAndDescriptionInView(self.context().GetHistoryMessage())
return nil
} else if currentIndex == context.NoCommitIndex {
self.context().SetHistoryMessage(self.c.Helpers().Commits.JoinCommitMessageAndUnwrappedDescription())
self.context().SetHistoryMessage(self.c.Helpers().Commits.JoinCommitMessageAndDescription())
}
validCommit, err := self.setCommitMessageAtIndex(newIndex)
@@ -116,9 +119,6 @@ func (self *CommitMessageController) setCommitMessageAtIndex(index int) (bool, e
}
return false, self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr)
}
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
}
self.c.Helpers().Commits.UpdateCommitPanelView(commitMessage)
return true, nil
}
@@ -130,8 +130,3 @@ func (self *CommitMessageController) confirm() error {
func (self *CommitMessageController) close() error {
return self.c.Helpers().Commits.CloseCommitMessagePanel()
}
func (self *CommitMessageController) openCommitMenu() error {
authorSuggestion := self.c.Helpers().Suggestions.GetAuthorsSuggestionsFunc()
return self.c.Helpers().Commits.OpenCommitMenu(authorSuggestion)
}

View File

@@ -1,112 +1,77 @@
package controllers
import (
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/patch"
"github.com/jesseduffield/lazygit/pkg/constants"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)
type CommitFilesController struct {
baseController
*ListControllerTrait[*filetree.CommitFileNode]
c *ControllerCommon
}
var _ types.IController = &CommitFilesController{}
func NewCommitFilesController(
c *ControllerCommon,
common *ControllerCommon,
) *CommitFilesController {
return &CommitFilesController{
baseController: baseController{},
c: c,
ListControllerTrait: NewListControllerTrait[*filetree.CommitFileNode](
c,
c.Contexts().CommitFiles,
c.Contexts().CommitFiles.GetSelected,
c.Contexts().CommitFiles.GetSelectedItems,
),
c: common,
}
}
func (self *CommitFilesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
bindings := []*types.Binding{
{
Key: opts.GetKey(opts.Config.CommitFiles.CheckoutCommitFile),
Handler: self.withItem(self.checkout),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.Checkout,
Tooltip: self.c.Tr.CheckoutCommitFileTooltip,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.CommitFiles.CheckoutCommitFile),
Handler: self.checkSelected(self.checkout),
Description: self.c.Tr.CheckoutCommitFile,
},
{
Key: opts.GetKey(opts.Config.Universal.Remove),
Handler: self.withItems(self.discard),
GetDisabledReason: self.require(self.itemsSelected()),
Description: self.c.Tr.Remove,
Tooltip: self.c.Tr.DiscardOldFileChangeTooltip,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Universal.Remove),
Handler: self.checkSelected(self.discard),
Description: self.c.Tr.DiscardOldFileChange,
},
{
Key: opts.GetKey(opts.Config.Universal.OpenFile),
Handler: self.withItem(self.open),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.OpenFile,
Tooltip: self.c.Tr.OpenFileTooltip,
Key: opts.GetKey(opts.Config.Universal.OpenFile),
Handler: self.checkSelected(self.open),
Description: self.c.Tr.OpenFile,
},
{
Key: opts.GetKey(opts.Config.Universal.Edit),
Handler: self.withItems(self.edit),
GetDisabledReason: self.require(self.itemsSelected(self.canEditFiles)),
Description: self.c.Tr.Edit,
Tooltip: self.c.Tr.EditFileTooltip,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Universal.Edit),
Handler: self.checkSelected(self.edit),
Description: self.c.Tr.EditFile,
},
{
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
Handler: self.withItem(self.openDiffTool),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.OpenDiffTool,
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
Handler: self.checkSelected(self.openDiffTool),
Description: self.c.Tr.OpenDiffTool,
},
{
Key: opts.GetKey(opts.Config.Universal.Select),
Handler: self.withItems(self.toggleForPatch),
GetDisabledReason: self.require(self.itemsSelected()),
Description: self.c.Tr.ToggleAddToPatch,
Tooltip: utils.ResolvePlaceholderString(self.c.Tr.ToggleAddToPatchTooltip,
map[string]string{"doc": constants.Links.Docs.CustomPatchDemo},
),
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Universal.Select),
Handler: self.checkSelected(self.toggleForPatch),
Description: self.c.Tr.ToggleAddToPatch,
},
{
Key: opts.GetKey(opts.Config.Files.ToggleStagedAll),
Handler: self.withItem(self.toggleAllForPatch),
Handler: self.checkSelected(self.toggleAllForPatch),
Description: self.c.Tr.ToggleAllInPatch,
Tooltip: utils.ResolvePlaceholderString(self.c.Tr.ToggleAllInPatchTooltip,
map[string]string{"doc": constants.Links.Docs.CustomPatchDemo},
),
},
{
Key: opts.GetKey(opts.Config.Universal.GoInto),
Handler: self.withItem(self.enter),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.EnterCommitFile,
Tooltip: self.c.Tr.EnterCommitFileTooltip,
Key: opts.GetKey(opts.Config.Universal.GoInto),
Handler: self.checkSelected(self.enter),
Description: self.c.Tr.EnterFile,
},
{
Key: opts.GetKey(opts.Config.Files.ToggleTreeView),
Handler: self.toggleTreeView,
Description: self.c.Tr.ToggleTreeView,
Tooltip: self.c.Tr.ToggleTreeViewTooltip,
},
}
@@ -124,6 +89,21 @@ func (self *CommitFilesController) GetMouseKeybindings(opts types.KeybindingsOpt
}
}
func (self *CommitFilesController) checkSelected(callback func(*filetree.CommitFileNode) error) func() error {
return func() error {
selected := self.context().GetSelected()
if selected == nil {
return nil
}
return callback(selected)
}
}
func (self *CommitFilesController) Context() types.Context {
return self.context()
}
func (self *CommitFilesController) context() *context.CommitFilesContext {
return self.c.Contexts().CommitFiles
}
@@ -176,51 +156,40 @@ func (self *CommitFilesController) checkout(node *filetree.CommitFileNode) error
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
}
func (self *CommitFilesController) discard(selectedNodes []*filetree.CommitFileNode) error {
func (self *CommitFilesController) discard(node *filetree.CommitFileNode) error {
parentContext, ok := self.c.CurrentContext().GetParentContext()
if !ok || parentContext.GetKey() != context.LOCAL_COMMITS_CONTEXT_KEY {
return self.c.ErrorMsg(self.c.Tr.CanOnlyDiscardFromLocalCommits)
}
if node.File == nil {
return self.c.ErrorMsg(self.c.Tr.DiscardNotSupportedForDirectory)
}
if ok, err := self.c.Helpers().PatchBuilding.ValidateNormalWorkingTreeState(); !ok {
return err
}
prompt := self.c.Tr.DiscardFileChangesPrompt
if node.File.Added() {
prompt = self.c.Tr.DiscardAddedFileChangesPrompt
} else if node.File.Deleted() {
prompt = self.c.Tr.DiscardDeletedFileChangesPrompt
}
return 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
selectedNodes = normalisedSelectedCommitFileNodes(selectedNodes)
// Reset the current patch if there is one.
if self.c.Git().Patch.PatchBuilder.Active() {
self.c.Git().Patch.PatchBuilder.Reset()
if err := self.c.Refresh(types.RefreshOptions{Mode: types.BLOCK_UI}); err != nil {
self.c.LogAction(self.c.Tr.Actions.DiscardOldFileChange)
if err := self.c.Git().Rebase.DiscardOldFileChanges(self.c.Model().Commits, self.c.Contexts().LocalCommits.GetSelectedLineIdx(), node.GetPath()); err != nil {
if err := self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err); err != nil {
return err
}
}
for _, node := range selectedNodes {
err := node.ForEachFile(func(file *models.CommitFile) error {
filePaths = append(filePaths, file.GetPath())
return nil
})
if err != nil {
return self.c.Error(err)
}
}
err := self.c.Git().Rebase.DiscardOldFileChanges(self.c.Model().Commits, self.c.Contexts().LocalCommits.GetSelectedLineIdx(), filePaths)
if err := self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err); err != nil {
return err
}
if self.context().RangeSelectEnabled() {
self.context().GetList().CancelRangeSelect()
}
return self.c.Refresh(types.RefreshOptions{Mode: types.SYNC})
return self.c.Refresh(types.RefreshOptions{Mode: types.BLOCK_UI})
})
},
})
@@ -230,22 +199,12 @@ func (self *CommitFilesController) open(node *filetree.CommitFileNode) error {
return self.c.Helpers().Files.OpenFile(node.GetPath())
}
func (self *CommitFilesController) edit(nodes []*filetree.CommitFileNode) error {
return self.c.Helpers().Files.EditFiles(lo.FilterMap(nodes,
func(node *filetree.CommitFileNode, _ int) (string, bool) {
return node.GetPath(), node.IsFile()
}))
}
func (self *CommitFilesController) canEditFiles(nodes []*filetree.CommitFileNode) *types.DisabledReason {
if lo.NoneBy(nodes, func(node *filetree.CommitFileNode) bool { return node.IsFile() }) {
return &types.DisabledReason{
Text: self.c.Tr.ErrCannotEditDirectory,
ShowErrorInPanel: true,
}
func (self *CommitFilesController) edit(node *filetree.CommitFileNode) error {
if node.File == nil {
return self.c.ErrorMsg(self.c.Tr.ErrCannotEditDirectory)
}
return nil
return self.c.Helpers().Files.EditFile(node.GetPath())
}
func (self *CommitFilesController) openDiffTool(node *filetree.CommitFileNode) error {
@@ -264,7 +223,7 @@ func (self *CommitFilesController) openDiffTool(node *filetree.CommitFileNode) e
return err
}
func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.CommitFileNode) error {
func (self *CommitFilesController) toggleForPatch(node *filetree.CommitFileNode) error {
toggle := func() error {
return self.c.WithWaitingStatus(self.c.Tr.UpdatingPatch, func(gocui.Task) error {
if !self.c.Git().Patch.PatchBuilder.Active() {
@@ -273,29 +232,21 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm
}
}
selectedNodes = normalisedSelectedCommitFileNodes(selectedNodes)
// Find if any file in the selection is unselected or partially added
adding := lo.SomeBy(selectedNodes, func(node *filetree.CommitFileNode) bool {
return node.SomeFile(func(file *models.CommitFile) bool {
fileStatus := self.c.Git().Patch.PatchBuilder.GetFileStatus(file.Name, self.context().GetRef().RefName())
return fileStatus == patch.PART || fileStatus == patch.UNSELECTED
})
// if there is any file that hasn't been fully added we'll fully add everything,
// otherwise we'll remove everything
adding := node.SomeFile(func(file *models.CommitFile) bool {
return self.c.Git().Patch.PatchBuilder.GetFileStatus(file.Name, self.context().GetRef().RefName()) != patch.WHOLE
})
patchOperationFunction := self.c.Git().Patch.PatchBuilder.RemoveFile
if adding {
patchOperationFunction = self.c.Git().Patch.PatchBuilder.AddFileWhole
}
for _, node := range selectedNodes {
err := node.ForEachFile(func(file *models.CommitFile) error {
return patchOperationFunction(file.Name)
})
if err != nil {
return self.c.Error(err)
err := node.ForEachFile(func(file *models.CommitFile) error {
if adding {
return self.c.Git().Patch.PatchBuilder.AddFileWhole(file.Name)
} else {
return self.c.Git().Patch.PatchBuilder.RemoveFile(file.Name)
}
})
if err != nil {
return self.c.Error(err)
}
if self.c.Git().Patch.PatchBuilder.IsEmpty() {
@@ -322,7 +273,7 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm
func (self *CommitFilesController) toggleAllForPatch(_ *filetree.CommitFileNode) error {
root := self.context().CommitFileTreeViewModel.GetRoot()
return self.toggleForPatch([]*filetree.CommitFileNode{root})
return self.toggleForPatch(root)
}
func (self *CommitFilesController) startPatchBuilder() error {
@@ -386,23 +337,3 @@ func (self *CommitFilesController) toggleTreeView() error {
return self.c.PostRefreshUpdate(self.context())
}
// 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 {
return lo.Filter(selectedNodes, func(node *filetree.CommitFileNode, _ int) bool {
return !isDescendentOfSelectedCommitFileNodes(node, selectedNodes)
})
}
func isDescendentOfSelectedCommitFileNodes(node *filetree.CommitFileNode, selectedNodes []*filetree.CommitFileNode) bool {
for _, selectedNode := range selectedNodes {
selectedNodePath := selectedNode.GetPath()
nodePath := node.GetPath()
if strings.HasPrefix(nodePath, selectedNodePath) && nodePath != selectedNodePath {
return true
}
}
return false
}

View File

@@ -13,27 +13,27 @@ type ConfirmationController struct {
var _ types.IController = &ConfirmationController{}
func NewConfirmationController(
c *ControllerCommon,
common *ControllerCommon,
) *ConfirmationController {
return &ConfirmationController{
baseController: baseController{},
c: c,
c: common,
}
}
func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
bindings := []*types.Binding{
{
Key: opts.GetKey(opts.Config.Universal.Confirm),
Handler: func() error { return self.context().State.OnConfirm() },
Description: self.c.Tr.Confirm,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Universal.Confirm),
Handler: func() error { return self.context().State.OnConfirm() },
Description: self.c.Tr.Confirm,
Display: true,
},
{
Key: opts.GetKey(opts.Config.Universal.Return),
Handler: func() error { return self.context().State.OnClose() },
Description: self.c.Tr.CloseCancel,
DisplayOnScreen: true,
Key: opts.GetKey(opts.Config.Universal.Return),
Handler: func() error { return self.context().State.OnClose() },
Description: self.c.Tr.CloseCancel,
Display: true,
},
{
Key: opts.GetKey(opts.Config.Universal.TogglePanel),

View File

@@ -31,11 +31,11 @@ type ContextLinesController struct {
var _ types.IController = &ContextLinesController{}
func NewContextLinesController(
c *ControllerCommon,
common *ControllerCommon,
) *ContextLinesController {
return &ContextLinesController{
baseController: baseController{},
c: c,
c: common,
}
}
@@ -45,13 +45,11 @@ func (self *ContextLinesController) GetKeybindings(opts types.KeybindingsOpts) [
Key: opts.GetKey(opts.Config.Universal.IncreaseContextInDiffView),
Handler: self.Increase,
Description: self.c.Tr.IncreaseContextInDiffView,
Tooltip: self.c.Tr.IncreaseContextInDiffViewTooltip,
},
{
Key: opts.GetKey(opts.Config.Universal.DecreaseContextInDiffView),
Handler: self.Decrease,
Description: self.c.Tr.DecreaseContextInDiffView,
Tooltip: self.c.Tr.DecreaseContextInDiffViewTooltip,
},
}

View File

@@ -20,12 +20,15 @@ func (self *CustomCommandAction) Call() error {
HandleConfirm: func(command string) error {
if self.shouldSaveCommand(command) {
self.c.GetAppState().CustomCommandsHistory = utils.Limit(
lo.Uniq(append([]string{command}, self.c.GetAppState().CustomCommandsHistory...)),
lo.Uniq(append(self.c.GetAppState().CustomCommandsHistory, command)),
1000,
)
}
self.c.SaveAppStateAndLogError()
err := self.c.SaveAppState()
if err != nil {
self.c.Log.Error(err)
}
self.c.LogAction(self.c.Tr.Actions.CustomCommand)
return self.c.RunSubprocessAndRefresh(
@@ -36,9 +39,10 @@ func (self *CustomCommandAction) Call() error {
}
func (self *CustomCommandAction) GetCustomCommandsHistorySuggestionsFunc() func(string) []*types.Suggestion {
history := self.c.GetAppState().CustomCommandsHistory
// reversing so that we display the latest command first
history := lo.Reverse(self.c.GetAppState().CustomCommandsHistory)
return helpers.FilterFunc(history, self.c.UserConfig.Gui.UseFuzzySearch())
return helpers.FuzzySearchFunc(history)
}
// this mimics the shell functionality `ignorespace`

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