23 Oct 2013, 23:19

Git tip: binary diffing

When dealing with binary files on Git repositories, we often would like to be able to diff and see changes on such files. However, git diff is not very helpful when working with non-textual files.

Fortunately, it's relatively simple to help git show us meaningful diffs for these files. We only need to add some lines to our configuration file and have the right tools installed.

For basic diffing with hexdump, we can add the following to ~/.gitconfig

[diff "hex"]
	textconv = hexdump -C

Then, on .gitattributes or $REPO/.git/info/attributes, we can use something like

*.so		diff=hex
*/*/bin/*	diff=hex
*/*/sbin/*	diff=hex

This will allow us to get an output similar to the following when using git diff:

diff --git a/blah.so b/blah.so
index 8891af2..5c2e1f5 100644
--- a/blah.so
+++ b/blah.so
@@ -339,7 +339,7 @@
 00001520  4d 61 73 6b 00 5f 5f 61  65 61 62 69 5f 75 6e 77  |Mask.__aeabi_unw|
 00001530  69 6e 64 5f 63 70 70 5f  70 72 30 00 67 73 6c 5f  |ind_cpp_pr0.gsl_|
 00001540  6c 69 6e 6b 65 64 6c 69  73 74 5f 61 6c 6c 6f 63  |linkedlist_alloc|
-00001550  6e 6f 64 65 00 6f 73 5f  6d 61 6c 6c 6f 63 00 67  |node.os_malloc.g|
+00001550  6e 6f 64 65 00 6f 73 5f  63 61 6c 6c 6f 63 00 67  |node.os_calloc.g|
 00001560  73 6c 5f 6c 69 6e 6b 65  64 6c 69 73 74 5f 67 65  |sl_linkedlist_ge|
 00001570  74 6e 6f 64 65 62 79 69  64 00 67 73 6c 5f 6c 69  |tnodebyid.gsl_li|
 00001580  6e 6b 65 64 6c 69 73 74  5f 66 72 65 65 6e 6f 64  |nkedlist_freenod|

You can define as many conversion rules as you wish, and then apply them to specific files to get meaningful diffs. This way, you can diff ODF or MS Word documents, image metadata and even Eagle layout files. The posibilities are endless.

23 Sep 2013, 09:36

Git tip: patch version numbering

If you are collaborating with a project that uses email as a patch exchange method, you will probably need to send many versions of your patches to public mailing lists. To aid in distinguishing the new from the old, we use version numbers on the email subjects; for example

[PATCH v2 0/9] wilink: add device tree support

indicates that these 9 patches are part of the second iteration of the patch series.

Git 1.8.2 added a new option, --reroll-count N, that lets us introduce this number automatically when using format-patch and send-email. This is mostly equivalent to passing --subject="PATCH vN" on older Git versions, except that --reroll-count will also alter the patch filenames.

So, for example

$ git format-patch -2 --reroll-count 3

will generate the following filename

v3-0001-clk-composite-.determine_rate-support.patch

and the subject will be

[PATCH v3 1/2] clk: composite: .determine_rate support

31 May 2013, 10:01

Git tip: build-test a branch

As a kernel contributor, I often like to build test my series of patches to make sure they are bisectable - that is, to make sure the code still builds (and hopefully runs) after each one of my changes. However, I did not find any easy and automatic way to do this, so I ended up writing a very simple implementation of it in sh, which I will show you here.

First, you will need to create a shell script and put it somewhere on your $PATH; I used ~/bin/git-build-test. Make sure you chmod +x it as well so we can then run it.

#!/bin/sh

# git reference, eg v3.10-rc2..
REF=$1
# list of hashes in that reference
HASHES=$(git rev-list $REF)
# current branch
BRANCH=$(git symbolic-ref HEAD | sed 's#refs/heads/##')
# build command, default to 'make'
BUILD=$(echo $@ | sed "s#$REF##")
[ -z "$BUILD" ] && BUILD="make -j16"

for H in $HASHES; do
    git checkout $H
    $BUILD || exit
done

echo "Success!"
git checkout $BRANCH

Then, we need to add a git alias to make it easily callable. On ~/.gitconfig, add

[alias]
    buildtest = !sh -c 'git-build-test $*' -

Then you can call it as git buildtest v3.10-rc2.. to test building every single commit from v3.10-rc2 to HEAD using make. You can also use more complex incantations like git buildtest v3.10-rc2.. make dtbs for example, to just test device tree building.

25 Mar 2013, 22:59

Git tip: rebase --autosquash

I found the --autosquash argument of git rebase --interactive to be very useful for my workflow. I usually keep a development branch, where I commit early and often. This means I'm usually left with a commit containing the actual feature, and then some smaller commits fixing bugs and other issues, that I later squash together using git rebase --interactive

Starting on 1.7.4, Git has two flags on commit that can help people who work this way: --fixup and --squash. They let you mark a commit as fixing up another one, and will automatically sort the commits on rebase --interactive as well as change the action to fixup or squash, respectively.

Here is an example case of how you would use --fixup

$ # We implement some awesome feature here
$ nano drivers/clk/sunxi/clk-sunxi.c
$ git add drivers/clk/sunxi/clk-sunxi.c
$ git commit -sm "clk: sunxi: implement some big feature"
[sunxi-clk 0867eea] clk: sunxi: implement some big feature
 1 file changed, 1 insertion(+)
$ # Then we enable it on the device tree
$ nano arch/arm/boot/dts/sun4i-a10-cubieboard.dtb
$ git add arch/arm/boot/dts/sun4i-a10-cubieboard.dts
$ git commit -sm "ARM: sunxi: enable the big feature"
[sunxi-clk b7f2640] ARM: sunxi: enable the big feature
 1 file changed, 1 insertion(+)
$ # And then we find a bug we need to fix!
$ nano drivers/clk/sunxi/clk-sunxi.c
$ git add drivers/clk/sunxi/clk-sunxi.c
$ git commit -s --fixup HEAD^
[sunxi-clk e9abc64] fixup! clk: sunxi: implement some big feature
 1 file changed, 1 insertion(+)
$ # Eventually we rebase
$ git rebase --interactive --autosquash torvalds/master

To make them even easier to use, you can add the following to your ~/.gitconfig:

[alias]
     fixup = !sh -c 'git commit --fixup=$1' -
     squash = !sh -c 'git commit --squash=$1' -
     ri = rebase --interactive --autosquash

Then you will be able to use git fixup, git squash and git ri, which are considerably easier to type and remember

Hat tip to Technosorcery for being the site on where I discovered this great feature