How to undo changes in the commands-history?

As long as you've edited a history entry but not pressed Enter yet, to go back to the original entry, repeatedly press Ctrl+_ — the undo command — until it doesn't make any further change. You're back to the original entry.


Revert to the original command when you've have made multiple changes to the line:

revert-line (M-r) 
    Undo all changes made to this line. This is like 
executing the undo command enough times to get back to the beginning.

M is the meta key, which is alt</kbd+r for me.


Gratuitous, Yet Helpful Info

When you have executed a command like OP had previously done (it happens), there is nothing to "undo" because the commands are handled and remembered by the GNU Readline library and are not written to $HISTFILE until the shell exits. The reason I mention this is because you can't just grep the $HISTFILE like one might expect and it may not be ideal to exit the shell.

So here are a couple of options to save you from scrolling back through all previous readline commands.

If you remember some of the command, press ctrl+r and type what you remember to search through previous commands containing that string. Pressing ctrl+r again will display the next most recent, searching backwards.

For example, type ls -l then ctrl+r as many times as it takes to find the previous command you seek. If you scroll past it, ctrl+s will search forward from the current position.

The fc bash builtin command is helpful to list the index numbers alongside previous readline commands.

fc -l -100 will list the previous 100 commands in readline.

Additionally, if OP knows he's looking for a previous ls -l command, he could pipe the output to grep such as: fc -l -100 | grep 'ls -l'

This should output a list of previous ls -l commands preceded by an index number. The output looks like this:
2065 ls -l

Now you can use the event designator !n where n is the index number. In this example, executing !2065 will expand to ls -l.


Although it doesn't help after the fact, anyone looking to preserve the recent command history when modifying previous commands should see the HISTORY EXPANSION section of man bash. Here are some alternative methods for modifying old commands without overwriting the history.

The Event Designators section shows how you can easily edit string from the most recently used command.

^string1^string2^
              Quick  substitution.  Repeat the previous command, replacing string1 with string2.  Equivalent to
              ``!!:s/string1/string2/'' (see Modifiers below).

Example:

$ echo foo
foo 
$ ^foo^bar
echo bar
bar

The most recent commands will now show:

echo foo
echo bar

The above example also explains how to use sed to replace a string in an event designator.

!-n    Refer to the current command minus n.

So if 3 commands up in the history is echo foo then you would use:
!-3:s/foo/bar

Note that event designators will appear in your history as the command executed, in this case echo bar. It will not appear in the history as !-3:s/foo/bar.

Just throwing that out there as it seems closely related, even if it is more of a "don't do" than the "undo" solution OP is looking for.


The readline variable revert-all-at-newline, available since bash-3.2, accomplishes nearly the desired effect.

If set, then hitting enter on any line (could be a different command, or even an empty line) will revert any history entries that were edited but not executed (as in the example in the question).

This can be set with

set revert-all-at-newline on

in ~/.inputrc.

or

bind 'set revert-all-at-newline on'

in ~/.bashrc.