git - rmu75/linuxcnc-wiki GitHub Wiki
This page has moved to: http://linuxcnc.org/docs/2.5/html/code/Contributing-to-LinuxCNC.html
On June 20, 2009, the LinuxCNC project began using [git] as its revision control system, replacing CVS. [Read the announcement]
This page collects instructions and guidelines for using git with LinuxCNC. There is also a wealth of documentation for git, including
- [The git tutorial] (This has been "404 Not Found" lately, but will probably come back eventually.)
- [The git tutorial (temporary)] (A link to Schacon's mirror of "gittutorial" until kernel.org gets back to normal. OK to delete this line later.)
- [Everyday git]
- [Git for the lazy] and full manpages for every git command (man git-clone or git --help clone)
The below tips can feel very daunting; don't panic. Your day-to-day life with git is going to be very simple: git pull git commit -a git format-patch OR git push
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)
git config --global user.name "Your full name"
git config --global user.email "[email protected]"
Use your real name (not a handle), and use an unobfuscated e-mail address.
"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.
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.
If you are a registered developer with "push" access, use git clone ssh://[email protected]/git/linuxcnc.git linuxcnc-dev This creates a repo that can push back to the central 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.
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)
Get a list of commits to a particular file since v2.1.7 branch: git log --oneline v2.1.7..origin/v2_3_branch -- src/hal/components/stepgen.c
View history graphically, if you installed the necessary program: gitk --all qgit --all
You can also [view the history online in gitweb], but viewing the history locally is often more powerful.
Edit some files and then commit the changes locally: git commit -s -a -m"my well-intentioned changes"
Use 'git add' to select specific files to commit, or 'git add --interactive' to specify specific edits in specific files to commit. 'git add' also functions like 'cvs add' for new files: git add README git commit -s -m"my well-intentioned changes"
Use a GUI to select individual changes to commit, and to compose the commit message: git gui qgit
In git, "commit" is a purely local operation. See "Share your changes with others" below.
Keep commit messages around 72 columns wide (so that in a default-size terminal window, they don't wrap when shown by 'git log')
Use the first line as a summary of the intent of the change (almost like the subject line of an e-mail). Follow it with a blank line, then a longer message explaining the change. Example: Get rid of RTAPI_SUCCESS, use 0 instead
The test "retval < 0" should feel familiar; it's the same kind of test you use
in userspace (returns -1 for error) and in kernel space (returns -ERRNO for
error)
To get changes that have been committed to the location you originally cloned from: git pull
Pull changes made by another developer in his public repository but not yet committed to the central repository: git pull git://git.unpythonic.net/linuxcnc-ignores.git master (this pulls two commits that change old .cvsignore files to new .gitignore files and add some missing items to .gitignore)
'git remote' can be used to manage short names for repositories that you frequently pull from.
Apply a patch from another developer, preserving the other developer's identity as the patch author: git am --signoff patch.mbox
To list just the branches in your local repository:
git branch
To list all the branches in the remote repository:
git branch -r
To check out a branch, for example, the 2.5 branch:
git checkout -b v2.5_branch origin/v2.5_branch
To work on the 2.5 branch instead of 'master' ('master' is the git equivalent of cvs 'TRUNK'): git branch --track v2.5_branch origin/v2.5_branch git checkout v2.5_branch After you branch, you can switch freely between master and branch: git checkout master git checkout v2.5_branch
You can create your own branch based off another branch: git branch my-topic master 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.
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: cp -r linuxcnc-dev/ linuxcnc2.5-dev git relink linuxcnc2.5-dev/ linuxcnc-dev/ cd linuxcnc2.5-dev git branch v2_5_branch origin/v2_5_branch git checkout v2_5_branch
For new features, use the git 'origin/master' branch as the starting point.
For v2.5_branch bugfixes, use the merge-base of master and v2.5_branch. You can make a bugfix and merge it into both branches like so:
git checkout $(git merge-base origin/v2.5_branch origin/master)
git checkout -b descriptive-bugfix-branch-name
edit/compile/test/commit
git checkout master
git merge descriptive-bugfix-branch-name
compile/test
git checkout v2.5_branch
git merge descriptive-bugfix-branch-name
compile/test
Check with cradek before pushing changes to v2.5_branch.
If your bugfix is approved for v2.5_branch, then it will also be fixed on master when changes in the branch are merged up.
For v2.4_branch bugfixes, use the merge-base of master and v2.4_branch. You can make a bugfix and merge it into both branches like so:
git checkout $(git merge-base origin/v2.4_branch origin/master)
git checkout -b descriptive-bugfix-branch-name
edit/compile/test/commit
git checkout master
git merge descriptive-bugfix-branch-name
compile/test
git checkout v2.4_branch
git merge descriptive-bugfix-branch-name
compile/test
Check with jepler before pushing changes to v2.4_branch.
If your bugfix is approved for v2.4_branch, then it will also be fixed on master when changes in the branch are merged up.
For more information about why to structure bugfixes like this, see [gitworkflows: Merging Upwards].
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.
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.
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.
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.
There's an automatic way to check a branch for each commit being buildable - see http://dustin.github.com/2010/03/28/git-test-sequence.html , and the code at https://github.com/dustin/bindir/blob/master/git-test-sequence. Use as follows (in this case testing every commit from origin/master to HEAD, including running regression tests):
$ cd linuxcnc-dev
$ git-test-sequence origin/master.. '(cd src;make;runtests)'
This will either report 'All's well' or 'Broke on <commit>'
When you think your changes are ready to be used by others, you can share it in the form of a patch. Make a series of patches for each commit in your local branch but not in 'origin': git format-patch -M origin This creates a number of files with names like 0001-my-well-intentioned-change.patch These patch files are suitable for putting on a webserver or for sending as e-mail with your favorite mail client or git-send-email (some configuration required).
To submit a patch, there are several different options:
- Submit it as an item on the sourceforge tracker: http://sourceforge.net/tracker/?group_id=6744 -- submit bugfixes in the "bugs" section. submit improvements in the "feature requests" section.
- 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.
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.
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.
Just because a thing can be done with git doesn't mean it should be done.
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.
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.
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:
git config --global core.excludesfile /.gitignore
echo '*' >> /.gitignore
Now, the exclusion pattern '*' will be applied in every directory of every git project you use.
I made a little script that pulls and then loads the GUI. Speeds the process up for me. BJT
#!/bin/bash
clear
cd linuxcnc-dev
git pull
git gui
echo Git-R-Done!
If you get errors trying to copy your linuxcnc-dev directory to a usb stick then tar it up first. From the directory above linuxcnc-dev tar cvf linuxcnc-dev.tar linuxcnc-dev then copy linuxcnc-dev.tar to the stick then tar xvf /path/to/linuxcnc-dev.tar on the other system If your usb stick is memory challenged you can compress the the files by adding a z. Like cvzf and xvzf.
To pull, you must have no uncommitted changes in your working tree. If your local work is done, just commit it and then pull.
If you have work in progress that isn't ready to commit, "stash" it: git stash save git pull --rebase git stash apply