Git usage

This page covers useful tips and tricks about using git for (embedded) development. It will not be the 10th git tutorial. It covers practical usage reports and tips and tricks not listed in official git documentation.

=Resources=


 * Git home page and download
 * Git wikipedia
 * Git online manpages
 * Git cheat sheet

=send-email=

git send-email is an useful tool to send patches (created with or without git) to mailing lists.

Note: Prior git version < 1.6 this command was git-send-email, i.e. with hyphen between git and send.

On Ubuntu (8.10) install packages

sudo apt-get install git git-email

and set up your GIT variables (probably in ~/.bashrc)

export GIT_COMMITTER_EMAIL=yourEmail@somewhere.com export GIT_COMMITTER_NAME='YourName' export GIT_AUTHOR_EMAIL=yourEmail@somewhere.com export GIT_AUTHOR_NAME='YourName'

format patch
After you did your commits with commit message in incremental stages generate email-able patch files: git-format-patch -s -n -o origin...


 * -s will generate the signed of-by
 * -n will generate numbered patches (if you have just a single patch, you can ignore it) - but if you have multiple ones, this is a good idea to use to generate subject auto numbered 1/2, 2/2 etc..
 * -o is where the output patch files will be stored -> each commit is a separate file.

Sending with Gmail
Then you can mail the patches. This (simple, no mail threads) example shows to how to use GMail for with git send-email:

git send-email \ --from My Name and mail address \ --to mail address \ --cc if I want a CC \ --smtp-server smtp.gmail.com \ --smtp-user MyMailID@gmail.com \ --smtp-pass add your password --smtp-ssl --subject add subject PatchFile

You can add most of these parameters to your ~/.gitconfig file to make them permanent (see man git-send-email for a full list of options):

[sendemail] smtpserver = smtp.gmail.com smtpuser = MyMailID@gmail.com smtppass = add your password smtpssl = true

Threaded mails
For threaded mails (e.g. if you want to send more than one patch), instead of (one) PatchFile you can pass a directory PatchDirectory with several patches to git send-email. In this directory you have your x patches you want to send (and only the patches!). At best, you order the patches by numbering them (e.g. 0001-patch1, 0002-patch2 etc.). If you pass this directory to git send-email then, all the files in this directory will be sent.

The question now is where to get the mail subjects from. As we want individual subjects for each patch, but all patches are sent automatically, we can't specify the subject with --subject any more. For this, you can have the subject stored in the header of your patch (file). E.g. with

Subject: [PATCH 1/3]: Testmail1 Test 1 Signed-off-by: A B a@b.com ...

git send-email will pick the subject from the patch file. The resulting mail will contain

[PATCH 1/3]: Testmail1

as subject and the body will start with

Test 1 ...

Next question are threaded mails. Some mailing lists like to have several patches to be sent threaded, i.e. all patches have to be sent as 'reply to' to the first one. With git send-email there are two tastes of threading possible:

--chain-reply-to:

Each (patch) mail will be a reply to the previous one. I.e.:

x |-x |-x |-x |-...

--no-chain-reply-to:

Each (patch) mail will be a reply to the first mail. I.e.:

x |-x |-x |-x |-...

Note: Make really sure that the

Subject: ...

is at the first line of all your patches if you use directory mode for a patch series. If there is one empty line before it, git send-email might be confused and take the subject from e.g. previous patch...

=bisect=

Here are some messages from Linus about using git bisect:

Message 1
Date: 10/06/06

Subject: Re: Simple script that locks up my box with recent kernels

Question: The first kernel where I know for sure it caused lockups is 2.6.18-git15. I've also tested 2.6.18-git16, 2.6.18-git21 and 2.6.19-rc1-git2 and those 3 also lock up solid.

Answer: Can I bother you to just bisect it?

Even if you decide that it's too painful to bisect to the very end, "git bisect" will give great results after just as few reboots as four or five, and hopefully narrow down the thing a _lot_.

So, for example, while my git tree doesn't contain the stable release numbers, you can trivially just get my tree, and then point "git fetch" at the stable git tree and get v2.6.17.13 that way.

Then you can do just

git bisect start git bisect good v2.6.17.13 git bisect bad $(cat patch-2.6.18-git15.id)

and off you go - it will pick a half-way point for you to test, and then if that one was good, you just say "git bisect good", and it will pick the next one.

(that "patch-2.6.18-git15.id" thing is from kernel.org - it's how you can get the exact git state of any particular snapshot, even if it's not tagged in any real tree - that particular one seems to have SHA1 ID 1bdfd554be94def718323659173517c5d4a69d25..)

"git bisect" really does kick ass. Don't worry if it says "10374 commits to test after this" - because it does a binary search, it basically cuts the commits to test in half each time, and so if you do just five bisections, you'll have cut down the 10,000 commits to just a few hundred. At that point, maybe we even have a clue, or we might ask you to test a few more times to narrow things down even more.

Linus

Message 2
Date: 10/07/06

On Sat, 7 Oct 2006, Jesper Juhl wrote: > > Can I bother you to just bisect it? > Sure, but it will take a little while since building + booting + > starting the test + waiting for the lockup takes a fair bit of time > for each kernel

Sure. That said, we've tried to narrow down things that took hours or days (under real loads, not some nice test-script) to reproduce, and while it doesn't always work, the real problem tends to be if the problem case isn't really reproducible. It sounds like yours is pretty clear-cut, and that will make things much easier.

> and also due to the fact that my git skills are pretty > limited, but I'll figure it out (need to improve those git skills > anyway) :-)

"git bisect" in particular isn't that hard to use, and it will really do a lot of heavy lifting for you.

Although since it will just select a random commit (well, it's not "random": it's strictly as half-way as it can possibly be, but it's automated without any regard for anything else), you can sometimes hit a situation where git will ask you to test a kernel that simply doesn't work at all, and you can't even test whether it reproduces your particular bug or not.

For example, "git bisect" might pick a kernel that just doesn't compile, because of some stupid bug that was fixed almost immediately afterwards. In those cases, the total automation of "git bisect" ends up being something that has to be helped along by hand, and then it definitely helps to know more about how git works.

Anyway, the quick tutorial about "git bisect" is that once you've given it the required first "good" and "bad" points, it will create a new branch in the repository (called "bisect", in case you care), and after that point it will do a search in the commit DAG (aka "history tree" - it's not a tree, it's a DAG, since merges will join branches together) for the next commit that will neatly "split" the DAG into two equal pieces. It will keep splitting the commit history until you get fed up, or until it has pinpointed the single commit that caused the problem.

The nicest tool to use during bisection is to just do a

git bisect visualize

that simply starts up "gitk" (the default git history visualizer) to show that the current state of bisection is. Now, if there are thousands and thousands of commits, you'll have a really hard time getting a visual clue about what is going on, but especially once you get to a smaller set of commits, it's very useful indeed.

And it's _especially_ useful if you hit one of the problem spots where you can't test the resulting tree for some unrelated reason. When that happens, you should _not_ mark the problematic commit as being "bad", because you really don't know - the "badness" of that commit is probably not related to the "badness" that you're actually searching for.

Instead, you should say "ok, I refuse to test this commit at all, because it's got other problems, and I will select another commit instead". The bisection algorithm doesn't care which commit you pick, as long as it's within the set of "unknown" commits that you'll see with the visualization tool.

Of course, for efficiency reasons, the _closer_ you get to the half-way mark, the better. So it's useful to try to pick a commit that is close to the one that "git bisect" originally chose for you, but that's not a correctness issue, that's just an issue of "if we have a thousand potential commits, we're better off bisecting it 400/600 rather than 1/999, even if the exact half-way point isn't testable".

So if you need to decide to pick another point than the one "git bisect" chose for you automatically, just select that commit in the visualizer (which will cut the SHA1 name of it), and then do

git reset --hard <paste-sha1-here"

to reset the "bisect" branch to that point instead. And then compile and test that kernel instead (and then if that's good or bad, you can do the "git bisect good" or "git bisect bad" thing to mark it so, and git will continue to bisect the set of commits).

It can be a bit boring, but damn, it's effective. I've used "git bisect" several times when I've been too lazy to try to really think about what is going on - I'll happily brute-force bug-finding even if it might take a little longer, if it's guaranteed to find it (and if the bug is reproducible, git bisect definitely guarantees to find what made it appear, even if that may not necessarily be the deeper _cause_ of the bug)

Linus