Navigation

Sometimes you will only want to work on local changes to Sage, for
your own private needs. However, typically it is beneficial to
share code and ideas with others; the manner in which the
Sage project does this (as well as fixing
bugs and upgrading components) is in a very collaborative and
public setting on the Sage Trac server
(the Sage bug and enhancement tracker).

One can use gitthe hard way for this,
but this section explains how to use the helper gittrac command, which
simplifies many of the most common actions in collaboration on Sage. Some
of the tutorials we suggest may be helpful
in navigating what they are for.

Most of the commands in the following section will not work unless
you have an account on Trac. If you want to contribute to Sage, it
is a good idea to get an account now (see Obtaining an Account).

Git is a separate project from trac, and the two do not know how to
talk to each other. To simplify the development, we have a special
gittrac subcommand for the git suite. Note that this really is
only to simplify interaction with our trac issue management, you can
perform every development task with just git and a web browser. See
Git the Hard Way instead if you prefer to do everything by
hand:

Sourcing the enable.sh script in there is just a quick and dirty
way to enable it temporarily. For a more permanent installation on
your system later, make sure to put the git-trac command in your
PATH. Assuming that ~/bin is already in your PATH, you can
do this by symlinking:

You need to set up both authentication mechanisms to be able to upload
your changes with “git trac”. For read-only access neither
authentication mechanism is needed. To set up gittrac, first go
to the Sage directory and tell gittrac about your trac account:

where you have to replace USERNAME with your trac user name and
PASSWORD with your trac password. If you don’t have a trac account,
use gittracconfig without any arguments. The single quotes in
'PASSWORD' escape special characters that you might have in your
password. The password is stored in plain-text in .git/config, so
make sure that it is not readable by other users on your system. For
example, by running chmod0600.git/config if your home directory
is not already private.

Instead of a username and password you may also configure authentication via
a generated token by passing --token=<token> instead of --pass:

The username to be entered here is NOT the GitHub username, but rather the trac username which is gh-<GitHub-username>
as given on the top right corner of the trac server.

If both a token and a username/password are configured, the token-based
authentication takes precedence.

If you do not want to store your trac username/password/token on disk you
can temporarily override it with the environment variables
TRAC_USERNAME, TRAC_PASSWORD, and TRAC_TOKEN respectively.
These take precedence over any other configuration.

If there is no SSH key listed then you haven’t uploaded your SSH
public key to the trac server. You should do that now following the
instructions to Linking your Public Key to your Trac Account, if you want to upload
any changes. You may have to add your private key to your authentication agent:

The git@... part of the push url means that write access is
secured with SSH keys, which you must have set up as in
Linking your Public Key to your Trac Account. Read-only access happens through the
fetch url and does not require SSH.

Finally, if you do not want to use the gittrac subcommand at all
then you can set up the remote by hand as described in the section on
The Trac Server.

This will create a new trac ticket titled “Last Twin Prime” with a
remote branchu/user/last_twin_prime attached to it. The remote
branch name is automatically derived from the ticket title; If you
don’t like this then you can use the -b switch to specify it
explicitly. See gittraccreate-h for details. This new branch is
automatically checked out for you with the local branch name
t/12345/last_twin_prime.

Note

Only some trac fields are filled in automatically. See
The Ticket Fields for what trac fields are available and
how we use them.

The gittraccheckout command downloads an existing branch (as
specified in the “Branch:” field on the trac ticket) or creates a new
one if there is none yet. Just like the create command, you can
specify the remote branch name explicitly using the -b switch if
you want.

The “Branch:” field of a trac ticket (see The Ticket Fields) indicates
the git branch containing its code. Our git server implements the following
access restrictions for remote branch names:

You can read/write/create a branch named
u/your_username/whatever_you_like. Everybody else can read.

Everybody can read/write/create a branch named public/whatever_you_like.

Depending on your style of collaboration, you can use one or the
other. The gittrac subcommands defaults to the former.

As a convention, the gittrac subcommand uses local branch
names of the form t/12345/description, where the number is the
trac ticket number. The script uses this number to figure out the
ticket from the local branch name. You can rename the local branches
if you want, but if they don’t contain the ticket number then you will
have to specify the ticket number manually when you are uploading your
changes.

At some point, you may wish to share your changes with the rest of us:
maybe it is ready for review, or maybe you are collaborating with
someone and want to share your changes “up until now”. This is simply
done by:

You can upload any local branch to an existing ticket, whether or not
you created the local branch with gittrac. This works exactly
like in the case where you started with a ticket, except that you have
to specify the ticket number (since there is no way to tell which
ticket you have in mind). That is:

It is common to go through a few iterations of commits before you
upload, and you will probably also have pushed your changes a few
times before your changes are ready for review.

Once you are happy with the changes you uploaded, they must be
reviewed by somebody else before they can be included in the next
version of Sage. To mark your ticket as ready for review, you should
set it to needs_review on the trac server. Also, add yourself as
the (or one of the) author(s) for that ticket by inserting the
following as the first line:

As soon as you are working on a bigger project that spans multiple
tickets you will want to base your work on branches that have not been
merged into Sage yet. This is natural in collaborative development,
and in fact you are very much encouraged to split your work into
logically different parts. Ideally, each part that is useful on its
own and can be reviewed independently should be a different ticket
instead of a huge patch bomb.

For this purpose, you can incorporate branches from other tickets (or
just other local branches) into your current branch. This is called
merging, and all it does is include commits from other branches into
your current branch. In particular, this is done when a new Sage
release is made: the finished tickets are merged with the Sage master
and the result is the next Sage version. Git is smart enough to not
merge commits twice. In particular, it is possible to merge two
branches, one of which had already merged the other branch. The syntax
for merging is easy:

This creates a new “merge” commit, joining your current branch and
other_branch.

Warning

You should avoid merging branches both ways. Once A merged B and B
merged A, there is no way to distinguish commits that were
originally made in A or B. Effectively, merging both ways combines
the branches and makes individual review impossible.

In practice, you should only merge when one of the following holds:

Either two tickets conflict, then you have to merge one into the
other in order to resolve the merge conflict.

Or you definitely need a feature that has been developed as part
of another branch.

A special case of merging is merging in the develop branch. This
brings your local branch up to date with the newest Sage version. The
above warning against unnecessary merges still applies, though. Try to
do all of your development with the Sage version that you originally
started with. The only reason for merging in the develop branch is if
you need a new feature or if your branch conflicts. See
Update Branch to Latest SageMath Version (and Minimizing Recompilation Time) for details.

Merge conflicts happen if there are overlapping edits, and they are an
unavoidable consequence of distributed development. Fortunately,
resolving them is common and easy with git. As a hypothetical example,
consider the following code snippet:

However, not having an internet connection, she cannot immediately
send her changes to the trac server. Meanwhile, Bob changes the
multiplication to an addition since that is the correct recursion
formula:

Eventually, Alice returns to civilization. In her mailbox, she finds a
trac notification email that Bob has uploaded further changes to their
joint project. Hence, she starts out by getting his changes into her
own local branch:

The conflict is shown between the conflict markers <<<<<<< and
>>>>>>>. The first half (up to the ======= marker) is Alice’s
current version, the second half is Bob’s version. The 40-digit hex
number after the second conflict marker is the SHA1 hash of the most
recent common parent of both.

It is now Alice’s job to resolve the conflict by reconciling their
changes, for example by editing the file. Her result is:

If Bob decides to do further work on the ticket then he will have to
pull Alice’s changes. However, this time there is no conflict on his
end: git downloads both Alice’s conflicting commit and her resolution.

The gittrac command gives you two commands that might be handy
(replace 12345 with the actual ticket number) if you do not want
to use the web interface:

gittracprint12345 displays the trac ticket directly in your
terminal.

gittracreview12345 downloads the branch from the ticket and
shows you what is being added, analogous to clicking on the
“Branch:” field.

To review tickets with minimal recompiling, start by building the “develop”
branch, that is, the latest beta. Just checking out an older ticket would most
likely reset the Sage tree to an older version, so you would have to compile
older versions of packages to make it work. Instead, you can create an anonymous
(“detached HEAD”) merge of the ticket and the develop branch using

$ git trac try 12345

This will only touch files that are really modified by the ticket. In particular,
if only Python files are changed by the ticket (which is true for most tickets)
then you just have to run sage-b to rebuild the Sage library. If files other
than Python have been changed, you must run make. When you are finished
reviewing, just check out a named branch, for example

$ git checkout develop

If you want to edit the ticket branch (that is, add additional commits) you cannot
use gittractry. You must Check out an Existing Ticket to get the actual ticket
branch as a starting point.