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

Re: What is the diff between a --soft and a blank reset

From
Chris Torek <chris.torek@gmail.com>
Date
Nov 17, 2024, 02:57 UTC
Message-ID
<CAPx1GvfT1iNnpJ0Jv0vhdHrwD-pDOK81MnUW2-Fk_zcJkW9PUQ@mail.gmail.com>
In-Reply-To
<myxdTw4K7jcrlKX-HC0edNKB3mgkjGJPAejkxWTcab03uT9uROZlO28zjhmnogOvGCJkag5q_Zvbok0VUyVjlkw5Goz3Gwe3l636lCYnGic=@proton.me>
On Sat, Nov 16, 2024 at 6:08 PM A bughunter <A_bughunter@proton.me> wrote:
> The difference here is touching the index but what does that mean in pragma ...

Understanding "the index" is _crucial_ to using Git, yet it's not often explained very well.

(Note: _emphasis_ means italics emphasis, while ALL CAPS means bold emphasis, below.)

I think it helps to start with a simple fact about _every_ source management system: such a system, by definition, _must_ have TWO COPIES OF EVERY FILE available at all times. This follows from the fact that you can get back the version you started with -- and to do that, the system must retain each original, unedited version -- and yet you must also be able to edit files, which means the system must retain the edited files as well. So those are the two _required_ copies: original, and edited. If the two are the same, it's at least theoretically possible to share them, but that's not important here. The actively-being-edited files are the _working tree_, while the frozen-for-all-time original files are saved (forever) in a Git commit, in the case of Git.

What's unusual about Git is that it keeps a THIRD copy of every file. As noted above, if any given pair of copies match, it's at least theoretically possible to share them -- and Git sometimes does -- but that's not important here.

What Git's index is all about is that it HOLDS THE THIRD COPY. The reason this is crucial to know is that running:

    git commit
tells Git to make a *new* commit FROM THIS THIRD COPY.

There are tricks you can use to attempt to hide or ignore this third copy, but using them is, in my opinion, a bad idea, because eventually one of these tricks fails and you're exposed to the fact that there _is_ a third copy. You might as well just get used to the idea.

Once you _are_ used to the idea, much of the rest of Git begins to make sense:

 * `git add` mainly copies files _into_ the index, preparing them
   for a future commit.
 * `git commit` takes whatever is in the index _right then_ and
   uses that to make the new (permanently-frozen) copy of all
   those files.

Now, logically, `git reset` might be the one that undoes `git add`. And it _does_ do that. The problem is that it does a lot more as well. It has, in fact, _three_ primary jobs:

 * It can move `HEAD`.  (Understanding precisly what `HEAD` means,
   in Git, is another crucial item, but this message won't cover
   that.)
 * It can copy some or all files from a commit into the index.
 * Last, it can _also_ copy those files from the commit, into the
   index, and then on into the working tree.

(Even more unfortunately, `git reset` has several auxiliary jobs as well as these three primary ones. I won't cover these.)

The three options -- `--soft`, `--mixed`, and `--hard` -- tell `git reset` which of these three jobs to do:

  * With `--soft`, `git reset` _only_ adjusts `HEAD`.  The
    default adjustment is to leave it unchanged, so running
    `git reset --soft` with no additional arguments does
    nothing at all.  That is, it does only job #1, then
    stops.
 * With `--mixed`, `git reset` adjusts `HEAD` as before --
   it's usually wisest to not have it adjust anything for
   this case, in my opinion -- and then goes on to copy the
   files from the `HEAD` commit into the index.  That is, it
   does jobs #1 and #2, and then stops.
 * With `--hard`, `git reset` adjusts `HEAD`, copies the files
   from the adjusted `HEAD` to the index, and then copies the
   files from the index to the working tree.  That is, it does
   all three of jobs #1, #2, and #3.

And that's it: that's all you need to know. Well, _almost_ all: there are all kinds of finicky corner cases around files that are in the working tree but _not_ in the index and/or commit. There's also one other problem, in a new, totally-empty repository in which there are no commits yet. But those edge cases need a lot of explanation and should be left until later.

Chris
Previous: A bughunterNext: A bughunter
Message 2 of 9 in “What is the diff between a --soft and a blank reset”
  1. A bughunterNov 17, 2024
  2. Chris TorekNov 17, 2024
  3. A bughunterNov 17, 2024
  4. Kristoffer HaugsbakkNov 17, 2024
  5. A bughunterNov 17, 2024
  6. Phillip WoodNov 17, 2024
  7. A bughunterNov 17, 2024
  8. Junio C HamanoNov 18, 2024
  9. A bughunterNov 18, 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.