[coreboot] [ANN] New code repository and development workflow

Peter Stuge peter at stuge.se
Mon Jun 6 05:54:12 CEST 2011


Patrick Georgi wrote:
> I'm glad to be able to announce that we moved the repository
> infrastructure to git and gerrit, with jenkins as supporting
> facility.

This is exciting!


> the coreboot development workflow changes considerably:
> 
> 1. New SCM
> You will need git, so install it from your usual software
> distribution channels.

For Windows users I would recommend installing the command line tools
in the msysGit package. During installation there is a somewhat
important question about how Git should handle line endings on
Windows.

Git can perform automatic translation between line ending formats, so
that code in the repository will never use anything but LF line
endings, while developers working on Windows will still have every
single file in their working tree use CRLF line endings. This
translation is enabled by the core.autocrlf setting, which is what
the installer will asks for the default value of.

There are many git configuration options. Options can be set either
per user (AKA global) or per repository. Options in a repo override
the global ones. Options are stored in plain text in ~/.gitconfig or
<repodir>/.git/config

You can edit the text files or use the git config command:

git config --global user.name "Peter Stuge"
git config --global user.email peter at stuge.se

The above two lines configure git so that all commits I make will
have my name and email. It's important that you do the same
configuration before you create commits, or they will look really
bad and ultimately end up being rejected.

If you run git config inside a repo dir you can leave out --global to
change settings locally for that repo only.

If you prefer to use a GUI for Git on Windows then I recommend
Git Extensions, which also includes a Visual Studio plugin, so that
you can interact with Git a little more easily directly from the IDE
if you prefer to use Visual Studio.

But allow me to emphasize that it is highly valuable to learn how to
work with Git on the command line. It may feel a little raw, but it
is incredibly efficient, and it very much exposes the concepts of Git
in a clear way, which I must say I have not really seen in any GUI so
far.


> For patch submission a gerrit account is necessary. You can register it
> on http://review.coreboot.org.

Currently registration requires OpenID and might be limited to Google
and Yahoo accounts, but I think this will change tomorrow. (I have
neither, so I can't register. :) We will certainly work something
out.


> 2. New patch submission process
> Develop "as usual" in git, and commit freely.
> When you're ready to submit patches, push them with
>   git push origin HEAD:refs/for/master

HEAD deserves a little discussion.

HEAD is a "meta name" which always refers to the last commit on
whatever branch is currently checked out.

Subversion has revisions, Git has commits. Git commits are identified
by a SHA-1 checksum calculated from the exact contents of the entire
repository. Commit ids can be abbreviated as long as they are unique.


In SVN, revisions are always linear.

In Git, commits can form a directed acyclic graph.
( http://en.wikipedia.org/wiki/Directed_acyclic_graph )

The graph theory is not important, just keep in mind that with Git
also the "parent commit" can be significant. So far, all coreboot
work has been quite linear, and I think it will continue to be mostly
linear, even if Git can handle more complicated situations.

With Git, the branch concept is very important. The actual commits
themselves are really low-level building blocks of a Git repository,
but it is only common to deal with commit ids while doing e.g.
interactive rebase or cherry-picking, which are slightly advanced
tasks compared to development using SVN. (But they are really lovely
features of Git! More later.)

A Git branch is nothing but a nickname pointing to one particular
commit in the repository commit graph. The branch thus also implies a
particular commit history; namely all commits that came before the
one that is the so-called branch HEAD.

Git is distributed, so *everything* is local by default in Git repos.
This goes for commits, branches, tags and everything else. But
everything can also be transferred to other repos easily. git push is
one way, email is another popular way to at least transfer commits
between repositories. Git can send email directly, but thanks to
Gerrit it will not likely be used for coreboot. By using git push to
transfer stuff over to Gerrit, emails will get sent out without
further action from the developer.

So, HEAD in the git push command above refers to the last commit on
the checked out branch.

The checked out branch was branched off the master branch at some
point in time, and maybe there are new commits in master since then.

Unless there is an actual conflict that's no problem. If there is a
conflict, you will eventually have to resolve it. Git may be able to
help, but can not always succeed without help, just like svn.

Instead of HEAD you could thus also type the current branch name.

All commits you have done since the branch was created will be
submitted to Gerrit, for proposed inclusion in the main coreboot
repository master branch.

How and when to create branches is very much a personal thing. I find
that I am a little too lazy to create branches as often as would
actually be practical, so I sometimes have to do a bit of surgery to
move commits around to fix that. :) It is much easier to deal with
too many branches, than it is to deal with too few branches.

Note that there is absolutely no requirement to create branches, but
it can be really really helpful, so it is a good habit to aquire
quickly if you are only just starting to use Git now.

Branches in Git are first class citizens, they are basically nothing
more than a name so they are very fast to deal with.

When you clone the coreboot repository, you will get a local Git
repository, where you can work completely freely. There are no
limitations to what you can do in the local Git repository, so please
feel free to work with it any way you like. You can also have
multiple repository clones, just like with svn, personally I find
this useful sometimes.

After cloning, your local repo only has one branch, called master.

I try to immediately create a branch named according to the
particular task or feature to work on next. This is so that the
master branch always has only commits that come from the main
coreboot repository. ("upstream") Again, I fail at this sometimes and
end up doing work on the master branch. I guess this is mostly a
matter of choice, how you want to work.

If you want to create a branch, you can do it two ways. The first is:

git branch newcoolfeature

This will create a branch called "newcoolfeature" which points to
HEAD. You will stay "on" the current branch. If you make a commit on
the current branch (as opposed to on the just-created branch) then
"newcoolfeature" does not change and still points to the same commit
as before; ie. the second last commit on the current branch.

The other way is:

git checkout -b newcoolfeature [<start_point>]

This does not only create a branch called "newcoolfeature" but it
also does a checkout of that branch, so that you will be "on" the
branch. If you create a commit after this, then newcoolfeature HEAD
will change, and the previous branch will stay unchanged. Sort-of the
opposite of what happened above - because even though a new branch
was created, "git branch" does not change what the current branch is.


Branches or not, you really only require very few commands after
having made a source code change:

git add changedfile.c
git commit

Git is more featureful than SVN, so creating a commit is split into
two steps. git add will let Git know what you want to include in the
commit. You can run git add many times before running git commit. You
can even undo. No commit will be created until you run git commit.
git add adds the changes you have made in the named files into the
"index" AKA "staging area" of the repository. This is a halfway house
before the changes are actually committed. It is possible to add only
some parts of a changed file, using "interactive add" which is
entered by the git add -i command.

Please see git add --help for more information on interactive add.

There exists a shortcut, in case you really truly want to create one
commit with every change that you have made in the source tree:

git commit -a

But I recommend to exercise caution with this command. Always using
git add is another good habit, because it makes you think a little
more about the changes that are about to be committed, which helps
create nicely formatted commits, which helps working with commits
going forward, which saves time.


Before you create a commit, please review the changes you have made,
just like with svn.

The command I like to use for review is git diff. In it's simplest
form, git diff will show all changes in your work tree which have not
yet been added to the index.

Use git diff --cached to instead show *only* the changes that *are*
added to the index; this is what will make up the commit if you would
run git commit.

git diff --cached is the perfect way to review changes before
creating a commit. git status is also helpful to get an overview of
the files that are involved. git status, git diff (with and
without --cached and/or other options) and git branch (without
parameters) are always safe, read-only, operations that can be run at
any point in time, regardless of the repository state, and will
provide helpful information about the repo state.


> If you push a number of commits at once, they're properly linked as
> "dependencies", so people (and tools like gerrit and jenkins) are
> aware about prerequisites.

Pushing a number of commits at once happens when the HEAD that you
push has more than one commit that is not available in the branch
that your push is targeted at. (Normally the master branch of the
main coreboot repo.) So if you have created two commits before you
push, then they will be assumed to depend on each other. If the
commits are not really related then please keep in mind to push one
at a time. Using one branch per related logical change is a good tool
to accomplish this.


> Praise?

Indeed! Thank you so much for the work getting this infrastructure up
and running. I am personally excited to see coreboot start using Git
and I think it will actually help developers a lot once everyone has
gotten up to speed. For example Marshall and I worked on the last
patchset for the E350M1 board exclusively using Git, and it would
have taken us a lot more time and would have been a lot more tedious
work to accomplish what we did without Git.

I think the same is true for much future development, in particular
since we tend to see (and very much prefer!) more patchsets, as
opposed to individual patches, and this fits Git very well.

Git is new for several coreboot developers, while some of us have
been using it for a while already. If you should run into trouble
please get in touch, the very best is to check on IRC, because if
there is a problem there will likely be a couple of commands back
and forth before the problem has been resolved, and email can be
somewhat slow and impractical.


Kind regards

//Peter




More information about the coreboot mailing list