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

Re: Destructive pre-commit behaviour and "--all"

From
Chris Torek <chris.torek@gmail.com>
Date
Mar 22, 2023, 20:00 UTC
Message-ID
<CAPx1GvftGM2kpVL9JWWXrjyTRWs+6OxteoJDq9dgeOjuidUGwg@mail.gmail.com>
In-Reply-To
<CAMbUV8F8y62n5ud3AoWQak8J==Zrn7kzwTE7jCveVJEpfcqncg@mail.gmail.com>
On Wed, Mar 22, 2023 at 3:35 AM Jan Rüegg <rggjan@gmail.com> wrote:
> Why doesn't "git commit --all" keep the files added to the staging
> area, so "git commit --all" would have the same behaviour as "git add
> --all && git commit"?

It's not completely clear to me what behavior you *want* here, but I can answer the "why doesn't" question.

Remember that `git commit` can be aborted (in several ways). If it *is* aborted, whatever it did must be rolled back. This means that `git commit -a`, which is otherwise a lot like `git add -u && git commit`, is fundamentally different from a successful `git add -u` followed by a `git commit`. In particular, if the `git commit` *is* aborted, the `git commit -a` command *must not* leave the updated files in the index. The `git commit` without `-a` did not update any files in the index, so it does not have to "roll back" the index update.

To achieve this, `git commit -a` doesn't actually update *the* index at all. Instead, it prepares a *new* index and updates that new index. It then proceeds to do the committing, using the new index, rather than the main index, as if it were *the* index. If all goes well so that the commit is done, the code then swaps in the *new* index for *the* index. If the commit is aborted, the code simply *deletes* the new index, leaving *the* index unchanged.

This is fundamentally different from "update *the* index, then start committing, then either roll back *the* index or leave it in place": there's a secondary temporary index involved here.

Things get even more complicated if you use `git commit --only` (vs `git commit --include`) as in this case there are *three* indices simultaneously active ("the" index, "proposed index for commit", and "proposed index if commit succeeds"). All three must be managed carefully and correctly.

It is unwise to invoke `git add` in a pre-commit hook precisely because there may be two or three indices, and `git add` cannot affect all of them correctly.

Note that Git could be designed differently (with real databases that have roll-forward and roll-back options), but that's a much bigger change. The process described here is merely how Git works now, which explains the constraints on using `git add` in pre- commit hooks.

Chris
Previous: Jan RüeggNext: Chris Torek
Message 2 of 5 in “Destructive pre-commit behaviour and "--all"”
  1. Jan RüeggMar 22, 2023
  2. Chris TorekMar 22, 2023
  3. Chris TorekMar 22, 2023
  4. Junio C HamanoMar 22, 2023
  5. Jan RüeggMar 28, 2023

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.