How to setup a Git repository

This howto will describe how to setup a Git repository:
  • Dedicated user for Git repos
  • SSH will be used for commits
  • Enable gitweb for web access (Apache will be used)
  • Anonymous cloning using the Git protocol

For those who don't know what Git is:

You should know how to use Git before reading on.

Install devel/git. Select GITWEB. SVN, P4, and CVS are optional. Deselect them if you don't plan to use them.

Create a git user with uid and gid as 9418:
Code:
# pw groupadd -n git -g 9418
# pw useradd -n git -u 9418 -g git -c git -d /git \
	-s /usr/local/libexec/git-core/git-shell -h -

The git-shell is used for this user, and home is set as /git/. The repos will be under /git/base/.

Make sure the permissions of the directory are correct and create /git/base/:
Code:
# chown git:git /git/
# chmod 755 /git
# mkdir /git/base/
# chown git:git /git/base/
# chmod 775 /git/base/

Next, add users to the git group to be able to create repositories under /git/base/. This isn't necessary for users who only need commit access.
Code:
# vi /etc/group
...
git:*:9418:user1,user2

We'll be using SSH keys for authenication, so collect the public keys of all the users who need commit access. Then, put the public keys into the right place:
Code:
# mkdir /git/.ssh/
# chmod 700 /git/.ssh/
# touch /git/.ssh/authorized_keys
# chmod 600 /git/.ssh/authorized_keys
(Put the public keys into authorized_keys, one per line)
# chown -R git:git /git/.ssh/

Everything should be set now. Let's create a repo for testing (change to a user that has been added to the git group and has commit access).
Code:
$ mkdir /git/base/test.git
$ cd /git/base/test.git && git init --bare --shared

Create a local repo and commit:
Code:
$ mkdir ~/test
$ cd ~/test && git init
$ echo '123456' > foo
$ git add .
$ git commit

Now push it into the remote repo (remember to replace git.example.com with your own hostname):
Code:
$ git remote add origin git@git.example.com:base/test.git
$ git push origin master

Don't delete the test repo yet.

Since the git repo should be up and working by now, let's enable gitweb for web access. Apache's VirtualHost will be used for this.

Copy gitweb files to /home/www/git/:
Code:
$ cp /usr/local/share/examples/git/gitweb/git* /home/www/git/

Modify Apache settings (change the ServerName and the access and error log paths as necessary):
Code:
<VirtualHost *:80>
  ServerAdmin webmaster@yourhostname
  DocumentRoot "/home/www/git"
  ServerName git.example.com
  ErrorLog "/path/to/errolog"
  CustomLog "/path/to/accesslog" combined

  <Directory "/home/www/git">
    Options ExecCGI
    Order allow,deny
    Allow from all

    DirectoryIndex gitweb.cgi
    AddHandler cgi-script .cgi
  </Directory>
</VirtualHost>

Now edit gitweb.cgi:
Code:
-our $projectroot = "/pub/scm";
+our $projectroot = "/git/base";
...
-our $home_link_str = "projects";
+our $home_link_str = "base";
...
-our $site_name = ""
+our $site_name = "git.example.com"
...
-our $home_text = "indextext.html";
+our $home_text = "content.html"; (Leave empty if unnecessary)
...
-our $projects_list_description_width = 25;
+our $projects_list_description_width = 40; (Give the description a bit more space)

Change the $site_header, $home_text, and $site_footer as needed.

Open up your browser and check if it's working.

You might notice that the description of the test repo hasn't been modified yet. You might also want to change the owner.

For the description, edit /git/base/test.git/description. Put this into /git/base/test.git/config to change the owner:
Code:
[gitweb]
        owner = Your Name

Only the Git protocol isn't working now.

Add this to /etc/rc.conf:
Code:
git_daemon_enable="YES"
git_daemon_directory="/git"
git_daemon_flags="--syslog --base-path=/git --export-all"

Start the daemon:
Code:
# /usr/local/etc/rc.d/git_daemon start

You should now be able to clone using the Git protocol. Try it out:
Code:
$ cd /tmp/
$ git clone git://git.example.com/base/test.git

One last thing. You might want to list URLs for cloning repos on the summary page of test.git in gitweb. Just add this line (the url line) to the [gitweb] section of /git/base/test.git/config:
Code:
[gitweb]
        owner = Your Name
        url = git://git.example.com/base/test.git

This line can appear more than once if there are multiple URLs:
Code:
[gitweb]
        owner = Your Name
        url = git://git.example.com/base/test.git
        url = git@git.example.com:base/test.git
 
Thanks a lot for this useful article!

I've noticed one problem on my FreeBSD 7.2 - looks like it is better to add one more flag (--detach) to the rc.conf:
Code:
git_daemon_flags="--syslog --base-path=/git --export-all --detach"
 
You can use devel/py-gitosis to manage git users.
This way system only needs 1 git user. Other users will be virtual users (authorization with ssh public/private keys)

It is very nice peace of software...
I use gitosis & cgit at git.bsdroot.lv
 
VictorGT said:
Thanks a lot for this useful article!

I've noticed one problem on my FreeBSD 7.2 - looks like it is better to add one more flag (--detach) to the rc.conf:
Code:
git_daemon_flags="--syslog --base-path=/git --export-all --detach"

I have the same problem on FreeBSD 9, if you don't add --detach in rc.conf, the daemon is started in the foreground and the boot process is stuck at launching the daemon (before SSH :/)

Except that, everything works very well ! Thank you.
 
On that stage it doesn't work on my FBSD 11.1 server.

Code:
$ git remote add origin git@git.example.com:base/test.git
$ git push origin master

I've got
Code:
[user@freebsd /usr/home/user/test]$ git push origin master
Password for git@freebsd64.work:
fatal: '/test.git' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
[user@freebsd /usr/home/user/test]$

Access rights is fine. I've checked them. And repository exist as well.
 
On that stage it doesn't work on my FBSD 11.1 server.
Keep in mind that the tutorial is over 8 years old, many things could have changed in the mean time.

Code:
$ git remote add origin git@git.example.com:base/test.git
$ git push origin master
Solely judging from the errors I'm tempted to blame the repository (or URL) instead of the command. How sure are you that you're using a legit repository? Also: what is master supposed to be?

If you cloned it then I don't understand why you'd need to manually add it as remote. And you also don't really need to do this in two steps either. git push -u git@git.example.com:base/test.git +HEAD, this would also work. You push the current branch onto a remote repository and define it as the upstream in one go.

(edit) I also couldn't help notice that you didn't specify a protocol while adding the remote. That too could have some influence here.
 
Thank you for response. Below is a sequence of commands that I'm used and some part of configs.
All this is stored on same machine.
Code:
[git] $ cd ~ && cd repositories
[git] $ mkdir test.git && cd test.git && git init --bare
...or
[git] $ git init --bare test.git

...then add to gitosis.conf
Code:
[group blah]
members = user@freebsd.work
writable = test

...then create local repository
Code:
[user] $ cd ~
[user] $ mkdir test && cd test
[user] $ git init
[user] $ echo "12345" > ./abc.txt
[user] $ git add .
[user] $ git commit (save and exit. Commit successful)
...then add to local repo's config the remote url but on local machine
[user] $ git remote add origin ssh://git@localhost/test.git
[user] $ git push origin master

...and got
Code:
[user@freebsd /usr/home/user/test]$ git push origin master
Password for git@freebsd64.work:
fatal: '/test.git' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.
[user@freebsd /usr/home/user/test]$

Where I'm doing wrong ?
 
I already figured it out myself. After creation of bare repository we was need to create a CLONE of the bare repository. Use the 'git clone' instead 'git init' if you need to create git on local server.
Code:
[user] $ mkdir test && cd test
[user] $ git clone /home/git/repositories/test.git
[user] $ echo "12345" > ./abc.txt
[user] $ git add .
[user] $ git commit
[user] $ git remote add origin ssh://git@localhost/test.git
[user] $ git push origin master
And it works now.
 
I figured this out itself. After creation of bare repository we was need to create a CLONE of the bare repository. Why this is wasn't explained above ?
Because there's no real need to do that.

Something else in between must have gone wrong for you. I still suspect that your refspec was wrong, where did you get the idea of using master from anyway? The regular notation would be HEAD which indicates the current status of your repository. See also gitrevisions(7). Notice how master could also have double meanings?

And I say this after having written / shared this piece (more recent even):

https://forums.freebsd.org/threads/using-git-on-freebsd-why-and-how.64898/

After you made a bare clone available you can immediately push onto it when done right.
 
Sorry I'd modified my post a little bit.

Actually I'm disagree because if thread called like "how to setup a git..." then it means thread should explain different scenarios. But this is not a complain. I would like to help improve it.

...where did you get the idea of using master from anyway?
I don't understand this question. Not from anyway, but master branch should be accessible at least within local host, isn't ?

What refspec do you mean?

p.s. This is did not work as well git push -u git@git.example.com:base/test.git +HEAD

I believe this is should works. But it doesn't on my particular server.
Code:
$ git remote add origin git@localhost/test.git
And I have no idea why.
 
I'm figured out a problem with using $ git remote add origin git@localhost/test.git within local server.
It was necessary to create a ssh key for user user and append a key to git.
Need to do follow:
Code:
$ cd /home/user/.ssh && ssh-keygen
$ cat /home/user/.ssh/id_rsa.pub >> /home/git/.ssh/authorized_keys 
$ nano /home/git/.ssh/authorized_keys

...should look inside like this

command="gitosis-serve user@freebsd.work",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa PUBLIC_KEY_STRING_HERE user@freebsd.work

So it works fine now for both. For clone and local remote
 
And this is was not a final solution as it turned out. Also you gonna need to change permissions and replace some accesses.

after this # pw useradd -n git -u 12345 -g git -c git -d /home/git -s /bin/sh -h - we need to edit two files

Code:
/etc/passwd
git:*:1001:12345:git:/home/git:/bin/sh

1001 - is ID of the user which should has access to the editable folder. In each particular case may differ.

/etc/master.passwd
git:*:1001:12345::0:0:git:/home/git:/bin/sh

You also could set 'git' user password by # passwd git, but this is not necessary.

Then run command below (It will update pwd.db).
Code:
# pwd_mkdb /etc/master.passwd

Then check the permissions for all files and folders and especially for /home/git/.ssh/authorized_keys
 
Code:
[user@freebsd /usr/home/user/test]$ git push origin master
Password for git@freebsd64.work:
fatal: '/test.git' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.
[user@freebsd /usr/home/user/test]$

Where I'm doing wrong ?

I believe you are going wrong here:
Code:
git remote add origin git@git.example.com:base/test.git

The same fatal message appeared for me until I changed the path to "/git/base/test.git" after creating the local repository.

Code:
git remote remove origin
Code:
git remote add origin git@git.example.com:/git/base/test.git
 
Back
Top