Question

My git repo's history looked like:

* (topic2) commit_11
* (topic1) commit_10
* commit_9
* commit_8
* (HEAD, master) commit_7
* commit_6
* commit_5
* commit_4 <- I wanted to edit this commit.
* commit_3

So I did

git rebase -i commit_3

and replace pick by edit for commit_4 in editor. I corrected some typos in variable names and then

git add .
git commit --amend
(rename commit)
git rebase --continue

And now history looks like:

* (HEAD, master) commit_7.1
* commit_6.1
* commit_5.1
* commit_4.1 <- Edited commit.
| * (topic2) commit_11
| * (topic1) commit_10
| * commit_9
| * commit_8
| * commit_7
| * commit_6
| * commit_5
| * commit_4 <- Original commit.
|/
* commit_3

I want to make my history straight and clean like previous. I try the way that I successfully used multiple times before

git checkout topic1
git rebase master

But it ends up with conflicts when applying first patch. I resolved them manually. But when I try git rebase --continue, it tells me "Nothing to commit".

How to deal with the problem and why it has arisen?

Was it helpful?

Solution

(I took the liberty of modifying your diagram to indicate that when you rebase, all the commits change, even if the contents don't. Your new set of commits will have different shas than the originals.)

The simplest solution here is use --onto. Have a look at this link, starting at the text "Here is how you would transplant a topic branch": git rebase

So in your case, it would be:

git rebase --onto commit_7.1 commit_7 topic1

In other words, take the commits from after commit_7 until (including) topic1, and transplant them onto commit_7.1.

You may still get merge failures that you have to manually fix, though.

I recommend that when you do this, you create an extra branch on the topic1 commit. Call it topic1old or something. That'll make it easier to go back in case the rebase doesn't go right; you can just hard reset your topic1 back to that commit.

EDIT: Why didn't simple git rebase master work?

If you don't tell it otherwise, git rebase assumes that you're rebasing against your upstream branch.

But as you see from the way I modified the diagram, topic1 and master don't have much in common anymore. If you do a simple rebase onto master, topic1 will try to rebase all of your commits onto all of the commits on master. Which means you'll get something like:

  • (topic1) commit_10
  • commit_9
  • commit_8
  • commit_7
  • commit_6
  • commit_5
  • commit_4
  • (HEAD, master) commit_7.1
  • commit_6.1
  • commit_5.1
  • commit_4.1 <- Edited commit.
  • commit_3

Now Git is smart about not duplicating commits that are already present. Obviously if you make changes X, Y, and Z, and then a later commit makes those again, Git just omits the later commit since those changes are already present.

But what throws a wrench into things is your change to commit 4. The result is that all of the commits after that are committing onto a different set of code. This leaves the potential necessity for a lot of merging.

Using --onto fixes this because it allows you to use a different base. You're saying: "I don't care about commit_4 (because I changed it) nor about commit_5, _6, and _7 (because I've already merged them, and they're essentially the same as in my topic branch). So start from commit_8 on, rebasing just those changes on top of the stuff I've already dealt with."

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top