Skip to content

Commit d567731

Browse files
committed
Make copies of the docs and schema folders
The plan is to keep the original docs and schema folders unchanged for the duration of a release; we'll only continuously update the -master copies. Right before a new release we will copy them over.
1 parent e3a1fe5 commit d567731

27 files changed

+8175
-0
lines changed

docs-master/Config.md

Lines changed: 1190 additions & 0 deletions
Large diffs are not rendered by default.

docs-master/Custom_Command_Keybindings.md

Lines changed: 370 additions & 0 deletions
Large diffs are not rendered by default.

docs-master/Custom_Pagers.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Custom Pagers
2+
3+
Lazygit supports custom pagers, [configured](/docs/Config.md) in the config.yml file (which can be opened by pressing `e` in the Status panel).
4+
5+
Support does not extend to Windows users, because we're making use of a package which doesn't have Windows support. However, see [below](#emulating-custom-pagers-on-windows) for a workaround.
6+
7+
Multiple pagers are supported; you can cycle through them with the `|` key. This can be useful if you usually prefer a particular pager, but want to use a different one for certain kinds of diffs.
8+
9+
Pagers are configured with the `pagers` array in the git section; here's an example for a multi-pager setup:
10+
11+
```yaml
12+
git:
13+
pagers:
14+
- pager: delta --dark --paging=never
15+
- pager: ydiff -p cat -s --wrap --width={{columnWidth}}
16+
colorArg: never
17+
- externalDiffCommand: difft --color=always
18+
```
19+
20+
The `colorArg` key is for whether you want the `--color=always` arg in your `git diff` command. Some pagers want it set to `always`, others want it set to `never`. The default is `always`, since that's what most pagers need.
21+
22+
## Delta:
23+
24+
```yaml
25+
git:
26+
pagers:
27+
- pager: delta --dark --paging=never
28+
```
29+
30+
![](https://i.imgur.com/QJpQkF3.png)
31+
32+
A cool feature of delta is --hyperlinks, which renders clickable links for the line numbers in the left margin, and lazygit supports these. To use them, set the `pager:` config to `delta --dark --paging=never --line-numbers --hyperlinks --hyperlinks-file-link-format="lazygit-edit://{path}:{line}"`; this allows you to click on an underlined line number in the diff to jump right to that same line in your editor.
33+
34+
## Diff-so-fancy
35+
36+
```yaml
37+
git:
38+
pagers:
39+
- pager: diff-so-fancy
40+
```
41+
42+
![](https://i.imgur.com/rjH1TpT.png)
43+
44+
## ydiff
45+
46+
```yaml
47+
gui:
48+
sidePanelWidth: 0.2 # gives you more space to show things side-by-side
49+
git:
50+
pagers:
51+
- colorArg: never
52+
pager: ydiff -p cat -s --wrap --width={{columnWidth}}
53+
```
54+
55+
![](https://i.imgur.com/vaa8z0H.png)
56+
57+
Be careful with this one, I think the homebrew and pip versions are behind master. I needed to directly download the ydiff script to get the no-pager functionality working.
58+
59+
## Using external diff commands
60+
61+
Some diff tools can't work as a simple pager like the ones above do, because they need access to the entire diff, so just post-processing git's diff is not enough for them. The most notable example is probably [difftastic](https://difftastic.wilfred.me.uk).
62+
63+
These can be used in lazygit by using the `externalDiffCommand` config; in the case of difftastic, that could be
64+
65+
```yaml
66+
git:
67+
pagers:
68+
- externalDiffCommand: difft --color=always
69+
```
70+
71+
The `colorArg` and `pager` options are not used in this case.
72+
73+
You can add whatever extra arguments you prefer for your difftool; for instance
74+
75+
```yaml
76+
git:
77+
pagers:
78+
- externalDiffCommand: difft --color=always --display=inline --syntax-highlight=off
79+
```
80+
81+
Instead of setting this command in lazygit's `externalDiffCommand` config, you can also tell lazygit to use the external diff command that is configured in git itself (`diff.external`), by using
82+
83+
```yaml
84+
git:
85+
pagers:
86+
- useExternalDiffGitConfig: true
87+
```
88+
89+
This can be useful if you also want to use it for diffs on the command line, and it also has the advantage that you can configure it per file type in `.gitattributes`; see https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.
90+
91+
## Emulating custom pagers on Windows
92+
93+
There is a trick to emulate custom pagers on Windows using a Powershell script configured as an external diff command. It's not perfect, but certainly better than nothing. To do this, save the following script as `lazygit-pager.ps1` at a convenient place on your disk:
94+
95+
```pwsh
96+
#!/usr/bin/env pwsh
97+
98+
$old = $args[1].Replace('\', '/')
99+
$new = $args[4].Replace('\', '/')
100+
$path = $args[0]
101+
git diff --no-index --no-ext-diff $old $new
102+
| %{ $_.Replace($old, $path).Replace($new, $path) }
103+
| delta --width=$env:LAZYGIT_COLUMNS
104+
```
105+
106+
Use the pager of your choice with the arguments you like in the last line of the script. Personally I wouldn't want to use lazygit anymore without delta's `--hyperlinks --hyperlinks-file-link-format="lazygit-edit://{path}:{line}"` args, see [above](#delta).
107+
108+
In your lazygit config, use
109+
110+
```yml
111+
git:
112+
pagers:
113+
- externalDiffCommand: "C:/wherever/lazygit-pager.ps1"
114+
```
115+
116+
The main limitation of this approach compared to a "real" pager is that renames are not displayed correctly; they are shown as if they were modifications of the old file. (This affects only the hunk headers; the diff itself is always correct.)

docs-master/Fixup_Commits.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Fixup Commits
2+
3+
## Background
4+
5+
There's this common scenario that you have a PR in review, the reviewer is
6+
requesting some changes, and you make those changes and would normally simply
7+
squash them into the original commit that they came from. If you do that,
8+
however, there's no way for the reviewer to see what you changed. You could just
9+
make a separate commit with those changes at the end of the branch, but this is
10+
not ideal because it results in a git history that is not very clean.
11+
12+
To help with this, git has a concept of fixup commits: you do make a separate
13+
commit, but the subject of this commit is the string "fixup! " followed by the
14+
original commit subject. This both tells the reviewer what's going on (you are
15+
making a change that you later will squash into the designated commit), and it
16+
provides an easy way to actually perform this squash operation when you are
17+
ready to do that (before merging).
18+
19+
## Creating fixup commits
20+
21+
You could of course create fixup commits manually by typing in the commit
22+
message with the prefix yourself. But lazygit has an easier way to do that:
23+
in the Commits view, select the commit that you want to create a fixup for, and
24+
press shift-F (for "Create fixup commit for this commit"). This automatically
25+
creates a commit with the appropriate subject line.
26+
27+
Don't confuse this with the lowercase "f" command ("Fixup commit"); that one
28+
squashes the selected commit into its parent, this is not what we want here.
29+
30+
## Creating amend commits
31+
32+
There's a special type of fixup commit that uses "amend!" instead of "fixup!" in
33+
the commit message subject; in addition to fixing up the original commit with
34+
changes it allows you to also (or only) change the commit message of the
35+
original commit. The menu that appears when pressing shift-F has options for
36+
both of these; they bring up a commit message panel similar to when you reword a
37+
commit, but then create the "amend!" commit containing the new message. Note
38+
that in that panel you only type the new message as you want it to be
39+
eventually; lazygit then takes care of formatting the "amend!" commit
40+
appropriately for you (with the subject of your new message moving into the body
41+
of the "amend!" commit).
42+
43+
## Squashing fixup commits
44+
45+
When you're ready to merge the branch and want to squash all these fixup commits
46+
that you created, that's very easy to do: select the first commit of your branch
47+
and hit shift-S (for "Squash all 'fixup!' commits above selected commit
48+
(autosquash)"). Boom, done.
49+
50+
## Finding the commit to create a fixup for
51+
52+
When you are making changes to code that you changed earlier in a long branch,
53+
it can be tedious to find the commit to squash it into. Lazygit has a command to
54+
help you with this, too: in the Files view, press ctrl-f to select the right
55+
base commit in the Commits view automatically. From there, you can either press
56+
shift-F to create a fixup commit for it, or shift-A to amend your changes into
57+
the commit if you haven't published your branch yet.
58+
59+
If you have many modifications in your working copy, it is a good idea to stage
60+
related changes that are meant to go into the same fixup commit; if no changes
61+
are staged, ctrl-f works on all unstaged modifications, and then it might show
62+
an error if it finds multiple different base commits. If you are interested in
63+
what the command does to do its magic, and how you can help it work better, you
64+
may want to read the [design document](dev/Find_Base_Commit_For_Fixup_Design.md)
65+
that describes this.

docs-master/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Documentation Overview
2+
3+
* [Configuration](./Config.md).
4+
* [Custom Commands](./Custom_Command_Keybindings.md)
5+
* [Custom Pagers](./Custom_Pagers.md)
6+
* [Dev docs](./dev)
7+
* [Keybindings](./keybindings)
8+
* [Undo/Redo](./Undoing.md)
9+
* [Range Select](./Range_Select.md)
10+
* [Searching/Filtering](./Searching.md)
11+
* [Stacked Branches](./Stacked_Branches.md)

docs-master/Range_Select.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Range Select
2+
3+
Some actions can be performed on a range of contiguous items. For example:
4+
* staging multiple files at once
5+
* squashing multiple commits at once
6+
* copying (for cherry-pick) multiple commits at once
7+
8+
There are two ways to select a range of items:
9+
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.
10+
2. Non-sticky range select: Press shift+up or shift+down to expand the selection. To reset the selection, press up/down without shift.
11+
12+
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.
13+
14+
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.

docs-master/Searching.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Searching/Filtering
2+
3+
## View searching/filtering
4+
5+
Depending on the currently focused view, hitting '/' will bring up a filter or search prompt. When filtering, the contents of the view will be filtered down to only those lines which match the query string. When searching, the contents of the view are not filtered, but matching lines are highlighted and you can iterate through matches with `n`/`N`.
6+
7+
We intend to support filtering for the files view soon, but at the moment it uses searching. We intend to continue using search for the commits view because you typically care about the commits that come before/after a matching commit.
8+
9+
If you would like both filtering and searching to be enabled on a given view, please raise an issue for this.
10+
11+
## Filtering files by status
12+
13+
You can filter the files view to only show staged/unstaged files by pressing `<c-b>` in the files view.
14+
15+
## Filtering commits by file path
16+
17+
You can filter the commits view to only show commits which contain changes to a given file path.
18+
19+
You can do this in a couple of ways:
20+
1) Start lazygit with the -f flag e.g. `lazygit -f my/path`
21+
2) From within lazygit, press `<c-s>` and then enter the path of the file you want to filter by

docs-master/Stacked_Branches.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Working with stacked branches
2+
3+
When working on a large branch it can often be useful to break it down into
4+
smaller pieces, and it can help to create separate branches for each independent
5+
chunk of changes. For example, you could have one branch for preparatory
6+
refactorings, one for backend changes, and one for frontend changes. Those
7+
branches would then all be stacked onto each other.
8+
9+
Git has support for rebasing such a stack as a whole; you can enable it by
10+
setting the git config `rebase.updateRefs` to true. If you then rebase the
11+
topmost branch of the stack, the other ones in the stack will follow. This
12+
includes interactive rebases, so for example amending a commit in the first
13+
branch of the stack will "just work" in the sense that it keeps the other
14+
branches properly stacked onto it.
15+
16+
Lazygit visualizes the individual branch heads in the stack by marking them with a
17+
cyan asterisk (or a cyan branch symbol if you are using [nerd
18+
fonts](Config.md#display-nerd-fonts-icons)).

docs-master/Undoing.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Undo/Redo in lazygit
2+
3+
You can undo the last action by pressing 'z' and redo with `ctrl+z`. Here we drop a couple of commits and then undo the actions.
4+
Undo uses the reflog which is specific to commits and branches so we can't undo changes to the working tree or stash.
5+
6+
![undo](../../assets/demo/undo-compressed.gif)
7+
8+
## How it works
9+
10+
If you're as clumsy as me you'll probably have felt the pain of botching an interactive rebase or doing a hard reset onto the wrong commit. Luckily, the reflog allows you to trace your steps and make things right again, but I personally can't stand trying to make sense of the reflog.
11+
12+
Lazygit can read through your reflog for you and walk back action by action so that you don't even need to read the reflog. If lazygit finds a reflog entry where you checked out a branch, we'll checkout the original branch. If the entry is from a commit being applied, we'll go back to the commit before that. If we hit an interactive rebase, we'll go back to the commit you were on just before you started it.
13+
14+
## You can even undo things you did outside of lazygit!
15+
16+
Because lazygit just uses the reflog to keep track of things, it doesn't matter whether you're trying to undo something you did in lazygit or directly on the command line. You can open lazygit for the first time and start undoing thing in your repo! Likewise, lazygit marks its undos/redos in the reflog so if you quit the application and come back, lazygit still knows where you're up to.
17+
18+
## Limitations
19+
20+
There are limitations: firstly, lazygit can only undo things that are recorded in the reflog. That means changes to your working tree or stash aren't covered. Secondly, anything permanent you do like pushing to a remote can't be undone. Thirdly, actions like creating a branch won't be undone, because they're not stored in the reflog.
21+
22+
If you are mid-rebase, undo/redo is not supported, because the reflog doesn't contain enough information about what specific things have happened inside that rebase. If you want to undo out of a rebase, it's best to abort the rebase (the default keybinding for bringing up rebase options is 'm').
23+
24+
Undo/Redo is a new feature so if you find a bug let us know. The worst case scenario is that you'll just need to look at your reflog and manually put yourself back on track.

docs-master/dev/Busy.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Knowing when Lazygit is busy/idle
2+
3+
## The use-case
4+
5+
This topic deserves its own doc because there are a few touch points for it. We have a use-case for knowing when Lazygit is idle or busy because integration tests follow the following process:
6+
1) press a key
7+
2) wait until Lazygit is idle
8+
3) run assertion / press another key
9+
4) repeat
10+
11+
In the past the process was:
12+
1) press a key
13+
2) run assertion
14+
3) if assertion fails, wait a bit and retry
15+
4) repeat
16+
17+
The old process was problematic because an assertion may give a false positive due to the contents of some view not yet having changed since the last key was pressed.
18+
19+
## The solution
20+
21+
First, it's important to distinguish three different types of goroutines:
22+
* The UI goroutine, of which there is only one, which infinitely processes a queue of events
23+
* Worker goroutines, which do some work and then typically enqueue an event in the UI goroutine to display the results
24+
* Background goroutines, which periodically spawn worker goroutines (e.g. doing a git fetch every minute)
25+
26+
The point of distinguishing worker goroutines from background goroutines is that when any worker goroutine is running, we consider Lazygit to be 'busy', whereas this is not the case with background goroutines. It would be pointless to have background goroutines be considered 'busy' because then Lazygit would be considered busy for the entire duration of the program!
27+
28+
In gocui, the underlying package we use for managing the UI and events, we keep track of how many busy goroutines there are using the `Task` type. A task represents some work being done by lazygit. The gocui Gui struct holds a map of tasks and allows creating a new task (which adds it to the map), pausing/continuing a task, and marking a task as done (which removes it from the map). Lazygit is considered to be busy so long as there is at least one busy task in the map; otherwise it's considered idle. When Lazygit goes from busy to idle, it notifies the integration test.
29+
30+
It's important that we play by the rules below to ensure that after the user does anything, all the processing that follows happens in a contiguous block of busy-ness with no gaps.
31+
32+
### Spawning a worker goroutine
33+
34+
Here's the basic implementation of `OnWorker` (using the same flow as `WaitGroup`s):
35+
36+
```go
37+
func (g *Gui) OnWorker(f func(*Task)) {
38+
task := g.NewTask()
39+
go func() {
40+
f(task)
41+
task.Done()
42+
}()
43+
}
44+
```
45+
46+
The crucial thing here is that we create the task _before_ spawning the goroutine, because it means that we'll have at least one busy task in the map until the completion of the goroutine. If we created the task within the goroutine, the current function could exit and Lazygit would be considered idle before the goroutine starts, leading to our integration test prematurely progressing.
47+
48+
You typically invoke this with `self.c.OnWorker(f)`. Note that the callback function receives the task. This allows the callback to pause/continue the task (see below).
49+
50+
### Spawning a background goroutine
51+
52+
Spawning a background goroutine is as simple as:
53+
54+
```go
55+
go utils.Safe(f)
56+
```
57+
58+
Where `utils.Safe` is a helper function that ensures we clean up the gui if the goroutine panics.
59+
60+
### Programmatically enqueueing a UI event
61+
62+
This is invoked with `self.c.OnUIThread(f)`. Internally, it creates a task before enqueuing the function as an event (including the task in the event struct) and once that event is processed by the event queue (and any other pending events are processed) the task is removed from the map by calling `task.Done()`.
63+
64+
### Pressing a key
65+
66+
If the user presses a key, an event will be enqueued automatically and a task will be created before (and `Done`'d after) the event is processed.
67+
68+
## Special cases
69+
70+
There are a couple of special cases where we manually pause/continue the task directly in the client code. These are subject to change but for the sake of completeness:
71+
72+
### Writing to the main view(s)
73+
74+
If the user focuses a file in the files panel, we run a `git diff` command for that file and write the output to the main view. But we only read enough of the command's output to fill the view's viewport: further loading only happens if the user scrolls. Given that we have a background goroutine for running the command and writing more output upon scrolling, we create our own task and call `Done` on it as soon as the viewport is filled.
75+
76+
### Requesting credentials from a git command
77+
78+
Some git commands (e.g. git push) may request credentials. This is the same deal as above; we use a worker goroutine and manually pause continue its task as we go from waiting on the git command to waiting on user input. This requires passing the task through to the `Push` method so that it can be paused/continued.

0 commit comments

Comments
 (0)