Monday, October 12, 2015

git rebase eats my commits when the rebase fail... (no, not really)

I'm playing with git --rebase for the first time. The first patch of the series was fixing coding style, but it was also introducing some coding style errors related to continuation lines. Instead of adding two additional tabs, I was aligning the continuation lines with the previous opening parenthesis. Oops. So I needed to edit the first commit of the series to be able to resent all of them. git makes it quite convenient, right?

     $ git --rebase --interactive <commit hash>^

Then git will show a text file for you to edit and choose what to do with each commits. Everything fine until now. My workflow is

     $ vi path/to/file.c
     $ make path/to/file.o
     $ git add path/to/file.c
     $ git commit --amend
     $ git rebase --continue

Well this is awesome, and I had fun rebasing all my 11 commits and it was looking very good. Even when the automatic rebase doesn't work it is very intuitive and great to work with. This is one sample output when the automatic rebase fails:

     $ git rebase --continue
     [detached HEAD a22bcda] usb/host/fotg210: Remove useless else statement
      1 file changed, 2 insertions(+), 3 deletions(-)
     error: could not apply d13e859... usb/host/fotg210: Add function: output_buf_tds_dir()

     When you have resolved this problem, run "git rebase --continue".
     If you prefer to skip this patch, run "git rebase --skip" instead.
     To check out the original branch and stop rebasing, run "git rebase --abort".
     Could not apply d13e8595018d5eb2f2eea19df7b20916f3862004... usb/host/fotg210: Add function: output_buf_tds_dir()

So I just repeated the same workflow as before:

     $ vi path/to/file.c
     $ make path/to/file.o
     $ git add path/to/file.c
     $ git commit --amend
     $ git rebase --continue

And... AHHHH! Where is my commit? Why did git merged two commits? I have to start again, why didn't I create a new branch before playing with rebase? And then, like Bart being tempted by trying again until it works, I tried again just creating some branches to avoid having to do all the work again. How boring is to adjust where the first character should be in 100 lines... I even made a script that detect continuation lines and print it for me. But when the rebase failed, and I used my proven workflow, the result was exactly the same: AHHHHH!

The issue is that when the rebase fails, you are not supposed to commit, unless you want to merge two commits! But, but, where is that information available? git tells you that. Try git status after git add and you see. So the workflow when rebase fails should be:

     $ vi path/to/file.c
     $ make path/to/file.o
     $ git add path/to/file.c
     $ git status # Read what git has to tell you
     $ git rebase --continue

And no more mysterious merges!