Reputation: 45134
I recently started using Zsh and it's awesome. Unfortunately, for the project I consider my "main" project, everything is slow. What I mean is that every time I run a command - ls
, for example - there's about a five-second delay between the time the command is executed and the time I can use the terminal again.
What could be different about this one repo that makes Zsh so slow? I assume it's a Zsh-specific thing because there was no problem before I started using Zsh. I tried doing a git clean
but it didn't make any noticeable difference.
I'm on Mac OS X if that matters.
Update: Turns out this line of my .zshenv
is what was making it slow:
[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function
If I comment that line, it goes from taking about 3 seconds to taking about 1 second. Unfortunately, I need that line, since many of my projects use RVM. I don't know what to do now.
Update 2: this seems to be specifically an oh-my-zsh thing. If I don't load ~/.oh-my-zsh/oh-my-zsh.sh
, I don't have a problem.
Upvotes: 209
Views: 105955
Reputation: 1599
For repositories using "master" as the default branch, you may try to rename it to "main" to make the current branch resolution process returning quickly. In my case, this was the root cause for a specific repo, but it was not always reproduced in other repos using "master".
I've tried to dig into the oh-my-zsh's lib/git.zsh
, but could not find specific relations to the default branch names.
FYI) The git_main_branch
function in oh-my-zsh's git
plugin runs an iterative default branch name resolution where "master" comes last and it may affect the latency of several git command aliases from the git
plugin. However, this function is not used in the git-prompt
plugin nor my theme setup.
Upvotes: 0
Reputation: 903
It is the case for large repositories, repositories in repositories, etc. My preferred solution is to run git status
in the repository when it is slow rather than changing the configuration of Oh My Zsh. It is easier and avoids any secondary effect.
Upvotes: 4
Reputation: 141
The top solution proposes
git config --add oh-my-zsh.hide-status 1
git config --add oh-my-zsh.hide-dirty 1
Which works but disables some cool functionality like branch name and dirtiness.
For me what worked was to compress git's database but using the aggressive
flag:
git gc --aggressive
Upvotes: 6
Reputation: 81
I wanted to keep my git status, so all the other answers weren't helpful to me.
The thing that really helped me is running this command in the git repository that was slow for me:
git gc
It stands for Garbage Collect and is fully explained here, but basically:
[It] Runs a number of housekeeping tasks within the current repository, such as compressing file revisions (to reduce disk space and increase performance)
After running this command, there was no loading anymore. Everything was instant again.
Upvotes: 3
Reputation: 681
I had the same issue. I ran the following command to get a list of all the themes that are not using hard-coded git plugin:
grep --files-without-match "git" ~/.oh-my-zsh/themes/*
The prompts became much faster, but I didn't like any of those themes.
I ended up using powerline10k, which can be configured to look pretty nice and doesn't have the speed issue.
Upvotes: 3
Reputation: 18289
For others coming to this question looking to improve their zsh git latency, the following reduced my latency from 40ms
to 4ms
:
Compile and install an optimized git-branch-name
command:
git clone https://github.com/notfed/git-branch-name
cd git-branch-name
make
sudo install git-branch-name /usr/local/bin/
Add this to your ~/.zshrc
:
function git_prompt_info() {
ref=$(git-branch-name -q -h 12 -b 64) || return
echo "${ZSH_THEME_GIT_PROMPT_PREFIX}${ref}${ZSH_THEME_GIT_PROMPT_CLEAN}${ZSH_THEME_GIT_PROMPT_SUFFIX}"
}
(The -h
and -b
flags control truncation length for branch names and hashes, respectively.)
With this, I can hold enter and not experience any lag.
Upvotes: 11
Reputation: 12587
For anyone using the spaceship theme add this to .zshrc
:
SPACESHIP_GIT_STATUS_SHOW="false"
worked for me. Obviously, you will lose the git status in your terminal prompt.
The git options for this theme can be found here
Edits
Updated link to git options is here
Upvotes: 2
Reputation: 329
Answers above didn't solve my problem. In my case, the function git_prompt_status
takes too much time than others. So I modified ~/.oh-my-zsh/lib/git.zsh, replacing git_prompt_status
function with my early return version:
function git_prompt_status() {
STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
echo $STATUS
return
local INDEX STATUS
INDEX=$(command git status --porcelain -b 2> /dev/null)
STATUS=""
if $(echo "$INDEX" | command grep -E '^\?\? ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_UNTRACKED$STATUS"
fi
if $(echo "$INDEX" | grep '^A ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS"
elif $(echo "$INDEX" | grep '^M ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS"
elif $(echo "$INDEX" | grep '^MM ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS"
fi
if $(echo "$INDEX" | grep '^ M ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
elif $(echo "$INDEX" | grep '^AM ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
elif $(echo "$INDEX" | grep '^MM ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
elif $(echo "$INDEX" | grep '^ T ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
fi
if $(echo "$INDEX" | grep '^R ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_RENAMED$STATUS"
fi
if $(echo "$INDEX" | grep '^ D ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS"
elif $(echo "$INDEX" | grep '^D ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS"
elif $(echo "$INDEX" | grep '^AD ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS"
fi
if $(command git rev-parse --verify refs/stash >/dev/null 2>&1); then
STATUS="$ZSH_THEME_GIT_PROMPT_STASHED$STATUS"
fi
if $(echo "$INDEX" | grep '^UU ' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_UNMERGED$STATUS"
fi
if $(echo "$INDEX" | grep '^## [^ ]\+ .*ahead' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_AHEAD$STATUS"
fi
if $(echo "$INDEX" | grep '^## [^ ]\+ .*behind' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_BEHIND$STATUS"
fi
if $(echo "$INDEX" | grep '^## [^ ]\+ .*diverged' &> /dev/null); then
STATUS="$ZSH_THEME_GIT_PROMPT_DIVERGED$STATUS"
fi
echo $STATUS
}
While I use ZSH_THEME_GIT_PROMPT_MODIFIED as a mark of undetermined, you may choose any status you like to indicate that or implement a much faster git_prompt_status
function in your case.
Upvotes: 2
Reputation: 713
Oh_my_zsh seems to be slow for some repos because it checks the status of the repo after each command. This behaviour can be overridden in the new version of .oh_my_zsh . Just Uncomment the following line in .zshrc:
DISABLE_UNTRACKED_FILES_DIRTY="true"
After this, restart your terminal or run the following:
source ~/.zshrc
Upvotes: 65
Reputation: 14725
For me it's slow on VirtualBox (the guest) because I'm using a synced folder. I still want it enabled on OS X (the host) where it's fast enough. Instead of using a local config setting which is stored with the repo and would change it both on the guest and host, I use a global config setting only on the guest:
git config --global --add oh-my-zsh.hide-dirty 1
If I want it just for a single repo:
git config --add oh-my-zsh.hide-dirty 1
Upvotes: 28
Reputation: 14669
You can add this to your git config and zsh won't check the status anymore
git config --add oh-my-zsh.hide-status 1
git config --add oh-my-zsh.hide-dirty 1
There are two central git functions in in lib/git.zsh:
git_prompt_info()
parse_git_dirty()
Each Method has a git config switch to disable it:
oh-my-zsh.hide-status
oh-my-zsh.hide-dirty
Some themes create their own git queries and sometimes ignore these flags.
Upvotes: 441
Reputation: 4139
If you don't care about another version control programs but git
, you can just disable all vcs_info
s in your *.zsh-theme
and replace them with native git
commands.
For example I tweak my agnoster.zsh-theme
by:
vcs_info
,edit code in prompt_git()
function from:
ref="$vcs_info_msg_0_"
to
ref="$(git branch 2>/dev/null | grep -Po '(?<=\* ).*$')"
So, basically, I just disabled all vcs_info
actions, and instead use a native git
command for checking statuses of the repo. As a result, I still can see my useful git prompt with a speed as fast as working in a non-git directory. With this small modification, my zsh can work 4-5x faster within git repos.
Note: use GNU grep not BSD grep.
Upvotes: 3
Reputation: 45134
I finally figured it out. My project had a rake
folder with a ton of files (like 20,000). I have no idea what that folder was there for, but I deleted it, Zsh is no longer slow, and my app still seems to work.
Upvotes: 6
Reputation: 2154
It could be the theme calling git and rvm stuff after every command.
For me, changing ZSH_THEME="juanghurtadoto"
to ZSH_THEME="miloshadzic"
removed the 2 second delay after every command completely.
Themes can be found at https://github.com/robbyrussell/oh-my-zsh/wiki/themes
Upvotes: 24
Reputation: 1326736
There are various way to speed up an oh-my-zsh
, as detailed in "zsh starts incredibly slowly", cleaning up the plugin section.
For instance, the blog post "Fix for oh-my-zsh git-svn prompt slowness" mentions the parse_git_dirty
function as a potential issue.
Upvotes: 13