Using git rebase to resolve merge conflicts on the CLI
I ran into a merge conflict today that, admittedly, my off-hand knowledge of
git didn’t cover (usually the kind of thing I’d look up) and I didn’t know off-hand how to resolve it (without forcing the merge to commit without review), but I worked with a teammate to understand how to work through this without having to re-do a ton of work, and it was a pretty neat use of
git rebase . Because git output can be sometimes kinda daunting to look at, that you may have the tools at your disposal to resolve it right away but since these solutions are not always obvious, it’s easy to overlook that resolving such conflicts are usually the result of one of a handful of possible methods.
The use case here is pretty specific, but also allows you to correct things like a merge conflict, without committing said merge (for example, if your organization requires a second person review before merging, or each commit be reviewed, etc.) so where I merge with
master in the examples, assume this is being done by a second user for the sake of the demonstration.
Consider a scenario where you’re making a change in a feature branch from
pre-production , but it’s a file that gets touched all the time, so another feature branch, making a change to the same line (something very dynamic, like a serial or just something to distinguish it iteration-to-iteration), ends up getting merged before yours, so your update is still valid, but it’s compared to the earlier
pre-production copy, which has since been replaced when your new pull request comes in.
Let’s say, for example, that this change is just a timestamp, so no matter what order the commits are made in, they’ll be unique, so it’s not really a conflict, but compared to when the feature branch was created, comparing to the previous version master, vs. the current, it will conflict, despite it not conflicting in real-time. It ends up holding up a gigantic pull request for your feature!
Okay, so you can do two things: just re-do pull request with a new branch that has the updated version of the tracked branch, but that’s only easy if the change was trivial. With some features with commits into the dozens, that’s not always easy, or fun. So,
git rebase can be used to allow you to modify the single piece of your pull request, if the change had since been committed.
So, let’s get to it.
You, Developer A, need to make a change to some file to make the merge unique:
Great. Okay, so let’s say you go ahead and update your file with that unique, serialized ID at some point during your development:
Great, so theoretically, with nothing else going on, if you committed right now there’d be no problem, right?
Let’s say, another team member is working on another feature,
feature_b , that has some overlap with this service, so that developer updates the same file, and you both created your feature branches from Master, so you’d be updating to the same serial. So, at this point, if you created a pull request for
feature_a, you’d still be more or less even with what got merged with their pull request on their feature. But, because development never ends, they proceed, and knock out a smaller feature that requires another update, so it gets incremented again, so now that counter is up one from where you are now.
so when you go to commit this change, and then try to merge it…
you get that nasty conflict error at the end. So, since this change is relatively easy to make, you can run
git diff to see that it’s showing where your serials ran into each other:
and if your change were as simple as changing this one line in reality, you’d just go ahead and recommit, but realistically, in a much larger codebase, this may not be as trivial a change, so for the sake of the demonstration, we’ll take this a step further.
Back on your feature branch, rebase to master:
and in the editor, you’ll see this:
You’ll change that first line,
pick to read
Then use your regular
vi exit (`ESC`, then
:wq! )to save this.
You can, then, go ahead and edit the file:
Once that is done, you can add and commit the file:
and with the
--continue , you can push to the feature branch, and re-attempt the pull request free of conflicts.