On 8/25/26 12:19 PM, Ilya wrote:

-------------------------------------------------------
Date: Tue 25 Aug 2026 04:19:48 PM UTC By: Ilya <ilya_the_human>
Reference says
```
When a shell with history enabled exits, Bash copies the last $HISTSIZE
entries from the history list to the file named by $HISTFILE. If the
histappend shell option is set (see Bash Builtin Commands), Bash appends the
entries to the history file, otherwise it overwrites the history file.
```

But if we look at the code (bashhist.c:512-523), we see that the history does
not work like that at all, and append happens basically always

People don't want to lose the history they've accumulated, sometimes over
many years (you'd be surprised). It also avoids duplicate entries and
reduces the work the shell has to do, but those are secondary.

Say your history file has 10,000 entries, and you make sure that
HISTFILESIZE reflects that. You don't want all those entries in every shell
session, so you set HISTSIZE to 1000.

where_history() will always return 1000, assuming you don't change
HISTSIZE, and the history numbers displayed by `history' will be offset by
9000, since you started with the 9000th entry in the file.

So say you enter ten commands and exit the shell.
history_lines_this_session will be 10, and the history list will no longer
contain the original first ten commands -- ones that you read from the
history file. If you overwrite the history file, you blow away all the data
the user has carefully saved. If you append everything in the history list,
you get duplicate entries. If you append only the commands entered during
this session, you avoid both of those things.

This applies for any value of HISTSIZE that's smaller than $HISTFILESIZE.

It's been this way for basically 35+ years. The check against
where_history() was the original code, the option to force an append
came years later.


```
          using_history ();
          if (history_lines_this_session <= where_history () ||
force_append_history)
            {
              result = append_history (history_lines_this_session, hf);
              history_lines_in_file += history_lines_this_session;
            }
          else
            {
              result = write_history (hf);
              history_lines_in_file = history_lines_written_to_file;
              /* history_lines_in_file = where_history () + history_base - 1; */
            }
```
the only case when the history is actually overwritten is as follows - in one
session I write more commands (history_lines_this_session) than HISTSIZE
(where_history(), which returns history_length), which is a pretty improbable
scenario.

Improbable? You can't imagine a shell session where you enter 500 commands?
And that's just the default value. I keep some shell sessions running for
weeks at a time. And if you were to have such a session, you wouldn't
necessarily want your history file to be overwritten, either. That's why
bash-2.0 introduced `histappend' as a shell option.

In this scenario, you're going to lose the earliest commands you entered,
since those are no longer in the history list, but you'll at least get the
last $HISTSIZE ones, and you can overwrite if you want.

I don't at all understand why it is this way

That's OK.

I suppose the historic behavior better be preserved, so I will not offer a
potential fix (which I feel would be to remove `history_lines_this_session <=
where_history ()` condition?),

Yeah, no.

 but the docs at least should be patched.

Maybe "up to the last $HISTSIZE entries, appending to the history file if
possible" with some text describing what happens if you enter more than
$HISTSIZE commands during a shell session.

Current text is extremely confusing,

Well, there's certainly some potential improvement there.

in reality "histappend" opt feels mostly
redundant

It's not.

Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    [email protected]    http://tiswww.cwru.edu/~chet/

Reply via email to