Search code examples
gitrebase

Git rebase consistently deletes changes


For some reason, every single time I've tried to use rebase, it ends up discarding all of my feature branch commits. Here is an example of what the interactive rebase onto master shows:

pick 05973319 First commit
pick 62341efd Second commit 
pick e1c1a080 Third commit
pick 2b5285f7 Fourth commit

Note that all these commits were made on the feature branch. Now when I exit interactive mode, the rebase fails due to conflicts. However, $ git log does not show any of the feature branch commits. And if I look at the files I modified in the feature branch, all those changes were discarded.

This seems to happen to me every single time I've used rebase on multiple repositories. In other cases where no conflict existed, Git would simply delete all my changes and indicate that there was nothing wrong.

I do not understand how this kind of conflict resolution is remotely acceptable. Is there some kind of misconfiguration or antipattern that could lead to this? Note that merging with $ git merge master always works as expected.


Solution

  • ... Now when I exit interactive mode, the rebase fails due to conflicts.

    It has not yet failed. It has stopped, after applying zero or more of the pick commands.

    The git status command, in any modern Git, will tell you that you are in an interactive rebase that has not yet finished, at this point. (In the bad old days git status did not tell you such things and you just had to know or guess.)

    $ git log does not show any of the feature branch commits.

    That suggests that the problem occurred during the very first cherry-pick, so that none of the picked commits are in the in-progress, being-built branch yet. That is, zero of your four picks have succeeded so far. The pick 05973319 is in progress right now and git status will tell you which files need hand-massaging to fix them up, after Git left you a mess.

    Your job is to fix them up—perhaps using the mess left behind in your work-tree, perhaps using git mergetool and some favorite merge tool; the method is up to you. But you must fix the problems. Having fixed them, and run git add if necessary,1 your git status will tell you that all conflicts are fixed and you should run git rebase --continue to make the rebase finalize that cherry-pick and move on to the next one. The next one may or may not have conflicts. If it does not, Git will finish that pick on its own and move on to the third, otherwise this whole thing repeats.

    This kind of rebase behavior is normal, though how common it is depends on your work patterns and input files. Some people encounter it constantly, and some almost never.


    1If you use git mergetool, it will usually do the appropriate git adds for you. I prefer to avoid git mergetool: I set merge.conflictStyle to diff3 instead, and normally, just use my editor on the mess left behind in the work-tree. Setting diff3 style changes the marked-up conflict to include the first, or merge-base, input. The default style leaves only the second, --our, and third, --theirs, sections. The merge base code, from which our and their versions diverged, is therefore invisible, and this sometimes makes the conflicts very difficult to understand. But this is all a matter of personal taste.