Skip to content

Reconsider storing UI toggles in state.yml #4602

@stefanhaller

Description

@stefanhaller

In #2904 we had a long debate about where/how to persist settings that users can change in the UI. After some discussion and a twitter poll we decided to persist them in state.yml (option C from the above link). I'm challenging this decision now, after gaining some more real-world experience with it.

First, an assessment of the status quo in lazygit:

ignore whitespace stored in state.yml, no config
diff context size stored in state.yml, no config
rename threshold stored in state.yml, no config
local branch sort order stored in state.yml, no config
remote branch sort order stored in state.yml, no config
show file tree stored in user config, not reset when config changes
show command log both user config and state.yml, interacting in interesting ways (see below)
git log order stored in state.yml, deprecated config exists for legacy reasons
show graph stored in state.yml, deprecated config exists for legacy reasons

Of these, the "show command log" setting is the most interesting one. It has a user config that defaults to true, and if it is true, the state is persisted in state.yml (in other words, hiding the log in the UI will be remembered, and it will stay hidden at the next start). If the config is false, this overrides the state.yml value, and the log will be hidden at every start. (I happen to like this latter behavior.)

The "git log order" and "show graph" settings are special in that they do have a user config, however it is only used for initializing the AppState values if no state.yml exists, i.e. only at the very first start of lazygit.

Discussion

There are arguments for and against our current default policy of storing settings in state.yml. The alternative is to have a user config for the initial value at startup, and then let users change this at runtime, but don't persist the change (option A from the discussion linked to above. Side note: after re-reading that discussion I still don't understand what option B is supposed to mean, so I'm ignoring it here).

Advantage of C (storing in state.yml):

  1. If a user changes, say, the diff context size and realizes that they do like the new value better in general, there's nothing else they need to do.

Advantages of A (user config):

  1. If they only changed the diff context size temporarily but usually prefer their default of 3 or 5, then they always get back to the preferred state at the next start.
  2. Some users accidentally changed a value like diff context size, and then got confused or ran into problems from that; for these users, the problems would have been fixed on the next restart by not persisting the value that they didn't even realize they changed.
  3. User configs can be repo-local. While this is probably not relevant for most of the settings, for some it is very useful. For example, you could keep git log order at the default of "topo-order" for most repos, and only set it to "default" for those few giant repos where it is needed for better performance. Similarly, some repos have such a messed up commit history that seeing the graph is more confusing than helpful, so you can turn the graph off for those, but keep it on for all others.

A middle-ground option (D)

There is another possible approach that is somewhere in the middle between A and C: allow users to set a user config to get a defined value at every start, but if they omit it, persist the value in state.yml. This is similar to what we do for "show command log" today, except there we do it only when the config is false. Here the suggestion is to do this for any config value if it exists. To implement this, we'd define these configs as pointers so that we can distinguish false from unset.

While this approach seems like the most flexible one, I'm not suggesting it because it doesn't have as many advantages as A. It supports 1. and 4. from the list above, but not 2. and 3.

Conclusion

I'm proposing to go back to option A. We've also seen people in various issues say that this is what they intuitively expect (e.g. here and here).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions