Using GIT at Savannah

To use Git on Savannah, you first need to enable it for your group; then a cron job will create an empty repository, see VCS Intro.

URL list summary:

  • git://git.savannah.gnu.org/mygroup.git - unencrypted read-only git lightweight protocol
  • ssh://git.savannah.gnu.org/srv/git/mygroup.git - encrypted member read-write developer access using SSH
  • https://git.savannah.gnu.org/git/mygroup.git - encrypted read-only anonymous smart http access
  • http://git.savannah.gnu.org/git/mygroup.git - unencrypted read-only anonymous smart http access, for use behind restrictive firewalls
  • http://git.savannah.gnu.org/r/mygroup.git - unencrypted read-only anonymous smart http access, for use behind excessively restrictive firewalls previously this was the slow dumb protocol but has since been switched to the git smart http protocol the same as the above /git/ path, making this URL redundant with the above)

The links in bold are the preferred and recommended protocols to use. This because they are encrypted to protect against possible man-in-the-middle data corruption. This also protects against broken site proxies and other misconfiguration. And also snooping too! The other link types are also available for those that can't make use of the encryption protected protocols.

Both sv.gnu.org and savannah.gnu.org and the same for nongnu.org are all the same. Use whichever you prefer using. Also all of the domain names exist in both gnu.org and nongnu.org domains.

Web browser: http://git.savannah.gnu.org/gitweb/ http://git.savannah.gnu.org/cgit/

If you use ssh-based access, please verify the host keys first at SshAccess

Note: There is up to a 1/2 hour delay between Git group creation in the web front-end, and its creation on the back-end system. The back-end version control system hosting git creates repositories by running a cron job every half hour.

Basic commands

  • Checkout (read-only):

    git clone https://git.savannah.gnu.org/git/group.git
    

    or

    git clone git://git.savannah.gnu.org/group.git
    

    For example cloning the GNU Hello package.

    git clone https://git.savannah.gnu.org/git/hello
    

    or

    git clone git://git.savannah.gnu.org/hello
    
  • Firewall checkout (read-only): if you're behind a outgoing-traffic-filtering firewall, you can use Git's "dumb protocol" via HTTP. The difference here is the /r/ part of the path instead of the /git/ path for the https and http protocols. Note that the git dumb protocols is SLOWER, both for you and Savannah. But this may work when both git:// and https:// are blocked. Avoid if possible, and please tell your local sysadmin to allow https and/or git protocol on port 9418:

    git clone http://git.savannah.gnu.org/r/group.git
    
  • Group member checkout: If you want to be able to push your changes back into the repository on Savannah then members must use ssh protocol to have write access.

    git clone ssh://login@git.sv.gnu.org/srv/git/group.git
    

    Or using the alternative scp-like format. Both are equivalent.

    git clone login@git.sv.gnu.org:/srv/git/group.git
    

Note that the ssh transport requires an active Savannah account and you must be a member of at least one group in order for your account to be enabled.

Developer setup

(For git 1.5.1 or newer)

Your identity for when you push commits. (Also okay to use the GIT_ environment variables.)

git config --global user.name "Your Name Comes Here"
git config --global user.email you@yourdomain.example.com

Enable colors (optional):

git config --global color.diff auto
git config --global color.status auto
git config --global color.branch auto

Disabling colors [defaults on in later git versions] (optional):

git config --global color.ui false

Note: If colors are enabled and you set the LESS environment variable then it must include the -R option or colors will be shown as their raw escape sequences. Warning: Git knows about pagers and less and if LESS is not set will set it to FRSX but if LESS is set will not modify it.

Developer basic commands

  • Create the initial directory and change to it:

    mkdir git_directory
    cd git_directory
    
  • Initial push / import:

    git init
    touch README
    # edit/add other files...
    # Import everything:
    git add .
    git commit -m "Initial import"
    
    #  initial publication to the 'master' branch
    git push --all login@git.sv.gnu.org:/srv/git/group.git
    

    Note: at this point your repository is not setup to merge _from_ the remote branch when you type 'git pull'. You can either freshly 'clone' the repository (see "Developer checkout" below), or configure your current repository this way:

    git remote add -f origin login@git.sv.gnu.org:/srv/git/group.git
    git config branch.master.remote origin
    git config branch.master.merge refs/heads/master
    
  • Developer checkout (via SSH - beware of punctuation):

    git clone ssh://login@git.sv.gnu.org/srv/git/group.git
    # or
    git clone login@git.sv.gnu.org:/srv/git/group.git
    
  • Commit:

    cd group/
    
    # <edit some_existing_file>
    git commit -a -m "I automatically commit modified files"
    
    # <edit some_other_existing_file and something_else>
    git add some_other_existing_file
    git commit -m "I only marked some_other_existing_file for commit"
    
    # Check your changes with the graphical tool
    gitk
    
    # Send everything to Savannah
    git push
    

Fixing checkout from git:// to ssh://

If by mistake a developer has checked out a repository using the public anonymous read-only git:// url this can be changed to the authenticated ssh:// url using git remote set-url:

git remote set-url origin ssh://login@git.sv.gnu.org/srv/git/group.git

If the origin remote has been removed, or if someone wishes to remove origin and recreate it, then it may be removed and set:

git remote rm origin
git remote add origin ssh://login@git.sv.gnu.org/srv/git/group.git
git fetch
git branch -u origin/master master

Shallow checkouts

When bandwidth is an issue, people can download the latest version of your repository without downloading all the history, using "shallow checkouts". Note that such a copy has limitations, see http://www.kernel.org/pub/software/scm/git/docs/git-clone.html, option --depth for details.

Example:

$ git clone --depth 1 git://git.sv.gnu.org/gnulib.git
Initialized empty Git repository in /tmp/gnulib/.git/
remote: Counting objects: 9897, done.
remote: Compressing objects: 100% (5462/5462), done.
Indexing 9897 objects...
remote: Total 9897 (delta 7382), reused 5737 (delta 4419)
 100% (9897/9897) done
Resolving 7382 deltas...
 100% (7382/7382) done

$ du -sh gnulib/.git
6,3M   gnulib/.git

$ du -sh full-gnulib/.git
28M    full-gnulib/.git

git-cvsserver pserver compatibility

You can download a git repository using the CVS client, thanks to a pserver-compatible server from git:

$ cvs -d:pserver:anonymous@pserver.git.sv.gnu.org:/autoconf.git co -d autoconf master
cvs checkout: Updating autoconf
U autoconf/.cvsignore
U autoconf/.gitattributes
U autoconf/.gitignore
U autoconf/.x-sc_prohibit_atoi_atof
U autoconf/.x-sc_space_tab
U autoconf/.x-sc_sun_os_names
U autoconf/.x-sc_trailing_blank
U autoconf/.x-sc_useless_cpp_parens
U autoconf/AUTHORS
U autoconf/BUGS
U autoconf/COPYING
...

Importing from CVS

First thing you may want to do is to tag the state of your CVS repository and declare it as closed. For example:

$ cd my-checked-out-cvs-repository
$ cvs tag cvs-repository-moved-to-git

On your group page, activate git. For example the libcdio group the URL for the group page is:

https://savannah.gnu.org/project/admin/editgroupfeatures.php?group=libcdio

"activated" is in the second column and the "git" row is midway down the page. If you forget to do this or git is not active, you may get a message like this:

Pushing to rocky@git.sv.gnu.org:/srv/git/libcdio.git
fatal: '/srv/git/libcdio.git': unable to chdir or not a git archive
fatal: The remote end hung up unexpectedly

Git comes with the tool, git-cvsimport which will import a CVS repository into a new git repository. You may want to use this for converting your existing CVS repository to a new git repository.

We will use a file which maps a Savannah login name username to real name (option -A) in the git-cvsimport command. The format of this file like this:

rms = Richard M. Stallman <rms@gnu.org>
toto = Another User <me@mydomain.com>
...

After creating this file, run something along the lines of the following mythical shell session:

$ # create authors.txt
$ group='mygroup' # change mygroup
$ myrepository='pserver:anonymous@cvs.savannah.nongnu.org' # Or whatever you usually use for CVS
$ mkdir $group
$ cd $group       # Note: that this is new directory. It is not git yet.
$ module='mymodule'   # adjust this
$ git-cvsimport -A ../authors.txt -p x -v -d:${myrepository}:/sources/$group $module

Adjust the variables myrepostory to be whatever you use to checkout CVS; the cvs.savannah.nongnu.org address won't be correct if your group is a GNU package. If your group is old or has lots of commits, git-cvsimport may take a long time because it is replaying the entire commit history: copying down each version of each file and then performing essentially git-commit for every CVS commit.

This will create a local git repository with at least two branches:

$ git show-branch -a
* [master] Moved from CVS to GIT.
 ! [origin] Moved from CVS to GIT.
--
*+ [master] Moved from CVS to GIT.

Before pushing this to your Savannah group page you might want to rename or remove that "origin" branch. It has the same state and history as the master branch so you won't lose any information. (Footnote: Normally the origin branch is used by developers who prefer to use git while working on groups that only run a central CVS repository. They do their work on "master" but track the changes in the CVS repository in the "origin" branch.) This is not what you are going to do anyway and unfortunately "origin" is also the default alias name for remote git repositories and thus it may lead to unnecessary confusion. You can remove the branch like this:

$ git branch -d origin

Don't worry! If you ever need to recreate that branch you can always do so by branching off at that last CVS commit and call the branch "origin", "cvs" or "back-in-the-dark-ages".

Now you are ready to push this git repository to your Savannah group page using the instructions under Pushing a Newly-Created, Existing, or Converted Git Repository.

If you have converted from a different version control repository to git then consider disabling commits to the previous location so as to prevent confusing history creation.

Importing from SVN

Git comes with 2 SVN-related tools: git-svnimport and git-svn. git-svnimport is for importing revisions (a one-shot import, or incrementally); git-svn is a 2-way gateway to a SVN repository, similar to SVK, more useful for maintaining a local branch than for importing a repository (IMHO). We'll use git-svnimport.

We will use a file which maps a Savannah login name to real name (option -A). It looks like this:

rms = Richard M. Stallman <rms@gnu.org>
toto = Another User <me@mydomain.com>
...

Common invocation:

git-svnimport -v -I .gitignore -A ../authors.txt file:///home/me/svn_repo

To ignore branches:

git-svnimport -v -I .gitignore -A ../authors.txt -b idontexist file:///home/me/svn_repo

git-svnimport assumes there is a trunk, a branches, and a tags directory (names are configurable) and ignores other directories. You may run into troubles if your layout changed during your former SVN life.

You'll usually perform the import several times before getting what you want. For this reason it's preferable to rsync the SVN repository locally:

rsync -av rsync://svn.sv.gnu.org/svn/mygroup svn_repo

or create it from a dump:

wget http://svn.gna.org/daily/mygroup.dump.gz
svnadmin create svn_repo
zcat mygroup.dump.gz | svnadmin load svn_repo/

To access a local copy of the repository, use svnserve:

svnserve -d -r svn_repo

Then access it with git svn with something like:

git svn clone svn://127.0.0.1/mygroup -A authors-transform.txt --stdlayout ./temp.checkout

where mygroup is the subdirectory under svn_repo.

Importing from GNU Arch

Use git-archimport.

Example importing a repository with a group--main--1.0 main archive and a group--release--1.7 tag, converting the Arch-style names into Git-style names:

git-archimport me@domain.tld--2007/group--main--1.0:master group--release--1.7:v1.7

Pushing a Newly-Created, Existing, or Converted Git Repository

If you are importing a repository with tags, e.g. for past releases, use the --tags option to send them with the initial import:

$ login='mylogin'
$ group='mygroup'
$ git push --tags -v ${login}@git.sv.gnu.org:/srv/git/${group}.git

Similarly remember to use the '--all' flags to push all branches, not just the 'master' one:

$ git push --all -v ${login}@git.sv.gnu.org:/srv/git/${group}.git

If you have branches and you don't push all branches when you do a git-clone you may get error messages like the one below:

$ git clone git://git.savannah.gnu.org/libcdio.git
Initialized empty Git repository in /src/external-vcs/libcdio/.git/
remote: Counting objects: 15471, done.
remote: Compressing objects: 100% (3223/3223), done.
....
Receiving objects: 100% (15471/15471), 16.56 MiB | 231 KiB/s, done.
Resolving deltas:  99% (12089/12208)   Resolving deltas: 100% (12208/12208)   Resolving deltas: 100% (12208/12208), done.
cd: 491: can't cd to /src/external-vcs/libcdio/.git/refs/remotes/origin
Warning: Remote HEAD refers to nonexistent ref, unable to checkout.

Removing a branch

We don't really like this, but there's a way to remove remote branches. We don't like it because this allow group members to potentially remove free software from Savannah, willingly or by mistake. This is mitigated by the fact it is very easy to push back changes.

When removing a branch, only its reference is removed, and the commit are still reachable by their identifiers. However, Savannah may prune unreachable commits (git gc), so don't count on this.

To remove a branch:

git push origin :mybranch

For an easier syntax, you can use git-publish-branch -d (the original location is offline but an archived copy may be found at https://web.archive.org/web/20170128205942/http://git-wt-commit.rubyforge.org/).

Non-Fast-Forward commits

'non-fast-forward' commits are commits which result in rewriting the commit history, leading to lost commits (see http://git-scm.com/docs/git-push#_note_about_fast_forwards for a technical explanation).

In Savannah, non-fast-forward commits are disallowed, for the same reason that RemovingProject is disallowed: to prevent removal of published code. Another reason to avoid non-fast-forward commits is to prevent troubles for users who already cloned a public repository - as a simple 'pull' will fail in their local repository.

Under special circumstances, Savannah administrators can temporarily enable non-fast-forward commits in a specific repository. Such cases include:

These are done on a case-by-case basis, and enabled only for a short period (usually 24 hours). Please submit a support request (https://savannah.gnu.org/support/?func=additem&group=administration or email savannah-hackers-public@gnu.org if you need to temporarily enable non-fast-forward commits.

An advanced configuration option where non-fast-forward commits are enabled for all branches except the master branch as been discussed but is not currently implemented (see http://lists.gnu.org/archive/html/savannah-hackers-public/2015-01/msg00011.html).

Links

FAQ

  • How does a group admin update the "description" file for the web interface?

    Please visit the 'Administer' link in the Git submenu, either in the 'Source code' top menu or in 'Development Tools' section of the main page.

  • Similarly, how can a group admin update the "HEAD" file to point to another branch?

    Unusual branching strategies are strongly discouraged. "Standard is better than better." You are encouraged to use typical branching strategies. If you need something custom for your group please file a support request and a Savannah Admin will discuss this with you and take any actions that are needed.