1. Prepare your system for development with git

1.1. Install git on your system

In the package manager, select the package "git-core" (the package "git" is an
unrelated program; don't choose it). Optionally, select "gitk" or "qgit" (not
on Dapper) to graphically view project history, and "git-gui" to graphically
select files to commit.

If you're using Ubuntu Dapper, git 1.6 packages are available on
the linuxcnc.org package server in the linuxcnc2.3 directory. If you already have
this repository enabled, simply update your package lists, and the new git
packages will be available for installation. (The git 1.1 packages that
shipped with dapper, and the git 1.5 packages in dapper-backports, are both not
recommended for various reasons)

1.2. Configure your identity

Use your real name (not a handle), and use an unobfuscated e-mail address.

2. Create an initial check-out

"clone" is the git command that gets a copy of a project's history. It is roughly like "cvs co", except that the whole project history (not just the current working files) are available after a clone.

2.1. Anonymous checkouts

git clone git://git.linuxcnc.org/git/linuxcnc.git linuxcnc-dev

this will create a new local directory 'linuxcnc-dev' and fetch the full history of
the project. On a system with a 3 megabit connection, this took about 3
minutes and the created directory is about 80 megs.
The repo created by this clone command is a full repo: it has all of the history,
and you can make local commits (for your own use, or for sending to
developers with commit access to the central repo). You can not push
back to the central repo from this repo.

2.2. Registered user checkouts

2.3. About your cloned local repo

Both of the clone commands above create a directory in your working directory
called "linuxcnc-dev", containing a full clone of the linuxcnc.org git repo.
All the commands below assume that you are in the linuxcnc-dev directory unless
noted otherwise.

3. View history

Take a look at the history:

git log -C --stat

(git log has a bunch of options; this set detects renames and copies, and
shows a summary of what files are changed in each commit)

Get a closer look at a particular change by commit:

git log -C -p -1 57c609

(-p shows a patch, -1 restricts to a single change, and 57c609 is the start
of a commit shown by the first 'git log' command)

git often uses "topic" as a placeholder for a branch name, because everything
in a branch should be on one "topic"--a topic might be to add feature X,
refactor subsystem Y, only fix bugs from version Z, and so on.

6.1. If you prefer to use different directories for different branches

The following sequence creates "linuxcnc2.5-dev" alongside "linuxcnc-dev", then uses 'git relink' to save disk space, then switches to the v2_5_branch in the linuxcnc2.5-dev directory:

7.2. Use multiple commits to organize changes

When appropriate, organize your changes into a series of commits where each commit is a logical step towards your ultimate goal. For example, first factor out some complex code into a new
function. Then, in a second commit, fix an underlying bug. Then, in the third commit, add a new feature which is made easier by the refactoring and which would not have worked without fixing that bug.

This is helpful to reviewers, because it is easier to see that the "factor out code into new function" step was right when there aren't other edits mixed in; it's easier to see that the bug is fixed when the change that fixes it is separate from the new feature; and so on.

7.3. Follow the style of the surrounding code

Make an effort to follow the prevailing indentation style of surrounding code. In particular, changes to whitespace make it harder for other developers to track changes over time.
When reformatting code must be done, do it as a commit separate from any semantic changes.

7.4. Prepare commits to share with fellow developers

With git, it's possible to record every edit and false start as a separate
commit. This is very convenient as a way to create checkpoints during
development, but often you don't want to share these false starts with others.

Git provides two main ways to do this, both of which can be done freely before
you share the change:

'git commit --amend' lets you make additional changes a part of the last thing you committed, optionally modifying the commit message as well. Use this if you realized right away that you left something out of the commit, or if you typo'd the commit.

'git rebase --interactive origin' lets you go back through each change made since 'origin', possibly editing it or combining ('squashing') it with another change. In the most extreme case, you can 'squash' it into a single commit, if there's no value to other developers in seeing the individual steps.

7.5. Making sure every commit builds

If your change consists of several patches, 'git rebase -i' may be used to reorder these patches into a sequence of commits which more clearly lays out the steps of your work. A potential consequence of reordering patches is that one might get dependencies wrong - for instance, introducing a use of a variable, and the declaration of that variable only follows in a later patch.

While the branch HEAD will build, not every commit might build in such a case, and that breaks git-bisect (find by binary search the change that introduced a bug) - something somebody else might use later on to find the commit which introduced a bug. So beyond making sure your branch builds, it is important to assure every single commit builds as well.

Subscribe to the emc-developers mailing list, and send the patch to the list as an attachment. However, there is a 24kb limit on messages to this mailing list.

On the #linuxcnc-devel IRC channel, post a link to your patch (on a site like http://pastebin.ca or on a private server) and ask if a developer will look at it. When using a 'pastebin'-type service, choose the option that retains the submission indefinitely.

By posting your patch in a public forum rather than in private to a single developer, you create more opportunities for review and comment.

These are some of the questions developers are likely to have about your patch:

What problem does it solve, or what feature does it add?

Specific questions about the workings of individual parts of the patch

It is not uncommon for a patch to go through several revisions before it is accepted.

7.7. Push changes to the central repository

If you've been approved to directly push your changes to the central
repository, then after some initial setup of ssh keys it's a fairly simple
process:

git pull
# resolve any conflicts, but generally there won't be any
git push

If another developer pushed between your pull and your push, you will have to
pull and then push again. This isn't expected to happen very frequently, but
it will happen more frequently than with cvs since it's required when any file
changed, not just when a specific file being committed changed.
It is also best to use "git pull --rebase" in this case, this will cause the
changes from the central repository to be positioned before your own changes
(thus skipping a merge).

With git we will want to reevaluate how readily little-tested changes are
pushed to 'master', since git provides so many more ways for developers to
exchange patches and collaborate on new features.

7.8. Push changes to your own public repository

You can host a public repository to which you "push" and from which others can
"pull". If you don't have a server of your own to do this, services like
[1] and [2] are free for open source
projects. After you push to your own public repository, other developers can
browse your changes or "pull" them.

8. Policy

Just because a thing can be done with git doesn't mean it should be done.

8.1. Renaming files

Please use the ability to rename files very cautiously. Like running indent
on single files, renames still make it more difficult to follow changes over
time. At a minimum, you should seek consensus on irc or the mailing list that
the rename is an improvement.

8.2. Prefer "rebase"

Use "git pull --rebase" instead of bare "git pull" in order to keep a nice linear history. When you "--rebase", you always retain your work as revisions that are ahead of origin/master, so you can do things like git format-patch them to share with others without pushing to the central repository.

9. Tips and tricks

9.1. Use a global ignore file for editor backups

Different developers' editors use different backup file names. Rather than put every possible editor backup file name in every project .gitignore, use a personal gitignore file to ignore your own editor backup files: