I need to run git fetch after any cd command in the background and only if I'm in a git directory.

  • hi and welcome to Stack Exchange! I'm answering your question since it's easy, but in the future, please demonstrate to us that you've already made an attempt at solving your problem before coming here. thanks!
    – strugee
    Nov 2, 2016 at 22:15

3 Answers 3


There are three parts to this:

  1. Run some code on changing the current directory. In zsh, you put this code in the chpwd function, or a function with a different name in the chpwd_functions array (example). See Execute bash scripts on entering a directory for a bash implementation.
  2. Detect git working copies. Since you're only interested in git, you can run git rev-parse --show-toplevel. There are more advanced frameworks to detect version control if you're interested in other version control systems.
  3. Run git fetch.

Here's a chpwd implementation that runs git fetch when changing into a git repository.

chpwd () {
  set -- "$(git rev-parse --show-toplevel 2>/dev/null)"
  # If cd'ing into a git working copy and not within the same working copy
  if [ -n "$1" ] && [ "$1" != "$vc_root" ]; then
    git fetch

This code goes in your shell startup script: .zshrc for zsh, .bashrc for bash (in bash you also need the wrappers to call chpwd on a directory change).

  • To avoid show of fatal error inside no git foldeers I changed this set -- "$(git rev-parse --show-toplevel)" 2>/dev/null into set -- "$(git rev-parse --show-toplevel 2>/dev/null)"
    – Mauro
    May 23 at 7:49

You can use a function:

function cd() {
    builtin cd "$@"
    if [[ -d .git ]]; then
        git fetch &

Add this to your shell's startup file.

There are a couple things that are going on here:

  1. First we use function cd() { to override the builtin cd behavior with our own custom code.
  2. Obviously we still want to change the directory, so we do that first - we prefix it with builtin* so that the shell uses the builtin cd instead of recursively calling our custom cd() function, and we provide it with $@ as the arguments, which gets expanded by the shell to all arguments provided to the function.
  3. We test if we're in a git repository^ by testing if the .git directory exists, and if it does we run git fetch, telling the shell to put it in the background by appending &.

Note that the output of git fetch will still be sent to the terminal. If you wish to discard it you can use this instead:

git fetch & 2>&1 >/dev/null

This redirects stderr into stdout, then sends stdout to /dev/null.

[*]: Note that builtin isn't in POSIX and therefore this solution isn't portable across all shells

[^]: This fails if the git repository is bare, but you almost certainly aren't going to have a bare repository on your drive, so who cares

  • That doesn't deal with pushd, with the multi-argument form of cd, etc. See unix.stackexchange.com/questions/21363/… for a more robust implementation. Nov 2, 2016 at 22:25
  • My shell doesn't support command so I renamed the function and just directly call cd "$@" which appears to be working correctly however, catching stderr and stdout doesn't capture the command done output from the shell like : [3] + done git fetch 2>&1 > /dev/null any suggestions on capturing that? Nov 2, 2016 at 22:35
  • @Gilles OP didn't ask about pushd and I thought $@ would expand to all arguments, hence handling the multi-argument form of cd. no?
    – strugee
    Nov 2, 2016 at 22:36
  • @north.mister you didn't specify your shell. since you mentioned bash and zsh I assumed it was one of the two - if you need code for a different shell, you should have said so.
    – strugee
    Nov 2, 2016 at 22:37
  • edited the answer to use builtin as that's probably more appropriate (and what I was thinking of in the first place)
    – strugee
    Nov 2, 2016 at 22:39

make a function in your .bashrc or .zshrc file that is in your home directory.

Add the following to the bottom of the file:

cd_fetch() {
    command cd "$@"
    if [ -d .git ]; then
        git fetch & 
alias cdg=cd_fetch

Now close and re-open your terminal or run source ~/.zshrc and now you can change directory with the command cdg that you just aliased.

Also if you don't want to use cdg and want to use just cd change the alias definition to alias cd=cd_fetch.

This approach will still output all that git fetch normally do, to silence it replace the git fetch & line for git fetch 2>&1 >/dev/null &.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.