aliases are not stored in zsh history - shell

Whenever I execute a command using an alias, this command is not stored in the shell's command history.
So if I run history these commands do not appear in the list.
Nor do they appear when I press CTRL + r for reverse searching the command history.
When I press the keyboard's arrow up for scrolling through the last commands, I will see an aliased command only if it was the last command I ran. Other aliased commands are will not be displayed.
For example:
$ cd my-repo
$ gs # an alias to git status
$ history
Outputs the following:
2374 cd my-repo
(the gs command is not displayed)
A few notes:
gs is only an example. The issue is far more annoying in more complex commands since I have to retype them all over again instead of executing them from history (e.g. k get pods | grep <pod_name>, where k=kubectl).
gs is defined so: alias gs=' git status'.
I also have a few functions in ~/.alias, e.g.:
mkcd () {
mkdir -pv $1
For some reason, mkcd (or any other function in the alias file) is included in the history.
I do not mind if it prints out gs or expands to git status, I'll take any of the two...
I am using zsh with oh-my-zsh on macOS (Monterey). My shell aliases are defined in ~/.alias which is sourced in ~/.zshrc (source ~/.alias).
This happens both in iTerm2 and in the default Mac terminal.
Thank you for taking the time to help :-)

I will assume that your example alias is exactly what you have in your ~/.alias file.
So you have aliases like this (notice the space character in front of git command):
alias gs=' git status'
There is an shell option called HIST_IGNORE_SPACE which is doing exactly what you are experiencing - in short it will not add command to the history when it starts with space character. Example:
echo 'This command will make it to the history.'
echo 'This poor command will be forgotten.'
You can check your current options using setopt or specifically:
setopt | grep 'histignorespace'
So there are two ways how you can fix this - either by fixing your aliases to not start with space or, If you really don't want this functionality at all, by unsetting it in your ~/.zshrc like this:
unsetopt HIST_IGNORE_SPACE

Related

Using !! to access bash history inside a Git alias

I want to create an alias that runs git stash and then executes the command that was before it.
This would be useful when git doesn't allow to run a command with unsaved changes, such as checkout, rebase, etc.
What I've tried:
s = "!git stash && fc -s
s = "!bash -c \"git stash && !!\""
None of the above work. It looks like in the first one git creates a subshell to run this command, as fc outputs no command found.
The second one is similar, but here I explicitly create a subshell and it obviously doesn't work, with no access to the history.
Is there a way around this? It's likely that this could be accomplished with a bash alias, but I'd prefer to do it through a git alias.
It's likely that this could be accomplished with a bash alias,
Yes, this would be simple and robust.
but I'd prefer to do it through a git alias.
Given how ugly and fragile this would be, I doubt it. However, here you go:
First, you need to relay the history. Make your shell write it out to the history file after every command by adding this to your .bashrc:
PROMPT_COMMAND='history -a'
You can then add your git alias. It needs to
run with Bash, since the system sh may not support history expansion
enable history and history expansion
read the history file
use history expansion in a separate parsing unit (e.g. after a linefeed, outside a compound command):
So all in all:
s = "!bash -c 'set -Ho history; history -r ~/.bash_history\ngit stash && !-1'"
Note that it'll run the last command executed regardless of bash instance, so if you use multiple tmux/screen/terminal windows, it won't necessarily run the last command in your current shell.
You can't use a git alias to access the Bash history (or any other shell data for that matter), since the command after the exclamation mark is not run as a subshell. Git is an external command, so all its child processes are also not subshells.
More details
You can confirm this by setting a git alias foo = !echo $$ $BASHPID and comparing it with the current shell:
$ echo $$ $BASHPID
11461 11461
$ git foo
25437
In my case it's not even running Bash. After some testing I think it's running /bin/sh, which is Dash for me since I'm using Ubuntu.

MacOS .bash_profile - /usr/bin/alias: line 4: builtin: alias: not a shell builtin - how to create an alias?

I have no idea why it isn't working. Using MacOS and bash:
$ echo $SHELL
/bin/bash
Here is the content of the file ```.bash_profile``:
I would imagine that I'm using right file - How do I create a Bash alias? - and the right syntax...
UPDATE:
Tried also .bashrc
When I tried to reload it:
$ source ~/.bashrc
/usr/bin/alias: line 4: builtin: alias: not a shell builtin
UPDATE:
Yes, it looks weird
$ type alias
alias is a shell builtin
$ source ~/.bashrc
/usr/bin/alias: line 4: builtin: alias: not a shell builtin
Given the set of possibilities we've eliminated --
Since you're using bash 3.2, set -x may not be visibly rendering all hidden characters, such as a byte order marker at the beginning of your file.
If the BOM is in fact the problem, then the first line of the file will always cause an error regardless of its contents, and if you move the alias command to the second line, it will then function. Similarly, if you install a more recent version of bash from MacPorts or Homebrew, then running bash -x -l -i will show the hidden characters at the beginning of the command it's trying to run in the generated log.
To solve this, recreate the file in a text editor that doesn't save a BOM, or use "Save As..." and choose a format with no BOM in an editor that gives you the option.
Run the alias command to display all created aliases. Also, you should use ~/.bashrc for aliases, not .bash_profile.
echo "alias p='python -m SimpleHTTPServer'" >> ~/.bashrc
source ~/.bashrc

How to echo OS X bash alias' command to terminal after calling it (like !cmd)?

In ~/.bash_profile aliases are defined, eg. alias vaguppro='vagrant up --provision
What I want is an echo of vagrant up --provision after typing vaguppro in the terminal.
Similar to when one types ls -hal in the terminal, then again type !ls. There's an echo of ls -hal in the terminal before execution.
SOME SOLUTIONS
vaguppro='vagrant up --provision'
alias vaguppro='echo $vaguppro && $vaguppro'
or andlrc's function solution below.
You may find this shortcut useful:
shell-expand-line (M-C-e)
Expand the line as the shell does. This performs alias and his‐
tory expansion as well as all of the shell word expansions. See
HISTORY EXPANSION below for a description of history expansion.
In other words, if you write vaguppro and press Ctrl+Alt+E in bash' default Emacs mode, it will expand aliases in the current line and turn it into vagrant up --provision. You can then press enter to run as usual.
!ls is a history expansion that searches your command history for ls and expands to the found command. As a bonus the expansion is also printed to the terminal.
To get the same behavior with your aliases, I think you would need to convert it to a function and print it manually:
vaguppro() {
echo "vagrant up --provision"
vagrant up --provision "$#"
}
I almost always recommend people using functions over aliases, unless it for adding colors for grep, ls, ...
alias grep='grep --color=auto'
alias ls='ls --color=auto'
alias cd..='cd ..'

Modifying bash prompt

When I open my terminal in Mac OS X, the command prompt current reads:
James-MacBook:project1 sam$
project1 is the name of the current directory.
What I want is to display the full path instead of James-MacBook.
How do I achieve this?
Your current prompt appears to show the hostname and the basename of your current directory. That means that the bash prompt, PS1, is likely set to:
PS1='\h:\W\$ '
To get the full directory name, use \w in place of \W:
PS1='\h:\w\$ '
You can set this at the command prompt. To make it permanent, this command can go into ~/.bashrc or ~/.bash_profile or other depending on how your system is configured.
You can read more about the options for command prompts, for which there are many options, in the PROMPTING section of man bash. Regarding the \w and \W options mentioned above, man bash explains how they are used:
\wthe current working directory, with $HOME abbreviated with a tilde (uses the value of the PROMPT_DIRTRIM
variable)
\W the basename of the current working directory, with $HOME abbreviated with a tilde
Easy. This is not an OS X thing, but a bash thing. Try this:
export PS1='$(pwd): '
Then if you want to make it permanent, just edit your .bash_profile:
nano ~/.bash_profile
And place that first command in there.

.bash_history does not update in Git for Windows (git bash)

I am using Git for Windows (ver. 1.7.8-preview20111206) and even though I have a .bash_history file in my HOME folder, it never automatically gets updated. When I start Git Bash, I can see in the history commands that I manually added to the .bash_history file, but it does not get updated automatically.
I used the shopt -s histappend command to make sure that the history gets saved every time I close the shell, but it does not work.
If I manually use the history -w command, then my file gets updated, but I would want to understand why the shopt command does not work as I understand it should.
Anyone can tell me why is this behavior happening?
I put this in my ~/.bash_profile
PROMPT_COMMAND='history -a'
Create the following files
~/.bash_profile
~/.bashrc
And put the following line in both of them
PROMPT_COMMAND='history -a'
To do this from the console (Git Bash) itself, use the following commands:
echo "PROMPT_COMMAND='history -a'" >> ~/.bash_profile
echo "PROMPT_COMMAND='history -a'" >> ~/.bashrc
What history -a means
From the history --help command
-a append history lines from this session to the history file
What is PROMPT_COMMAND?
Bash provides an environment variable called PROMPT_COMMAND. The contents of this variable are executed as a regular Bash command just before Bash displays a prompt.
Difference between .bash_profile and .bashrc
.bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells.
When you login (type username and password) via console, either sitting at the machine, or remotely via ssh: .bash_profile is executed to configure your shell before the initial command prompt.
But, if you’ve already logged into your machine and open a new terminal window (xterm) then .bashrc is executed before the window command prompt. .bashrc is also run when you start a new bash instance by typing /bin/bash in a terminal.
On OS X, Terminal by default runs a login shell every time, so this is a little different to most other systems, but you can configure that in the preferences.
References
https://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x264.html
https://apple.stackexchange.com/questions/51036/what-is-the-difference-between-bash-profile-and-bashrc
As it was said here, to save git bash history on Windows you must not close the terminal with X button. Use exit command instead. History of commands will be saved then regardless of configuration mentioned in the accepted answer.
If you're using Git bash in VSCode please see C.M.'s comment above.
This worked for running git's bash in Visual Studio Code, but I had to put it ~/.bashrc not ~/.bash_profile. – C.M. Jul 29 at 14:43
This solved it for me.
There is a more complete answer on Unix Stackexchange, by Pablo R. and LinuxSecurityFreak. Add the following to your ~/.bashrc:
# Avoid duplicates
HISTCONTROL=ignoredups:erasedups
# When the shell exits, append to the history file instead of overwriting it
shopt -s histappend
# After each command, append to the history file and reread it
PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"
Please be careful, though:
The problem with this PROMPT_COMMAND solution is that the numbers for each history item changes after each command. For example, if you type history(1) ls (2) rm, then you do !1 to repeat (1), the history number might change and might run the rm command. Chris Kimpton
If you use git bash for windows 8, just put this in your ~/.bash_logout file:
history > .bash_history
Obviously you need a ~/.bash_history file.
Regards.
For me what worked was going into C:\Users\MY_USER\ and deleting the .bash_profile file.
Ps: I am using windows 10
I am using Windows 10 for me it was a permission problem, my temporary solution was to add Everyone group and give it Full control on ~/.bash_history file.
By the way, for those using the Portable version of Git for Windows, there's no need to create .bash_profile or .bashrc. Simply add to C:<path to your Git Portable folder>\etc\bash.bashrc:
PROMPT_COMMAND='history -a'
Found an answer in another post : https://superuser.com/questions/555310/bash-save-history-without-exit
If you want to have an history updated between two terminals.
As a window user I created a file .bash_profile inside my user folder. And then I add the following content : PROMPT_COMMAND='history -a;history -c;history -r'
Just run this in your git bash
echo 'HISTFILE=$HOME/.bash_history' >> $HOME/.bashrc

Resources