Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix conflicts after rebase and push them

Tags:

git

branch

rebase

In our project we use git, every feature we release in new branch and after codereview CTO rebases it into the develop branch. After I finished my ticket CTO said that he can't rebase my changes bc conflicts occured. I reproduced it on local machine:

git clone ...
cd project1
git checkout my-branch
git rebase develop
...
Auto-merging admin/contest.html
CONFLICT (content): Merge conflict in admin/contest.html
Failed to merge in the changes.
Patch failed at 0019 contest: admin, dashboard, /contest

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".

Ok, I resolved this conflict, than added this file but I can't continue rebase or push something. What is the best way to resolve such conflicts?

UPDATE

After I did git rebase --continue I got:

Applying: $0 in admin/contest dropdown
No changes - did you forget to use 'git add'?
If there is nothing left to stage, chances are that something else
already introduced the same changes; you might want to skip this patch.

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".
like image 421
greg Avatar asked Oct 24 '25 18:10

greg


1 Answers

A rebase, whether interactive or not, works by repeating a simple cherry-picking process.

First let's define a "cherry pick".

Suppose you have a branch (e.g., a production branch) that is not ready to be upgraded generally, but you also have a bug. Suppose further that, on a development branch, someone already fixed that particular bug, and the fix is simple and clean and will work in the production code. (For instance, changing one line in fileA and two lines in fileB fixes the problem, and this can be done on the production branch.)

You could:

$ git show 15fd3dc > /tmp/bug-fix

to see the change and write the patch to a file, and then manually copy in the patch and git add and git commit. Or you could even do the above, or use git format-patch, and then use git apply or git am to import the patch to branch production. But it's even easier: you can simply get on branch production and use:

$ git cherry-pick 15fd3dc

and git will, in essence, extract the fix and apply and commit it, all automatically. In other words, it copies a commit.

Now let's consider a rebase. Here we have something like this:

... o - o - o - * - * - X - * - *   <-- your-work
              \
                o - Y - Z   <-- their-work

I've labeled one of your commits X and two of theirs Y and Z, just so that I can make something special happen with them later. First let's just look at the mechanics of the rebase.

To do the rebase, git simply needs to take each of your commits (the * ones, along with X in the middle) and cherry-pick them onto the end of their-work. That is, we create a new temporary branch and start copying commits:

... o - o - o - * - * - X - * - *   <-- your-work
              \
                o - Y - Z   <-- their-work
                          \
                            * - *   <-- temp-branch

In many cases, all the commits copy over trivially: there are no conflicts and all your commits cherry-pick cleanly. In that case, git then does the final step: erase the old branch label your-work, and change the branch label temp-branch to your-work, so that your (copied) commits now sit atop commit Z.

In this case, however, there was a conflict when trying to cherry-pick commit X. It conflicted with one or both of commits Y and Z: those other two commits changed something in the same region where your change in X goes.

This is where rebase stops and gives you the message you saw:

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".

You begin the manual resolving, by editing the conflicted files (with your merge tool rather than with a plain text editor, but the effect is the same) and git adding the final files.

Next, you run git rebase --continue. At this point there are two possibilities (assuming you did remember to git add files as needed):

  1. You still have some change from the previous revision (Z if this is the first commit being copied, or one of the copies of your * commits if later; given where I drew X, this would be one of those copies).
  2. You actually have removed all your changes during the conflict resolution. Perhaps commit Y had half of what you did, and then commit Z had the rest of it, so now your commit X is redundant with those two commits.

You appear to have hit case (2). In case (1), git rebase --continue just goes on to copy the rest of the * commits, and then moves your branch label. In case (2), however, git rebase --continue complains:

No changes - did you forget to use 'git add'?
If there is nothing left to stage, chances are that something else
already introduced the same changes; you might want to skip this patch.

In this case (and only if you did not forget to do the git add step), you should, as the next bit tells you, use git rebase --skip. This tells git to forget about your earlier commit X entirely, and go on to cherry-pick the remaining * commits.

like image 74
torek Avatar answered Oct 26 '25 07:10

torek