0

I am trying to contribute to a GitHub repository. The commit from before I started contributing I'll call "a". I made a commit "b" and my pull request for it was accepted. I then made another commit "c" and I have made a pull request for it but it has not yet been accepted. I made another commit "d" which I committed to a new branch so I'd be able to pull it separately. However, I forgot to rebase back to "b" before creating "d" so the branch for "d" also contains "c" meaning "c" would exist on both branches which I don't want.

So, currently I have this

a-b-c-d

But I want this

a-b-c
  \-d

How can I accomplish this?

This question has been marked as a duplicate of questions asking how to undo the last commit, but these do not answer my question because it's not the last commit I'm trying to undo but instead a commit twice back. Rebasing to HEAD{2} also doesn't work because that still undo's the last commit.

hopperelec
  • 133
  • 1
  • 2
  • 13
  • 3
    Does this answer your question? [How do I delete a commit from a branch?](https://stackoverflow.com/questions/1338728/how-do-i-delete-a-commit-from-a-branch) The second option answer is your choice https://stackoverflow.com/a/1338758/6752050 – 273K Dec 30 '22 at 00:06
  • @273K That would remove "c" from the branch, which I want, but it would also remove "d" since "c" was before "d", which I don't want, so no that doesn't answer my question – hopperelec Dec 30 '22 at 00:10
  • It will not remove `d`, see the second option in my answer. – 273K Dec 30 '22 at 00:14
  • @273K that answer says 'The ~N means rebase the last N commits', explaining itself that it's not just the Nth old commit that is 'removed' but also the commits after that. – hopperelec Dec 30 '22 at 00:20
  • Rebasing without changing all following commits is impossible, thus it rebases N commits. – 273K Dec 30 '22 at 00:28
  • Which is why I don't think that answer answers my question. But I might be misunderstanding – hopperelec Dec 30 '22 at 00:41
  • The top comment on the linked question actually perfectly describes why the answers to that question don't answer the question very well. My question is specifically targeting what those answers lacked. – hopperelec Dec 30 '22 at 01:06
  • But you've accepted an answer. So you don't need the question reopened; the problem is solved. – matt Dec 31 '22 at 19:43
  • @matt I know I already have an answer, but isn't the point of StackOverflow that the answers aren't just there to help the asker? – hopperelec Jan 01 '23 at 11:46
  • And it still can. – matt Jan 01 '23 at 14:06
  • @matt I thought StackOverflow didn't recommend closed questions to people? But even if it does, people still can't provide improved answers. The current answers works, but it may not apply to everyone and there might be another solution that works better in another, similar situation. Questions aren't supposed to be closed just because they already have an answer, they're supposed to be closed if they aren't good questions (duplicate, unclear, opinionated...) – hopperelec Jan 01 '23 at 14:12
  • Taking you seriously: This has nothing to do with "just because they already have an answer". The base reason for closing here is that the question itself is unoriginal and fails to distinguish itself sufficiently from existing questions that have good answers. The question falls right into that category. I myself have responded to multiple questions with explanations of how to perform exactly this kind of topological rearrangement. The fact that the answerer got in under the wire and the answer got accepted doesn't counteract any of that; it's not a valid reason for reopening. – matt Jan 01 '23 at 14:50
  • By the way, personally I would have given this solution (where the notation means "the SHA of the commit whose message is x": `git branch newbranch; git reset --hard ; git rebase --onto newbranch`. This would exactly change your first diagram to your second diagram. – matt Jan 01 '23 at 14:55

1 Answers1

3

The easiest way:

  1. Remember the d's SHA1, let say it is 535dce28f1c68e8af9d22bc653aca426fb7825d8.
  2. git reset --hard HEAD~2
  3. git cherry-pick 535dce28f1c68e8af9d22bc653aca426fb7825d8

More advanced:

  1. git rebase -i HEAD~3
  2. Change the second pick to drop, or remove that line, then save the file and exit from the editor.

More advanced 2:

  1. git revert HEAD~1 will make b-c-d-^c
  2. git reset --soft HEAD~3 will reset to b and keep the changes on the disk
  3. git add -A && git commit will make b-d'.
273K
  • 29,503
  • 10
  • 41
  • 64
  • 2
    If `d` modifies new lines in `c`, merge conflicts are possible. Just solve them. – 273K Dec 30 '22 at 00:18
  • 'The easiest way' and 'More advanced 2' work, but I'm confused by step 2 of 'More advanced' and I don't see how that would accomplish what I'm looking for – hopperelec Dec 30 '22 at 01:07
  • The second option shows the list `pick b, pick c, pick d`, you change it to `pick b, drop c, pick d` and get `b-d'` after merge finishes. – 273K Dec 30 '22 at 01:16
  • Oh, I didn't notice the '-i' and I was still putting '--hard' when trying it. – hopperelec Dec 30 '22 at 01:20