git rebase --continue: how to suppress the "no changes" check
git
Solution
Interesting question. Here Automatically skip empty commits when using git rebase user Olivier Refalo suggested using a function from G2, simplified git interface for newbies. Basically it boils down to checking whether contents of files in index is different from files the repository after doing `git add`. If it's different do `git rebase --continue`, if it's the same do `git rebase --skip`. You could create script that would do the following:
#!/bin/sh
if git diff-index --quiet HEAD --; then
git rebase --skip
else
git rebase --continue
fi
Alternatively you can add an alias to your .gitconfig:
[alias]
reb = "!if git diff-index --quiet HEAD --; then git rebase --skip; else git rebase --continue; fi"
Problem
Is there a way to configure `git` so that `git rebase --continue` skips the "no changes" test? I don't want `git rebase --continue` to ever fail because it detects no changes. It should automatically delete the commit when this happens. Why? I frequently run into the problem with git where I `git rebase --continue` fails because it sees no changes and requires me to say `git rebase --skip`. I understand why this happens, but it slows down my workflow and makes it more dangerous: if I'm doing a large rebase where the problem recurs multiple times, along with legitimate merge conflicts, I'm more likely to accidentally use a skip command from the history when I meant to reuse a continue command. Example Suppose I have the following history: ``` A -- B -- C -- D -- E -- F <-- topic \ H -- I <-- master ``` and I want to push commits B, C, E, and F to the master branch in `origin`. Suppose that when I cherry pick them, B works fine, C and F have some trivial merge conflict caused by commits H and I, and E has a non-trivial merge conflict that needs to be resolved differently if H and I are in the history than if D is in the history. After resolving those conflicts, suppose my history is: ``` A -- B -- C -- D -- E -- F <-- topic \ H -- I -- B -- C' -- E'' -- F' <-- master ``` Now, I want to rebase my `topic` branch onto `master`. In doing so, B will get automatically dropped, but I'll get merge conflicts for C, E, and F because they were modified when they were cherry-picked. When the rebase pauses at C, resolving the conflicts results in no net change, so `git` will be defensive and complain when I try to run `git rebase --continue`: ``` No changes - did you forget to use 'git add'? ``` The solution is to use `git rebase --skip` instead. At that point, E will conflict; resolving it requires actual changes, so I actually (and successfully) use `git rebase --continue`. Then, F produces another spurious merge conflict. As with C, resolving that conflict results in no net changes, so again I'm told to use skip mode when I try to continue. I'd like to configure `git` so that when I resolve a merge conflict (esp. with `mergetool`) and the resolution results in no net changes, I want `git rebase --continue` to just do the work of `git rebase --skip`, at most prompting me. I'd prefer it always auto-skip if it can't be smart enough to know that I ran the mergetool. The continue option seems to be defending against incorrect `git checkout` commands mid-rebase; I'm familiar enough with git these days to never be in danger of accidentally nuking changes mid-rebase. I have however come close to accidentally doing a skip when my history looks like this: ``` git rebase # start the rebase git mergetool # apply non-trivial fix git rebase --continue # succeeds: non-trivial fix git mergetool # apply non-trivial fix git rebase --continue # succeeds: non-trivial fix git mergetool # apply non-trivial fix git rebase --continue # succeeds: non-trivial fix git mergetool # nuke all changes from the topic branch git rebase --continue # fails: no changes git rebase --skip # this should have been automatic git mergetool # apply non-trivial fix (THIS MUST NOT BE SKIPPED) ... here I have to be careful and not just reflexively hit up-arrow twice then <ENTER>... ```