tummychow / git-absorb

git commit --fixup, but automatic
https://crates.io/crates/git-absorb
BSD 3-Clause "New" or "Revised" License
3.35k stars 59 forks source link

"Inverse" git aborb? #86

Closed devinrhode2 closed 1 year ago

devinrhode2 commented 1 year ago

Let's say a questionable PR was merged in order to hit a deadline for a demo.

However, that code has since been completely re-written.

Of course I can branch off master, revert the PR/commits, and then base the re-written work on top of that. However, I'd like to avoid the wholesale initial revert.

How can I make the initial revert "absorb" UP into the subsequent commiits?

Answer?

Enter interactive rebase Drop the revert commit Favor re-written code in every conflict (could use --strategy-option) Check final diff, cleanup anything at the end (revert more) if needed

tummychow commented 1 year ago

i'm not sure i fully understand the question. let me try saying it back to you:

so the branch structure looks something like this:

old PR <- current master
|
C - new PR <- my current branch
|
B
|
A

i want to revert the old PR on my branch, so that it would look something like this:

new PR <- my branch
|
revert of old PR
|
old PR <- current master
|
C
|
B
|
A

but i don't want the revert to be a single commit, i want it to be absorbed into the commit(s) of my new PR. is this understanding correct? a rough sketch of how this could be done:

i'm going to be honest with you, this sounds quite unpleasant to implement. it does reuse some existing git-absorb machinery, but it also demands a lot of new machinery that git-absorb doesn't currently need. in particular, splitting a commit that's beneath a bunch of other commits is quite fiddly work. it essentially requires us to reimplement most of the functionality of an interactive rebase. this is much harder than what git-absorb currently has to do, which is simply creating new commits on the top of the stack.

furthermore, the use case seems very niche. i mentioned before (https://github.com/tummychow/git-absorb/issues/44#issuecomment-851106623) that i'm open to plumbing flags on git-absorb to query commutation (which would be useful for the first bullet point of the described algorithm). i think anything more than that would be a tough sell for me. we're talking about a lot of code for something that's pretty rare. if i was in this situation, i would just leave the revert in one commit and move on... the new PR might even be easier to review that way.

rjmunro commented 1 year ago

You could maybe do something like:

This may or may not achieve exactly what you want, but even if it works double revert will mess up the commit message - I'm not sure if there is a good way to fix that, there may be a way using revert's --no-commit option and committing with-m, but then you'd need to run in a loop rather than use revert's ability to undo multiple commits.

devinrhode2 commented 1 year ago

I think the general solution is to get everyone on a team creating small commits which are easy to revert or otherwise discard.

Agreed this is not worth the effort.

On Tue, May 16, 2023, 12:55 PM Robert (Jamie) Munro < @.***> wrote:

You could maybe do something like:

  • Revert all your commits with git revert [base]..HEAD
  • Run absorb on the reverted commits
  • Revert them all again
  • Rebase --onto [base] to get rid of your original working and reverts, leaving only the reverted absorbed reverts

This may or may not achieve exactly what you want, but even if it works double revert will mess up the commit message - I'm not sure if there is a good way to fix that, there may be a way using revert's --no-commit option and committing with-m, but then you'd need to run in a loop rather than use revert's ability to undo multiple commits.

— Reply to this email directly, view it on GitHub https://github.com/tummychow/git-absorb/issues/86#issuecomment-1550118026, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEDZKGXTKCXCMDRCJY44UTXGO5PXANCNFSM6AAAAAAXQ4S53U . You are receiving this because you authored the thread.Message ID: @.***>