====== Some experimentation with git ====== The world has already moved from Centralized Version Control Systems (CVS, SVN et.al) to Distributed Version Control Systems, and it has for long been my intention to play catch-up on that. For me, and for quite a lot of open-source oriented people, the de-facto choice has become Git (http://git-scm.com/), so that is the DVCS I will be focusing on. Now, starting to use Git as a single user, or even as multiple contributors when working on a shared system is very straight-forward. In these scenarios, you can live with all source-control happening in the locally available file system. The [[http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html|git tutorial]] and [[http://cworth.org/hgbook-git/tour/|Carl Worths "A tour of git"]] will tell you hot to get started with that. But, I keep having the desire/need to publish my work more publicly than on my local file system. And coming from a CVSC-background, I have become very used to having external contributors to my code, without having to be a "patch-broker". In addition, I use "VCS-pushing" of code as a form of easily available backup. I have little or no desire to add local Unix-accounts to my web-server to allow for external contributions, and I would like to avoid having to run a separate Daemon process. With that basis, I'll describe my foray into git. NOTE: For those of you who want to know about using git, and are not interrested in setting up a "svn-to-git-migration-like" server, I have a section on [[#Everyday use of git]] towards the end. ===== About the environment ===== I am implementing this using a web-server running Debian Lenny and apache2, hosting all git repositories from a separate virtualhost. My example server hostname will be "git.example.com". My example clients will be a Debian Lenny system and an Ubuntu 9.10.11.12 FIXME. ===== Installing ===== ===== Attempt one ===== As you probably get from the heading, I have ended up using a couple of tries getting my setup workable. There is one single reason for this; I started out with the old version of git supplied with Debian Lenny, git 1.5.6.5. But I realized after setting this scenario up, that this version will allow for either anonymous read/write or authenticated read/write. There is no sane way to do anonymous read, authenticated write. To get that functionality, you have to go for git 1.6 or newer, where the more recent [[http://www.kernel.org/pub/software/scm/git/docs/git-http-backend.html|git-http-backend]] is supported. There is still an important reason to keep this part of the document. I have not been able, despite serious attempt, troubleshooting, irritation and swearing, to get a git 1.7.1 http-backend based setup working with git-push from a 1.5.6 client! So, if you need to support the Debian Lenny default git version for direct upload (push) over HTTP, use the information in this section. On the other hand, if you can live with having to be a patch-broker for users of this older version of git, the [[#Attempt two]] section is for you. ==== Serverside install ==== We need to install the git software first, and then prepare a repository for publication via web: apt-get install git-core mkdir /var/www/git.example.com mkdir /var/www/git.example.com/.passdb cd /var/www/git.example.com mkdir test-repo.git cd test-repo.git git --bare init chown -R www-data.www-data . chmod +x hooks/post-update Next, we create the required configuration of Apache2's VirtualHost: cat << EOF > /etc/apache2/sites-available/git.example.com.conf ServerAdmin webmaster@example.com ServerName git.example.com DocumentRoot /var/www/git.example.com Options +Indexes AllowOverride None Order allow,deny allow from all AllowOverride None Order deny,allow deny from all DAV on AuthType Basic AuthName "Git" AuthUserFile /var/www/git.example.com/.passdb/test.git Require valid-user EOF So, this VirtualHost will require: * A htpasswd file for users / groups * The mod_dav module * The mod_dav_fs module htpasswd -c /var/www/git.example.com/.passdb/test.git testuser a2enmod dav a2enmod dav_fs a2ensite git.example.com /etc/init.d/apache2 reload ==== Clientside install ==== First, we need to test that WebDAV works properly. I do this using cadaver, the command line DAV client: sudo apt-get install cadaver cadaver http://git.example.com/test-repo.git Authentication required for Git test on server `git.example.com': Username: testuser Password: With that working, it is time to prepare our local git environment. Steps to do here: * Set up automatic authentication for curl/git-push-http * Verify authentication * Install the git program core * Set up your identity as represented with git. Change this as needed, in the form I list this, I completely replace any previous content: cat << EOF > ~/.netrc machine git.example.com username testuser password Pa55w0rd EOF chmod 0600 ~/.netrc To verify that the .netrc file works, this should not fail: curl --netrc --location -v http://git.example.com/test-repo.git/HEAD Install and configure git: sudo apt-get install git-core git config --global user.name "My Name" git config --global user.email email@example.com The setup is now tested with a sample data-set. I did quite a bulk of commands to test and troubleshoot my setup, I am listing them here just as much for my own reference as yours :) cd ~/testcode git init git add . git commit git push http://testuser@git.example.com/test-repo.git/ master git branch git branch testing git checkout testing vim newfile git add newfile git commit git push http://testuser@git.example.com/test-repo.git/ testing git ls-remote http://git.example.com/test-repo.git mkdir ../testout cd ../testout git clone http://testuser@git.example.com/test-repo.git git branch -a git checkout -b testing origin/testing Note that whenever you need to add a new repository to this kind of setup, you will have to update the apache configuration, adding a new Location block. ===== Attempt two ===== As I mentioned in the [[#Attempt one]] section, the older versions of git leave a bit to be desired when it comes to access options. But, looking at the results from the [[https://git.wiki.kernel.org/index.php/GitSurvey2010#05._Which_Git_version.28s.29_are_you_using.3F|Git User's Survey 2020]], it seems that maintaining support for these older git-clients should not really be needed. So, I tore the previous setup down, and started with more modern, recent technology. I can live with users of git 1.5.x submitting patches via email, and forcing people who need direct push access into using a newer version. ==== Serverside install ==== The serverside install starts out very similar to the previous attempt, but this time differs strongly by pulling in the new (1.7.x) version of git from Lenny Backports. cat << EOF > /etc/apt/sources.list.d/lenny-backports.list deb http://backports.debian.org/debian-backports lenny-backports main contrib non-free EOF apt-get update apt-get install debian-backports-keyring apt-get autoremove git-core apt-get -t lenny-backports install git Preparation of our initial repo is identical to attempt one: mkdir /var/www/git.example.com mkdir /var/www/git.example.com/.passdb cd /var/www/git.example.com mkdir test-repo.git cd test-repo.git git --bare init chown -R www-data.www-data . chmod +x hooks/post-update The VirtualHost definition for Apache2 is changed somewhat. Most notably, it has become longer, and now uses a ScriptAlias to execute CGI instead of relying on WebDAV ServerAdmin webmaster@example.com ServerName git.example.com DocumentRoot /var/www/git.example.com Options +Indexes +FollowSymLinks +MultiViews +ExecCGI AllowOverride None Order allow,deny allow from all AllowOverride None Order deny,allow deny from all Options None Options ExecCGI CustomLog /var/log/apache2/git.example.com_access.log combined ErrorLog /var/log/apache2/git.example.com_error.log LogLevel warn SetEnv GIT_PROJECT_ROOT /var/www/git.example.com SetEnv GIT_HTTP_EXPORT_ALL SetEnv REMOTE_USER=$REDIRECT_REMOTE_USER ScriptAliasMatch \ "(?x)^/(.*/(HEAD | \ info/refs | \ objects/(info/[^/]+ | \ [0-9a-f]{2}/[0-9a-f]{38} | \ pack/pack-[0-9a-f]{40}\.(pack|idx)) | \ git-(upload|receive)-pack))$" \ "/usr/lib/git-core/git-http-backend/$1" AuthType Basic AuthName "Git Access" AuthUserFile /var/www/git.example.com/.passdb/test.git Require valid-user Now, create the htpasswd file and enable the configuration. Note that I disable my old WebDAV support completely here. If you need WebDAV for something unrelated, please make sure you skip those lines :) a2dismod dav a2dismod dav_fs htpasswd -c /var/www/git.example.com/.passdb/test.git testuser a2ensite git.example.com /etc/init.d/apache2 reload ==== Clientside install ==== This is for Debial Lenny. If you have the older version of git-core installed, start by removing it: sudo apt-get install git-core Next, pull in the new version from Lenny Backports: cat << EOF > /etc/apt/sources.list.d/lenny-backports.list deb http://backports.debian.org/debian-backports lenny-backports main contrib non-free EOF apt-get update apt-get install debian-backports-keyring apt-get -t lenny-backports install git Now, configure git global options (your identity): sudo apt-get install git-core git config --global user.name "My Name" git config --global user.email email@example.com Set up a .netrc file to avoid those pesky password prompts. Change this as needed, in the form I list this, I completely replace any previous content: cat << EOF > ~/.netrc machine git.example.com username testuser password Pa55w0rd EOF chmod 0600 ~/.netrc The setup is now tested with a sample data-set. Note a difference from the 1.5-series git version, I no longer list the username in the git http URL. cd ~/testcode git init git add . git commit git push http://git.example.com/test-repo.git/ master mkdir ../testout cd ../testout git clone http://git.example.com/test-repo.git ===== A prettyfied web-view: gitweb ===== Install gitweb from Lenny Backports, and point it to the root of the GIT projects: apt-get install -t lenny-backports gitweb Add the following to the Apache2 VirtualHost: Options FollowSymLinks +ExecCGI AddHandler cgi-script .cgi Alias /gitweb /usr/share/gitweb ScriptAlias / /usr/share/gitweb/index.cgi/ AllowOverride None Order deny,allow deny from all AuthType Basic AuthName "Git Private" AuthUserFile /var/www/git.example.com/.passdb/private_users Require valid-user cat << EOF > /etc/gitweb.conf # path to git projects (.git) $projectroot = "/var/www/git.example.com"; # directory to use for temp files $git_temp = "/tmp"; # target of the home link on top of all pages #$home_link = $my_uri || "/"; # html text to include at home page # $home_text = "indextext.html"; $home_text = "/var/www/git.example.com/.gitweb/index.inc"; # The text on the home link in the breadcrumbs $home_link_str = "git.example.com"; # file with project list $projects_list = "/var/www/git.example.com/.gitweb/list"; # Hide any repo not listed in the $projects_list $strict_export = 1; # stylesheet to use $stylesheet = "/gitweb/gitweb.css"; # logo to use $logo = "/gitweb/git-logo.png"; # the 'favicon' $favicon = "/gitweb/git-favicon.png"; EOF echo "Example text" > /var/www/git.example.com/.gitweb/index.inc ls | grep -v private | awk ' { print $1 " Me" }' > /var/www/git.example.com/.gitweb/list ===== Everyday use of git ===== ===== References ===== http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html http://cworth.org/hgbook-git/tour/ http://www.kernel.org/pub/software/scm/git/docs/howto/setup-git-server-over-http.txt http://www.espace.com.eg/blog/2010/11/10/migrating-from-subversion-to-git/ http://www.kernel.org/pub/software/scm/git/docs/git-http-backend.html