177

I have been using git to keep two copies of my project in sync, one is my local box, the other the test server. This is an issue which occurs when I log onto our remote development server using ssh;

git clone me@me.mydevbox.com:/home/chris/myproject
Initialized empty Git repository in /tmp/myproject/.git/
Password:
bash: git-upload-pack: command not found
fatal: The remote end hung up unexpectedly
fetch-pack from 'me@me.mydevbox.com:/home/chris/myproject' failed.

(the file-names have been changed to protect the guilty... !)

Both boxes run Solaris 10 AMD. I have done some digging, if I add --upload-pack=$(which git-upload-pack) the command works, (and proves that $PATH contains the path to 'git-upload-pack' as per the RTFM solution) but this is really annoying, plus 'git push' doesn't work, because I don't think there is a --unpack= option.

Incidentally, all the git commands work fine from my local box, it is the same version of the software (1.5.4.2), installed on the same NFS mount at /usr/local/bin.

Can anybody help?

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
Chris Huang-Leaver
  • 6,059
  • 6
  • 41
  • 67
  • 1
    See also https://stackoverflow.com/questions/1509246/git-over-ssh-without-git-being-installed-on-server , for the case where you want to use a remote repo that does not have `git` installed on the remote machine – M.M Jun 25 '21 at 09:33

17 Answers17

173

Make sure git-upload-pack is on the path from a non-login shell. (On my machine it's in /usr/bin).

To see what your path looks like on the remote machine from a non-login shell, try this:

ssh you@remotemachine echo \$PATH

(That works in Bash, Zsh, and tcsh, and probably other shells too.)

If the path it gives back doesn't include the directory that has git-upload-pack, you need to fix it by setting it in .bashrc (for Bash), .zshenv (for Zsh), .cshrc (for tcsh) or equivalent for your shell.

You will need to make this change on the remote machine.

If you're not sure which path you need to add to your remote PATH, you can find it with this command (you need to run this on the remote machine):

which git-upload-pack

On my machine that prints /usr/bin/git-upload-pack. So in this case, /usr/bin is the path you need to make sure is in your remote non-login shell PATH.

Matt Curtis
  • 23,168
  • 8
  • 60
  • 63
  • 2
    The path was correct if I run the command on my machine, but wrong if I run it the other way around. (from the remote machine back to mine) Editing my local .bashrc fixed it. Thanks – Chris Huang-Leaver Jan 21 '09 at 11:58
  • Against Chris's comments, I found that when Matt's command reported the wrong path, I logged in with "ssh you@remotemachine" and changed the .bashrc there; that fixed the problem. Changing the "local" .bashrc makes no difference that I can see. – Dan Fabulich Mar 24 '09 at 00:07
  • I had ssh'd into a remote machine trying to pull from local system, which is why my .bashrc was the one to change. It's the same issue as you but reversed. – Chris Huang-Leaver Jul 16 '09 at 12:57
  • I had an additional problem; when I ssh'd into the remote machine and executed git-upload-pack, it found it find, but not when I was cloning. (ie: the PATH was different between the direct login and the remote execution). Setting the path in .bashrc, as described here, fixed the problem. – Craig Walker Nov 21 '09 at 22:13
  • Good to hear Craig. The way you describe it, I think it's actually the same problem the OP had. – Matt Curtis Nov 27 '09 at 23:20
  • For the benefit of anyone else who may be trying this without success: I had this same problem and it turned out that the first command in my .bashrc was `[ -z "$PS1" ] && return` which exits if the shell is non-interactive. Once I commented that out it worked. – David Z Feb 03 '10 at 06:44
  • On OS X it seems to use `.profile` by default(?), `ln -s .profile .bashrc` fix this for me.. – dbr Mar 06 '10 at 00:18
  • @David Zaslavsky: You shouldn't just delete that statement, but rather replace it with with "if [[ -n $PS1 ]] ; then " (minus quotes) and then put a "fi" (minus quotes) at the end of your bashrc, putting all of the original contents inside that if-statement and putting whatever else you might need outside of it. – semperos Nov 02 '10 at 18:02
  • @semperos: true. Or equivalently, I wound up just putting my path manipulation commands before the `return`. – David Z Nov 04 '10 at 05:34
  • @dbr Login shell will read /etc/profile and then .bash_profile. Non-login shell will read .bashrc only. – Yantao Xie Apr 13 '11 at 13:38
  • 1
    In my case the command wasn't found because git was installed via MacPorts, which puts it in `/opt/local/bin`. Adding this to my `.bashrc` via `PATH=$PATH:/new/path/here` worked for me. – Ben Scheirman May 16 '11 at 23:22
  • What does the back-slash before $PATH in "ssh you@remotemachine echo \$PATH" mean? If I include it, the git path is not printed. If I omit it, it is. All this via ssh; if I include the backslash on the local terminal, the word '$PATH' is echoed? – Nicolas Miari Jun 13 '12 at 13:49
  • 1
    @ranReloaded The backslash is supposed to escape the dollar sign and prevent expansion of $PATH on the local machine, and instead pass "echo $PATH" literally to the remote machine. It might depend on what shell you're using; it works for me in zsh and bash. You might be able to get the right result using single quotes, e.g. "ssh you@remotemachine 'echo $PATH'" - give that a go. Otherwise, what shell are you using? Maybe someone else here uses that shell and can give you the workaround. – Matt Curtis Jun 14 '12 at 01:54
  • Oh, I see. I seem to be using bash. I've since tampered with .profile, .bash_profile and even .git/configure to get it right... Must check again – Nicolas Miari Jun 14 '12 at 04:04
  • OK, I added Andy's solution ("sudo ln -s /[path/to/git]/bin/git* ." Below) and now it is working (though I'm pretty confident I forgot to include the last period '.'). – Nicolas Miari Jun 14 '12 at 07:16
  • I have scratched my head a lot about this and read lots of different tutorials. There are mentions to SSH keys all around, but I don't remember setting those up for my git user on my server. Am I missing something? (the user git is in the SSH Users group) – Nicolas Miari Jun 14 '12 at 07:17
  • 3
    @ranReloaded: When you say "the git path is not printed", do you mean that ssh shows lots of stuff but not the path that git is on? If so then you have just the same problem that the OP had, and using a symlink is just a bandaid. The `"ssh .. echo \$PATH"` command will show you the path on the remote machine, which might be different to your login path, but this is the crucial thing to get right to make it work, and you can do that by setting PATH to include git in the `.bashrc` on the remote machine. According to the manpage, `.profile`/`.bash_profile` are only read for interactive logins. – Matt Curtis Jun 15 '12 at 05:57
  • 1
    @ranReloaded: As an experiment, *on the remote machine, in your home directory*, try getting rid of all the other bash dotfiles (`.profile`, `.bash_profile`, `.login`, `.bash_login` etc.) and just have the single line "export PATH=$PATH:/your/path/to/git" in `.bashrc`. Then, on the local machine, try `ssh you@remote echo \$PATH`: it should show the path with /your/path/to/git on the end. If that works, you should be able to use git over ssh without issues, and you can put back the other stuff from your dotfiles. If it fails, post what it shows. – Matt Curtis Jun 15 '12 at 06:00
  • @ranReloaded: oh - if you're using a different user, "git", do it in that home directory (on the remote machine), not your own, and `ssh git@remote echo \$PATH`. from your local machine. – Matt Curtis Jun 15 '12 at 06:02
  • 1
    Thanks a lot, Matt. This clarifies a lot about the whole confusion with all the dot files. The symlink worked, but I will try your methos to clean things up. – Nicolas Miari Jun 15 '12 at 06:49
  • The weird thing is, push through ssh WAS working OK, but not from the Xcode GUI. – Nicolas Miari Jun 15 '12 at 06:50
68

You can also use the "-u" option to specify the path. I find this helpful on machines where my .bashrc doesn't get sourced in non-interactive sessions. For example,

git clone -u /home/you/bin/git-upload-pack you@machine:code
Brian Hawkins
  • 2,813
  • 2
  • 25
  • 17
  • 2
    Just to note: [here](http://stackoverflow.com/questions/820517/bashrc-at-ssh-login) are instructions on how to make .bashrc get sourced on ssh sessions. – sp3ctum Oct 22 '13 at 08:52
62

Building on Brian's answer, the upload-pack path can be set permanently by running the following commands after cloning, which eliminates the need for --upload-pack on subsequent pull/fetch requests. Similarly, setting receive-pack eliminates the need for --receive-pack on push requests.

git config remote.origin.uploadpack /path/to/git-upload-pack
git config remote.origin.receivepack /path/to/git-receive-pack

These two commands are equivalent to adding the following lines to a repo's .git/config.

[remote "origin"]
    uploadpack = /path/to/git-upload-pack
    receivepack = /path/to/git-receive-pack

Frequent users of clone -u may be interested in the following aliases. myclone should be self-explanatory. myfetch/mypull/mypush can be used on repos whose config hasn't been modified as described above by replacing git push with git mypush, and so on.

[alias]
    myclone = clone --upload-pack /path/to/git-upload-pack
    myfetch = fetch --upload-pack /path/to/git-upload-pack
    mypull  = pull --upload-pack /path/to/git-upload-pack
    mypush  = push --receive-pack /path/to/git-receive-pack
Community
  • 1
  • 1
Garrett
  • 47,045
  • 6
  • 61
  • 50
  • I tried your suggestion, also added "which git-receive-pack" to path in .bashrc but somehow git push still doesn't work for me, though repo upload works fine. Any idea why this could happen? – coredump Oct 12 '12 at 17:44
  • @coredump, setting "remote.origin.receivepack" should eliminate the need to modify PATH in your .bashrc. Try ``git push --receive-pack /full/path/to/git-receive-pack`` on it's own, tweak until that's successful, then modify .git/config (or run "git config") to permanently set the receive-pack path. – Garrett Oct 12 '12 at 18:19
  • Thanks everyone for your responses! In my case the fetch server and push server were different and the fetch server did not have write permissions. when I use git push everything works fine. – coredump Oct 24 '12 at 18:59
  • This article helped explain this a little better, and this did the trick for me, thanks! http://www.twohard.com/blog/remedy-git-upload-pack-or-git-receive-pack-command-not-found-errors-when-you-have-limited-acces – thaddeusmt Jan 07 '13 at 16:30
30

I found and used (successfully) this fix:

# Fix it with symlinks in /usr/bin
$ cd /usr/bin/
$ sudo ln -s /[path/to/git]/bin/git* .

Thanks to Paul Johnston.

Andy
  • 11,215
  • 5
  • 31
  • 33
13

Mac OS X and some other Unixes at least have the user path compiled into sshd for security reasons so those of us that install git as /usr/local/git/{bin,lib,...} can run into trouble as the git executables are not in the precompiled path. To override this I prefer to edit my /etc/sshd_config changing:

#PermitUserEnvironment no

to

PermitUserEnvironment yes

and then create ~/.ssh/environment files as needed. My git users have the following in their ~/.ssh/environment file:

PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/git/bin

Note variable expansion does not occur when the ~/.ssh/environment file is read so:

PATH=$PATH:/usr/local/git/bin

will not work.

tom
  • 131
  • 1
  • 2
  • This seems like the perfect tip, but it's not working here for 10.6.6. ssh user@host echo \$PATH still shows the hard coded build path. Addded .ssh/environment with non-expanding required path. Changed /etc/sshd_config PermitUserEnvironment yes. no dice. Any suggestions? Thanks. – Dad Apr 06 '11 at 06:42
  • Also tried setting BASH_ENV='~/.nibashrc' on the client machine and making a file in that with the expanded path in it. also no dice. – Dad Apr 06 '11 at 06:45
  • Ok. so putting the path in .bashrc on the machine you are connecting to worked for me. – Dad Apr 06 '11 at 06:48
  • thanks for the tip about variable expansion not working for .ssh/environment – Denis Jun 25 '15 at 17:01
  • Upvote for explaining that var expansion does to work. – XMAN Aug 02 '19 at 23:32
7

Matt's solution didn't work for me on OS X, but Paul's did.

The short version from Paul's link is:

Created /usr/local/bin/ssh_session with the following text:

#!/bin/bash
export SSH_SESSION=1
if [ -z "$SSH_ORIGINAL_COMMAND" ] ; then
    export SSH_LOGIN=1
    exec login -fp "$USER"
else
    export SSH_LOGIN=
    [ -r /etc/profile ] && source /etc/profile
    [ -r ~/.profile ] && source ~/.profile
    eval exec "$SSH_ORIGINAL_COMMAND"
fi

Execute:

chmod +x /usr/local/bin/ssh_session

Add the following to /etc/sshd_config:

ForceCommand /usr/local/bin/ssh_session

Skeletron
  • 233
  • 3
  • 7
  • Interesting to hear it didn't work for you. Do you mind telling what it said PATH on the remote machine was, when you ran "ssh you@remote \$PATH"? – Matt Curtis Sep 24 '09 at 10:47
7

For bash, it needs to be put into .bashrc not .bash_profile (.bash_profile is also only for login shells).

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
5

I got these errors with the MsysGit version.

After following all advice I could find here and elsewhere, I ended up:

installing the Cygwin version of Git

on the server (Win XP with Cygwin SSHD), this finally fixed it.

I still use the MsysGit version client side

..in fact, its the only way it works for me, since I get POSIX errors with the Cygwin Git pull from that same sshd server

I suspect some work is still needed this side of Git use.. (ssh+ease of pull/push in Windows)

Ric Tokyo
  • 6,577
  • 3
  • 30
  • 48
1

My case is on Win 10 with GIT bash and I don't have a GIT under standard location. Instead I have git under /app/local/bin. I used the commands provided by @Garrett but need to change the path to start with double /:

git config remote.origin.uploadpack //path/to/git-upload-pack
git config remote.origin.receivepack //path/to/git-receive-pack

Otherwise the GIT will add your Windows GIT path in front.

felixc
  • 168
  • 2
  • 11
1

It may be as simple as installing git on the remote host (like it was in my case).

sudo apt-get install git

Or equivalent for other package management systems.

truefusion
  • 485
  • 4
  • 9
1

Like Johan pointed out many times its .bashrc that's needed:

ln -s .bash_profile .bashrc

Stefan Lundström
  • 1,262
  • 11
  • 12
1

You must add the

export PATH=/opt/git/bin:$PATH

before this line in the .bashrc:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Otherwise all export statements will not be executed (see here).

Community
  • 1
  • 1
Dennis
  • 4,011
  • 7
  • 36
  • 50
0

For zsh you need to put it in this file: ~/.zshenv

For example, on OS X using the git-core package from MacPorts:

$ echo 'export PATH=/opt/local/sbin:/opt/local/bin:$PATH' > ~/.zshenv

miknight
  • 493
  • 1
  • 4
  • 8
0

Add the location of your git-upload-pack to the remote git user's .bashrc file.

Yeison
  • 193
  • 3
  • 6
0

If you're using GitHub Enterprise, make sure the repo is public, not internal. There may be other ways to solve this for an internal repo, but this was the quickest way to solve the problem without involving more time and people.

Snekse
  • 15,474
  • 10
  • 62
  • 77
0

I have been having issues connecting to a Gitolite repo using SSH from Windows and it turned out that my problem was PLINK! It kept asking me for a password, but the ssh gitolite@[host] would return the repo list fine.

Check your environment variable: GIT_SSH. If it is set to Plink, then try it without any value ("set GIT_SSH=") and see if that works.

RAVolt
  • 83
  • 2
  • 9
0

For me it looks like a bug in the setup.

I use a Windows server and just set up Git with the default settings. There was no mention of "git-upload-pack" in any instructions. I found an executable file in "C:\Programs\Git\mingw64\bin" and added it to the Windows environment variables.

The incredible Jan
  • 741
  • 10
  • 17