109

I recently rebased a branch that I was working on. The history of the tree looked something like this:

1 = 2 = 3 = 4
     \
      5 = 6 = 7
           \
            8

I wanted to rebase my changes (number 8 in the diagram) to be on the master branch (up to commit 4 on the diagram now). So I did the following:

git checkout my_branch
git rebase master

< lots of git mergetool/git rebase --skip to resolve conflicts >

Only now when I run:

git checkout my_branch
git diff master

I get zero differences. I haven't lost my branch (I can still recreate my changes from a patch that I saved) but I can't find the merge/rebase that I did. What did I do wrong? Is the rebase still there somewhere with my changes merged with the master or do I have to do it again?

dave
  • 4,812
  • 4
  • 25
  • 38
  • 2
    When you did `git rebase --skip` (instead of `--continue`) is it possible you "skipped" a change that actually still had meaningful changes during the rebase? – CB Bailey Oct 31 '12 at 09:17
  • See this answer: http://stackoverflow.com/a/4851776/450609. I had to use git rebase --skip in order to skip over the change which I'd just manually merged. – dave Oct 31 '12 at 09:24
  • 2
    If you've manually merged you usually want to `--continue`. You only need to skip if the result of the merge is "no change". How many of the changes did you skip and how many did you actually apply? – CB Bailey Oct 31 '12 at 09:38
  • I don't remember, when I tried git rebase --continue it always said "No changed did you forget to git add". And then I found the answer I linked above and I started doing git rebase --skip. I also restarted the whole process so I could have skipped some. But the diff is _nothing_, and git status shows nothing. My work should have gone somewhere (I hope). – dave Oct 31 '12 at 09:42
  • Well, if the diff is nothing then there were no effective changes to rebase (if I've understood you correctly - perhaps they were applied in different commits on the master branch?) so you wouldn't expect any commits in the results of your rebase. You can always reset your branch back to before the rebase and retry the rebase being careful not to skip any patches that _should_ have an effect. (Use `git log -g` to find the where your branch was before the rebase.) – CB Bailey Oct 31 '12 at 09:45
  • 34
    I have a new rule: No rebasing after 1am – ryan0 Jan 29 '15 at 06:33
  • 4
    An easy way to avoid problems with a rebase going wrong is to create a branch before starting it. You'll be able to compare the final result with the original more easily, as well. Just delete the branch when you finish. – jpmc26 Jun 20 '16 at 22:40
  • 3
    This (https://) goo.gl/YQUyi1 saved my time. – InaFK Oct 09 '18 at 13:55

1 Answers1

247

If you're not seeing any difference, I suspect you lost your changes. You can likely use git reflog to identify the branch that existed before the rebase, and use git reset --hard <my-branch-tip-before-rebase> to get back the original branch. And yes, you'll have to run through the process again. :-(

I'm not quite sure how you ended up with them looking the same though. I would have expected to see the following with the command you gave:

1 = 2 = 3 = 4              (master)
     \       \
      \       5' = 6' = 8' (my_branch)
       \
        5 = 6 = 7

In this case, you probably should've used rebase --onto:

git rebase --onto master <commit id for 6> my_branch

That would have left you with a graph that looked like this:

1 = 2 = 3 = 4              (master)
     \       \
      \       8'           (my_branch)
       \
        5 = 6 = 7

As far as losing your changes, it does take a bit of practice dealing with merge conflicts, especially when you have a couple of big blocks that look nearly identical. I always resort to looking at the actual diff introduced by a commit, and the attempting to tease out that change and merge it with what is already on the branch in an appropriate way. I can easily see how your change may have gotten lost in there.

One thing to remember. If you don't expect a bunch of merge conflicts--because you don't feel the sources diverged enough, the seeing one is a warning flag of doing something wrong. It's good to back up, by doing a git rebase --abort, investigating the branches and checking again if you expect a conflict. Make sure to take note of where the conflict happened (there's usually a "Applying ..." just before rebase kicks you to the command line). That's usually a great place to start.

At times, conflicts are unavoidable, and are tedious to work through. But I suspect with practice, you'll run into this problem less.

For more information on transplanting changes between branches, look at the git rebase man page. Search for "rebase --onto". The first hit should land you in a section talking about transplanting changes to another branch.

John Szakmeister
  • 44,691
  • 9
  • 89
  • 79
  • You were right; I used the wrong command. I needed to say --onto. I've got my rebased patch now :) (and I did have to redo it but fixing a conflict for the second time is much easier). – dave Nov 01 '12 at 00:41
  • Awesome! Glad it helped! And yes, I find the same thing: conflicts are definitely easier the second time around. One interesting feature is rerere. Scott Chacon has a [nice article](http://git-scm.com/2010/03/08/rerere.html) on the facility, and is very helpful in resolving conflicts, if you find you're running into the same one over and over. – John Szakmeister Nov 01 '12 at 01:36
  • 39
    `git reset --hard xxxxx` saved me! I thought everything was lost! Even `git reset xxxx` without the `--hard` didn't work! – Chloe Apr 09 '14 at 22:15
  • 8
    I've seen something similar. I saw it in a previous job, and I saw it again today. The repository can someone get into a state where a regular `git rebase` (against the upstream) loses all the local commits, and just sets the head to the upstream. Whereas a `git rebase -i` with no changes (everything is picked) works correctly. I honestly think it's some sort of obscure bug. – Ryan Lundy Dec 23 '15 at 17:46
  • 18
    OMG! You saved me! I did a reflog and then a cherry-pick :D – Fernando Martínez Dec 21 '17 at 16:39
  • 3
    `git reflog` +`git cherrypick` saved my lost commit. thanx~ – Ryan Yan Nov 10 '20 at 03:11
  • whats different with --onto flag? is it like merge? – Hassan Faghihi Nov 16 '21 at 11:10
  • 2
    @deadManN This is a slight over simplification, but a normal `git rebase A B` will compute the what is in B, but not in A, and then put those extra commits in B on top of A. It's actually a short form of `git rebase A B --onto A`. You can, however, choose to put those commits onto a different branch (instead of A), so you could say `git rebase A B --onto C`. It still computes the extra commits in B but not in A, and then places them onto branch C. It's a bit hard to explain in comments and is better with pictures, but I hope that helps give you the idea. – John Szakmeister Nov 17 '21 at 23:05
  • When you say it compute, its more like it take differences rather than continue the last commits and merge :-s yeah it's hard... but what about `rebase A` without `--onto`? I believe when I use rider it do onto... as name suggest. with VS, I'm not sure – Hassan Faghihi Nov 17 '21 at 23:53
  • 1
    @deadManN `git rebase A` is the same as `git rebase A B`, where B is the current branch. So rebase will determine what commits are in the current branch and not in A, then replay those commits on top of A. Does that make sense? I'm not sure what you mean by "I believe when I use rider it do onto... as name suggest. with VS, I'm not sure". I don't use VS, so I'm a bit useless in that department. :-) – John Szakmeister Nov 20 '21 at 18:25
  • well jetbrains bring commits from B to A, when current is A and selected is B... so it is not as you said... the thing I had issue with was that I thought there is differences between result from this ```1 = 2 = 3 = 4 (master) \ \ \ 5' = 6' = 8' (my_branch) \ 5 = 6 = 7 ``` and ```1 = 2 = 3 = 4 (master) \ \ \ 8' (my_branch) \ 5 = 6 = 7``` where 8` had branches before it, and in later one, it was alone – Hassan Faghihi Nov 21 '21 at 09:11
  • 1
    @deadManN Why are you comparing the git command line to what jetbrains is doing? I'm talking about the command line and the command line only. Another UI might present the situation differently. You're words, however, describe exactly the situation. In my example A was the "selected branch to bring commits" from and "B" was the current branch. If you change your assignment to match mine, then it's doing exactly what I said. :-) Also, trying to post ASCII pictures as comments doesn't work. I have no idea what your picture is trying to represent. :-( – John Szakmeister Nov 21 '21 at 19:54
  • It was just the first, and the second, representation that you did provided in the actual post – Hassan Faghihi Nov 22 '21 at 07:54
  • 1
    @deadManN Ah, I see. Yes, there are slight differences, and it stems from how to compute the difference (the commits on B not on A) and then where to put the commits. It does takes some study to get it all squared away in your mind. I know it took me a bit when I first looked at rebase. :-) The Git book has a section on it: https://git-scm.com/book/en/v2/Git-Branching-Rebasing. I may have another reference I can dig up and post here too. Best of luck with everything! – John Szakmeister Nov 26 '21 at 10:13
  • I lost all my 3 days of hard work after rebase. Utterly disappointed me when searched for answer, 'git reflog' and 'git reset --hard xxxx' saved my day. – Vikas Piprade Feb 15 '23 at 10:05