oh-my-zsh slow, but only for certain Git repo
Asked Answered
F

15

207

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.

Fraternize answered 7/10, 2012 at 1:21 Comment(9)
and if you use bash now, is it still slow?Broeder
Excellent question. No, it's fast on bash.Fraternize
Is it still slow if you move your ~/.z* files out of the way?Spherics
No. So I guess it's something in one of those.Fraternize
Okay, the culprit seems to be ~/.oh-my-zsh/oh-my-zsh.sh. I don't know what to do with this information, though.Fraternize
Narrowed it down even further and updated my answer.Fraternize
Also, when I include oh-my-zsh.sh in my .zshrc, it for some reason loads .zshenv twice, which loads RVM twice, which must certainly make things slower than necessary.Fraternize
If the repo is big, calling git st everytime might slow the shell down. Use this option to turn it off. git config --add oh-my-zsh.hide-status 1Timecard
FYI this also occurs on WSL on Windows with Oh My Zsh.Inmate
D
438

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

Explanation

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.

Displacement answered 16/9, 2014 at 8:32 Comment(14)
This solution still works, just tried this in my Symfony2 project folder. Maybe the vendor folder makes things slow, like the rake folder does for rails apps? zsh is fast now, and I do not need the GIT zsh plugin anyway. Thanks!Tletski
This solved my problem perfectly. I can still use the nice git-status business in other repos, but not in my huge firefox source code repo where git it slow.Collyrium
I had to use oh-my-zsh.hide-dirty. It might have changed or maybe my theme (agnoster) only respects hide-dirty.Dematerialize
Don't forget to update oh-my-zsh, otherwise your lib/git.zsh might completely ignore the hide-dirty option.Golanka
Doing this in global settings for vagrant virtualbox vms with --global is really handy (slow in guest, fast on host) as described here: https://mcmap.net/q/126517/-oh-my-zsh-slow-but-only-for-certain-git-repo <3Crinoline
This answer added a big blank space at the end of my prompt. Not sure how to fix that.Alyose
What's the sdie effect?Fulvia
Neither this nor the solution below help speed things up for me. Any ideas? git status is definitely the slow issueOehsen
git config --add oh-my-zsh.hide-dirty 1 was all I needed for my slow repo.Birdsall
A few notes about this solution: I also needed to remove git-prompt from my list of plugins and completely launch a new shell before things improved. (Despite the name, that plugin isn't required for git info in your prompt at all.) Just sourcing .zshrc wasn't enough. Also FWIW, the takashiyoshida theme works great with these flags.Copious
git config --global --add oh-my-zsh.hide-dirty 1 I add this config to the global config. speeds up a lotTwill
This command gave me instantaneous relief!Godspeed
It is great when even after almost 10 years your answer is still valid, isn't it?Azoic
I just preferred to run the line :git config --local --add oh-my-zsh.hide-status 1 only in the directory of the huge git project just to make sure all the other git projects would have unaffected status on my terminalRaffia
H
64

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

Hernadez answered 10/8, 2016 at 6:22 Comment(6)
git config --add oh-my-zsh.hide-status 1 speeds the things up but it completely removes the zsh status of the VCS. This one keeps it and still speeds it up.Ripple
I was hoping this would do the trick, but no effect, even after source ~/.zshrc. git config --add oh-my-zsh.hide-dirty 1 worked for me, though. git config --global --add oh-my-zsh.hide-dirty 1 to disable this for all repos.Birdsall
@JohnathanElmore @Peeyush, DISABLE_UNTRACKED_FILES_DIRTY="true" doesn't do the same thing as the oh-my-zsh.hide-dirty setting, even though they're similar. See the code here: github.com/ohmyzsh/ohmyzsh/blob/master/lib/git.zsh#L17. The DISABLE_UNTRACKED_FILES_DIRTY setting simply adds an --untracked-files=no flag to the git status command, whereas the oh-my-zsh.hide-dirty 1 setting will skip the whole git status command altogether. I recommend @JohnathanElmore's suggestion of the global git config setting.Pah
not work for me with mac m1 on large file repository.Oversoul
In macOS adding the given line DISABLE_UNTRACKED_FILES_DIRTY="true" end of the ` ~/.zshrc` file helped to solve the issueDestrier
In my case, the check for dirty files became slow after adding a large binary in git lfs. So disabling dirty check for untracked files makes no difference.Colas
D
28

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
Dematerialize answered 3/12, 2016 at 1:0 Comment(0)
G
22

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

Glyceride answered 20/1, 2013 at 19:10 Comment(1)
Interesting. +1. This is more specific than my answer.Matelote
M
13

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.

Matelote answered 8/10, 2012 at 7:49 Comment(2)
That stuff helped in that it led me to start commenting stuff out to see what might make things load faster. I narrowed the problem down further and updated my question.Fraternize
The compinit post improved a small amount for me, but removing parse_git_dirty really sped things up. Thanks.Ablate
L
11

For others coming to this question looking to improve their zsh git latency, the following reduced my latency from 40ms to 4ms:

  1. 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/
    
  2. 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.

Livorno answered 3/7, 2021 at 16:35 Comment(1)
With this I was able to create a fast git-aware shell prompt with: export PS1="\u@\h \t \W [$txtcyn\]\$(git-branch-name) \[$txtrst\]\$ "Workbench
F
6

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.

Fraternize answered 16/2, 2013 at 18:54 Comment(3)
Interesting feedback (more precise than my answer) +1Matelote
And it only took me 4 months to figure out!Fraternize
I find that fast! I know somes who take several years ;) meta.stackexchange.com/questions/36318/…Matelote
C
5

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
Ceric answered 18/3, 2022 at 15:49 Comment(1)
This one solved it for me, thank you! < git config --add oh-my-zsh.hide-dirty 1Klingel
G
4

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.

Guacin answered 27/10, 2022 at 12:18 Comment(1)
This worked perfectly for me. I run git status and now suddenly every command is instantaneous. I believe that adds the git status to a cache or something.Sectarianize
V
3

If you don't care about another version control programs but git, you can just disable all vcs_infos in your *.zsh-theme and replace them with native git commands.

For example I tweak my agnoster.zsh-theme by:

  1. comment/remove all lines that have vcs_info,
  2. 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.

Vespasian answered 2/12, 2017 at 9:51 Comment(0)
C
3

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.

Capper answered 26/11, 2021 at 13:2 Comment(0)
R
3

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.

Redhead answered 15/12, 2021 at 0:20 Comment(1)
So it was!! Thank you! In my case, I believe it cleaned up some LFS files which made all the difference.Colas
E
2

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.

Erb answered 15/7, 2019 at 7:41 Comment(0)
N
2

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

Nievesniflheim answered 12/2, 2020 at 17:57 Comment(2)
Updated second linkNievesniflheim
I observe that spacehip makes terminal slower than its already it is.Destrier
A
0

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.

Arnie answered 13/4 at 7:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.