Git pull hangs on SMB shared repository

Apple switched to SMB2 with Mavericks and it's not working so well for quite a few people. As an alternative, here's a more permanent fix you can apply instead of the temporary one of cifs://:

To force all connections to be SMB1:

Open A terminal window paste in the following line followed by the return key (should be all on one line):

echo "[default]" >> ~/Library/Preferences/nsmb.conf; echo "smb_neg=smb1_only" >> ~/Library/Preferences/nsmb.conf

What the command does:

Creates a file called nsmb.conf in your home directory at the path ~/Library/Preferences/nsmb.conf. Adds directives to force SMB connections to use the SMB1 protocol. This is slower but stable.

How to remove the workaround:

Open a terminal window paste in the following at the prompt and then hit the return button:

rm ~/Library/Preferences/nsmb.conf

Notes: ( source )

Its a good idea to restart your mac before trying to connect to your storage again. This will clear any hung SMB processes from previous attempts to connect to your storage before implementing this workaround.


EDIT: Commenter replied "it wasn't helpful" — not the best choice of words, but you get the idea.


In the Git source, there seems to be a infinite loop in Git's fmt-merge-msg function when the repo sits in a SMB share while being accessed from Mavericks. The only way I've been able to fix this is by doing doing a process that doesn't involve automatic merging.

git pull is essentially a git fetch && git merge all in one command. If you try and do a git fetch into your current branch when there have been changes, you may run into an issue where the git fetch fails.

The way that I've fixed this issue is to fetch the remote branch into a temporary local branch and them merge that temp branch into your working branch. See the following which details trying to fetch the latest changes from your origin/master into your current working branch master.

  1. Fetch the latest changes from origin master into a local branch called master_merge_tmp. git fetch [<remote loc>] [<remote branch>]:[<local branch>] allows you to fetch the latest changes without invoking fmt_merge_msg automatically and you can target a different local destination branch:

    git fetch origin master:master_merge_tmp
    
  2. Merge the master_merge_tmp branch into master:

    git merge master_merge_tmp
    
  3. Perform some cleanup by deleting the remote branch mater_merge_tmp:

    git branch -D master_merge_tmp
    

Alternatively you could create a helper function to automate the steps above. You can place this in your .bashrc or .zshrc:

# Workaround for fmt-merge-msg issue on Mavericks w/SMB repo
# gfm [<remote>] [<remote branch>]
function _git-fetch-merge() {
  local remote="$1"
  local branch="$2"
  local tmp_branch="${2}_merge_tmp"
  git fetch $remote $branch:$tmp_branch
  git merge $tmp_branch
  git branch -D $tmp_branch
}
alias gfm="_git-fetch-merge"

Now from the terminal you can do the following:

_git-fetch-merge origin master

Or you can use the alias:

gfm origin master

If you are working with a remote upstream branch:

gfm upstream master