Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git rebase --continue: how to suppress the "no changes" check

Tags:

git

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>...
like image 943
Mr Fooz Avatar asked Oct 01 '22 16:10

Mr Fooz


1 Answers

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"
like image 108
Arkadiusz Drabczyk Avatar answered Oct 03 '22 05:10

Arkadiusz Drabczyk