git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Multiple indices / staging areas

From
JLJacek Lipiec <jacek.lipiec.bc@gmail.com>
Date
Jan 30, 2024, 03:47 UTC
Message-ID
<CAPGWkwcqbkanFP4h1P0umJAFzmiQYTvSm1KeD0=yY0n2K=KS7g@mail.gmail.com>

Hello, I am thinking about extending the current index mechanism, and I wish to ask for feedback if this would be something that you would be interested in. Please note, I have no prior git development experience.

The main idea is to mirror the "changelist" functionality found in IntelliJ IDE's (https://www.jetbrains.com/help/idea/managing-changelists.html). Namely, at each given moment you can create a "changelist"/separate index to which you can move hunks to. Such changelists are named, and optionally have a (default) commit message. This allows for an easy way to split current changes into separate commits, to have clean and atomic work units committed; while seeing the combined changes in the worktree; as well as having a conceptual/logical separation for changes

Scenario: I am introducing a new functionality. Changes are
conceptually separate, but work together. i.e. new version of package
& using the new functionality from the package.
Scenario 2: I am not yet sure about what needs to be done, so I am
sketching in code. Some changes will be of linting nature, some will
introduce code, some will be an "ad-hoc fix".
What we can do with the current flow:
* Commit/amend/fixup. This works best when one has prior knowledge of
what needs to be done, i.e. bumping versions then using the
functionality. Problems arise when the code is "living", as such you
need to fixup commits in the local branch, which can lead to
conflicts. Another issue is that if you wish to commit small change
(i.e. a fix for a linter) you need to juggle the staging area. (This
is my current flow in the vanilla git. It can become clunky if you,
like me, sketch the solution in the code)
* git worktree. While this functionality is the closest to what I am
proposing, it does not allow for easy transfer of hunks, nor it allows
for working with all the changes in the same worktree at the same
time.
* branches. This again does not allow us to see all the changes at the
same time.

The idea for the implementation would be as follows, and should hopefully introduce no change to the existing flow.

1) Design

1.1) New indices file We add a new file in the $GIT_DIR, called `indices`. This is a map file that will MUST have at least one entry. Index entry MUST have a name. Index entries COULD have default commit message Example: ```.git/indices selected=1 # maps to .git/index.1 # translates to .git/index.0 index[0].name=Default # translates to .git/index.1 index[1].name=Add named index # translates to .git/index.2 index[2].name=Wip index[2].message=Add named index\n\nThis is a longer description ``` The "selected" index is in two places - one is `index` and the other is based on the selected entry; so following example, `index.1`. The best way to keep them synced would be to symlink them, though this would introduce FS dependency. Synchronized copy would work as well. Renames could work, but there would be IMO high risk of losing changes from the index due to a mistake.

This way, the existing index file format remains unchanged; and all new functionality can be handled via the new `indices` file; due to that all existing code should work without an issue. I see a potential problem of two indices overlapping (i.e. index changed via older git, or other tool) - in this case I would transparently correct other indices, treating selected index as the source of truth. This would imply that software not aware of the indices would see the changes in the not-selected index as unstaged. The second issue is the split index, as I know nothing about it, yet it might require changes.

1.2) Commands A git index create <name> [-m|--message <message>] A git index delete <name> A git index switch <name> A git index update <name> [-m|--message <message>] [-n|--name <new name>] M git add [-I|--index <index name>] M git diff [-I|--index <index name>]

2) Example workflows
2.1) Working with indices/non interactive add
git index create "wip" --message="This is a default commit message" #
We have a new index, but the default one is selected
touch {example|example2|example3}
git add example # Added to the "current"/"default" index, by default 0
git index switch "wip"
git add example2 # Added to the "wip"/ index, with id of 1
git add example3 --index=default # Added to the "current"/"default" index,
git commit # commit message="This is a default commit message"
# At this point, index.1 (wip) is empty, but selected. We can commit
another index
git commit --index=default -m "This is a commit message for the default index"
2.2) Status
> git status
On branch main
Selected index: wip
Changes to be committed (wip):
  (use "git restore --staged <file>..." to unstage)
        modified:   example
Changes staged for commit (default)
  (use "git restore --index=default --staged <file>..." to unstage)
        modified:   example
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   example
2.3) Git add (interactive)
> git add --interactive # details omitted for brevity

-Example change +Example change 2 (1/1) Stage this hunk to wip [y,n,q,a,d,e,i,?]?

> ?
i - change the current index
2.4) Remove index
Show 6 quoted lines
> git index remove # removes current, all staged goes to the "default" branch/index 0
> git index remove wip # removes wip, all staged goes to the default branch/index 0
> git index switch default
> git index remove # Does nothing...
> git index rename default "WIP" # index[0].name=WIP
> git index remove # renames default -> index[0].name=Default
...
I am open for the feedback/questions, or early go/nogo.
Jacek Lipiec
Next: Junio C Hamano
Message 1 of 2 in “Multiple indices / staging areas”
  1. Jacek LipiecJan 30, 2024
  2. Junio C HamanoFeb 2, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.