Skip to content
Shell & TerminalFix Published Updated 5 min readViews unavailable

Fixing Shell History That Doesn't Persist or Save Correctly

Commands seem to vanish between sessions, or history from multiple terminals overwrites instead of combining — how history writing works and the fix for each.

Shell history that seems to disappear between sessions, or that gets overwritten rather than combined across multiple open terminals, comes down to specific, identifiable settings governing when and how the history file actually gets written.

Step 1: identify the exact symptom

History from yesterday is completely gone → likely overwrite,
  not append, behavior

History works in one terminal but not visible in
  a different, simultaneously open terminal → expected default
  behavior without explicit history sharing enabled

Step 2: check whether Bash is appending or overwriting on exit

shopt -s histappend

Add this to .bashrc — without it, each Bash session overwrites the history file with just its own session’s commands when it exits, rather than adding to what was already there, meaning the last session to close “wins” and earlier sessions’ history is lost.

Step 3: check your HISTSIZE and HISTFILESIZE settings

echo $HISTSIZE       # commands kept in memory during the session
echo $HISTFILESIZE   # commands kept in the history FILE on disk

A HISTFILESIZE set too low silently truncates older history entries from the file, even with histappend correctly enabled — check both values are set to something reasonably large if you want extensive history retained.

Step 4: enable live history sharing across simultaneously open sessions in Zsh

setopt APPEND_HISTORY
setopt SHARE_HISTORY
setopt INC_APPEND_HISTORY

Without these settings, each open Zsh session only writes to the shared history file when it exits — SHARE_HISTORY makes history genuinely live-shared across every currently open session, and INC_APPEND_HISTORY writes each command incrementally as you run it, rather than only at session exit.

Step 5: check for a corrupted or overly large history file

wc -l ~/.bash_history

An extremely large history file can, in some configurations, cause slow shell startup or unusual truncation behavior — trimming it to a more reasonable size (keeping the most recent N lines) can resolve both performance and consistency issues simultaneously.

Step 6: check for HISTCONTROL settings unexpectedly excluding commands

echo $HISTCONTROL
# ignorespace: commands starting with a space are excluded
# ignoredups: consecutive duplicate commands are excluded
# erasedups: all previous duplicate entries are removed

If specific commands seem to be missing from history entirely rather than the whole file being affected, check whether HISTCONTROL is configured to deliberately exclude commands matching certain patterns — this is often intentional (excluding commands starting with a space, commonly used for commands containing sensitive values) rather than a bug.

Step 7: verify the fix by testing across an actual new session

# run a distinctive test command, close the terminal fully,
# open a new one, and check that the test command appears
# in history

Testing across a genuinely new session (not just the current one) is the only way to confirm persistence-related settings actually took effect, since the current session’s in-memory history behaves normally regardless of file-writing configuration.

Step 8: check for multiple, conflicting configuration files

# a HISTFILE or history-related setting defined in
# multiple sourced files (.bashrc, .bash_profile,
# a separately sourced history-specific config) can
# have the last-sourced one silently win

If a fix doesn’t seem to take effect despite being correctly written, check for the same setting being defined elsewhere too, potentially overriding your intended configuration later in the shell’s startup sequence.

Why history behavior differs so much between “just works” and “commands vanish”

History persistence isn’t automatic by default in the way many users assume — it depends on specific settings governing append-vs-overwrite behavior, file size limits, and (for multiple simultaneous sessions) explicit history-sharing configuration, all of which have to be deliberately set correctly for history to behave the way most users intuitively expect it to.

Adding timestamps while you’re already tuning history settings

export HISTTIMEFORMAT="%F %T "

Setting HISTTIMEFORMAT in Bash writes a timestamp alongside each history entry, shown when you run history — genuinely useful once persistence itself is working correctly, since it lets you answer “when did I actually run that command” rather than just “what did I run.” One real caveat: Bash only starts recording timestamp data from the point you set this variable onward, so existing history entries won’t retroactively gain timestamps once you enable it. Zsh offers the equivalent through setopt EXTENDED_HISTORY, storing both a timestamp and elapsed execution duration for each command directly in the history file format itself.

Distinguishing HISTCONTROL from HISTIGNORE

HISTCONTROL (covered above) filters based on generic properties of a command line — whether it starts with a space, whether it duplicates the previous entry. HISTIGNORE, in Bash, is a separate, colon-separated list of shell glob patterns matched against the full command line itself, letting you exclude specific commands by name or pattern regardless of leading whitespace or duplication status:

export HISTIGNORE="ls:cd:pwd:clear:exit"

The two mechanisms compose rather than substitute for each other — HISTCONTROL for the general space-prefix and duplicate-suppression behavior most people want everywhere, HISTIGNORE for a specific, named list of low-value commands you’ve decided aren’t worth recording regardless of how they were typed. Confusing which one governs a specific missing command is a common reason a fix aimed at the wrong variable appears not to work.

Related:

Sources:

Comments