Mr Redstoner
Mr Redstoner

Reputation: 488

Git rebase branch onto older commit

Note: How this situation came to be is more of a tale that anything and not really relevant IMO.

Given the following git commit graph, starting from oldest, all pushed to origin

          start
            |
         breaking
       /          \
fix #0             work
    |               |
fix #1(master)     morework(issue-fix)

I need to move my branch (issue-fix) to be based on start, rather than breaking, that is turn it into

          start
       /         \
breaking            |
    |               |
fix #0             work
    |               |
fix #1(master)     morework(issue-fix)

The changes in breaking are unrelated to the issue fix (different part of project), hovever they cause the CI to fail for that branch, as the testing covers that part of the project as well.

I assumed a rebase would work, but after checking out morework, attempting it in SourceTree did nothing, manually running git rebase start just prints Current branch issue-fix is up to date

Is there a clean and effiecient way of doing this? I don't want to make a new branch and move everything over manually if I don't have to.

EDIT: Also, issue-fix has been pulled into another branch, thereby introducing the wrong commits there as well. Will the same process work there, or will doing it on issue-fix break that branch?

Upvotes: 11

Views: 21525

Answers (3)

Rozart
Rozart

Reputation: 1788

You should use interactive rebase to get rid of the breaking commit from your issue-fix branch.

In your case you should, checkout to the issue-fix branch and do:

git rebase -i HEAD~3

Then when the editor is open you should be able to choose which commits you want to leave and which you want to get rid of:

drop 2dsafa ... will delete the commit you want to get rid of
pick sdfsadf .. will leave this commit
pick dfsa4sdc .. will leave this commit

If your issue-fix branch have been already merged into other branches in its broken state, then things become a bit more complicated.

In such case I would suggest to use the interactive rebase to get rid of the issue-fix commits from those other branches. After that I would rebase the commits from those other branches on top of issue-fix.

Upvotes: 16

mimikrija
mimikrija

Reputation: 113

You would need to run interactive rebase for that.

On branch issue-fix run: git rebase --interactive start

This should pop-up the editor:

pick breaking <commit message>
pick work <commit message>
pick morework <commit message>

you should change "pick" from the first line to "drop" - i.e., you'd like to drop the breaking commit from your branch and rebase it top of start. Save and close the editor. Run git log to check the result.

As always, be careful as rebasing changes the commits hashes i.e. even though the commits work and morework look the same, their parents would have changed, causing their respective commit hashes to change. This is potentially dangerous if issue-fix is a shared branch.

In case you are not sure whether someone already pulled your issue-fix branch, I'd go with git revert breaking. This is a safe choice that does not mess up your branch history (it just adds another commit which "cancels out" breaking).

Upvotes: 0

ElpieKay
ElpieKay

Reputation: 30976

git rebase --onto start work^ issue-fix

It tries to move the commits from work(included) to the tip of issue-fix onto the new base start.

If you want to skip or squash some of the commits, use the interactive mode with -i. The interactive page will show you how to.

If you want to keep merge commits, you could add -p. To keep empty commits, use --keep-empty.

You may have some other needs not mentioned in the question. But most probably you could find proper options in the manual of git rebase.

Upvotes: 4

Related Questions