Is there a way to automatically discard amended commits in a git rebase?

Viewed 46

The following situation is something that happens every once in a while when I am working with Git. I start with a linear history, with two branches. The master currently points at C. Branch A is a branch that I am asking my colleagues to merge into master and branch B has unfinished work that I haven't made public yet.

 C
  \ 
   A - B

During the code review, my colleague notices that there is a typo in the last commit in branch A. Instead of creating a new commit just to fix the typo, I amend the offending commit and we merge that into master. Master now points to A', which is the commit that corrected the typo.

C - A'
 \
   A - B

The next step is to rebase the unfinished work. I want the final result to look like this:

C - A'
     \
      B

However, by default Git assumes that A and A' are completely unrelated commits and it tries to do this instead:

C - A'
     \
      A - B

Which finally brings us to my question:

Is there a way to ask git to figure out by itself that we don't need to include A in the rebase because A' is already there? Or is this one of those situations that always requires human intervention to remove the duplicate commit?

2 Answers

This could be achieved thru git rebase --skip.

C - A'
     \
      B

When the branch B is rebased on master, this would be what you would see -

error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch' to see the failed patch
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

You can then do git rebase --skip which would skip the commit and the git history would look clean

It doesn't do what you're asking, but in these situations I've grown accustomed to always using git rebase -i. This allows you to:

  • Remove A from the to-do list first.
  • Avoid creating an A' commit that isn't already an ancestor to B. You instead can commit the typo fix as D:
    C
     \
      A - B - D
    
    And then when running git rebase -i C, you can reorder the to-do list to make D a fixup commit to A. Then you'll end up with:
    C
     \
      A' - B
    
    which is your desired end state. (If you commit D via git commit --fixup A, then the reordering will happen automatically when running git rebase -i if git.autosquash = true.)
Related