There are a lot of super useful "!" commands documented in the bash manual in the section entitled 'History Expansion'
!! which you know runs the previous command in your history. It's just short for !-1
!123 runs the 123th command in your history
!gi runs the most recent command in your history that begins with letters g and i
!* is the args to the most recent command
!$ is the last argument to the most recent command
!:0 is argv[0] of the most recent command (i.e. the program name)
These can be combined:
!g:$ is the last argument to the most recent command that began with g
They are also really handy in backquotes since you can do things like grep foo `!find | egrep .cc` because your find command was almost right
Sometimes you can get away with a ^ substitution:
git add foo.cc bar.cc
oops
^add^reset
There are a lot of such commands that let you use the basename of the argument etc. After a short while they are so automatic they are easier to type than the actual command name ("I just want to do that thing again but with this filename"). These have actually become so deeply wired that I had to think to write them down because I use them “without thinking”.
So this is handy with normal commands:
git-add foo.cc
<do some stuff>
!g:0 bar.h
git-add foo.cc bar.cc
<do some stuff... oh wait, I didn't mean to do this>
git-reset !g:*
But with subcommands, you end up matching against all the git operations; !* matches all the arguments to the `git` command including the subcommand so you can't conveniently say "yes, that last git command but I want to change the subcommand"
!! which you know runs the previous command in your history. It's just short for !-1 !123 runs the 123th command in your history !gi runs the most recent command in your history that begins with letters g and i
!* is the args to the most recent command !$ is the last argument to the most recent command !:0 is argv[0] of the most recent command (i.e. the program name)
These can be combined: !g:$ is the last argument to the most recent command that began with g
They are also really handy in backquotes since you can do things like grep foo `!find | egrep .cc` because your find command was almost right
Sometimes you can get away with a ^ substitution:
oops ^add^resetThere are a lot of such commands that let you use the basename of the argument etc. After a short while they are so automatic they are easier to type than the actual command name ("I just want to do that thing again but with this filename"). These have actually become so deeply wired that I had to think to write them down because I use them “without thinking”.
So this is handy with normal commands:
But with subcommands, you end up matching against all the git operations; !* matches all the arguments to the `git` command including the subcommand so you can't conveniently say "yes, that last git command but I want to change the subcommand"