Search code examples
gitrepositorygit-pushgit-clone

Using git on a single server, i.e. no truly remote origin


This seems so dumb, but I can't figure it out. Tons of instructions out there for cloning or adding a remote server, or pushing to a cloned repository. But I'm trying to figure out how to set up a git repository in a shared directory on a server, and let other people collaborate from clones in their personal directories.

This is what I've tried:

abalter@U1:~$ mkdir mainrepo
abalter@U1:~$ cd mainrepo/
abalter@U1:~/mainrepo$ echo "inital entry" > text.txt
abalter@U1:~/mainrepo$ git init
Initialized empty Git repository in /home/abalter/mainrepo/.git/
abalter@U1:~/mainrepo$ git add text.txt 
abalter@U1:~/mainrepo$ git commit -m "initial commit"
[master (root-commit) fb829d6] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 text.txt
abalter@U1:~/mainrepo$ cd ..
abalter@U1:~$ git clone mainrepo/ userrepo
Cloning into 'userrepo'...
done.
abalter@U1:~$ cd userrepo/
abalter@U1:~/userrepo$ echo "users addition" >> text.txt 
abalter@U1:~/userrepo$ git commit -am "users addition"
[master 3d4ea94] users addition
 1 file changed, 1 insertion(+)
abalter@U1:~/userrepo$ git add remote origin ../mainrepo/
fatal: ../mainrepo/: '../mainrepo/' is outside repository
abalter@U1:~/userrepo$ git push origin master
Counting objects: 5, done.
Writing objects: 100% (3/3), 267 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error: 
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error: 
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To /home/abalter/mainrepo/
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to '/home/abalter/mainrepo/'
abalter@U1:~/userrepo$ 

I'm clearly missing a step, but I don't know what it is.

EDIT I realize it should have been git remote add origin ../mainrepo. But

abalter@U1:~/userrepo$ git remote add origin ../mainrepo
fatal: remote origin already exists.
abalter@U1:~/userrepo$ 

If it already exists, why can't I push to it?


Solution

  • The answer here is no different than the setup on actual remote machines: a repository you push to should1 be a --bare clone. For instance, to set things whole thing up you start by making a user repository (so that you can make some initial commits):2

    $ mkdir set-it-up && cd set-it-up
    $ git init
    [create and add files as usual and then]
    $ git commit
    

    Then move to the place you want the bare master repo, and, e.g.:

    $ mkdir master-repo.git; cd master-repo.git; git init --bare
    

    (you may want to add --shared or --shared=all, etc.; see the git init documentation). Now you have a bare—no work directory—repository, suitable for both cloning-from and pushing-to.

    To fill it in, you may now fetch (manually) everything from your "set-it-up" repo:

    git fetch /path/to/set-it-up 'refs/*:refs/*'
    

    At this point it's safe to remove your "set-it-up" copy: cloning the master-repo.git directory will get you a fresh clone in which to work, with the clone's origin set to the path of the master-repo.git directory.

    Alternatively, in your set-it-up repo, you can now add the master-repo.git directory as the "origin" URL, then push.


    1Since git 2.5, it's possible to make sensible things (for some value of sensible) happen with a non-shared repository, but this is a bit more complex to describe.

    2You can make the initial bare repository completely empty, if you prefer. When cloning an empty repository, git gripes a bit, but you can then work in the clone and push back to fill in the bare repository.