I am working on a project that has two branches: master
and feature
The feature
branch was created some time ago and has numerous commits.
Since the feature
branch was created there have been a couple of commits to master
At this point when I go to rebase
off of master
I get conflicts. I resolve them and then rebase --continue
. Then I get conflicts again, and again resolve and rebase --continue
. This happens over and over and many times it seems like they are the same conflicts that are appearing.
In my mind here is what is happening:
master(commits)->a->b
feature(commits)->c->d->e->f->g
feature
was branched from master->a
and then all commits were created.
When I rebase
it rewinds back to the begining of feature
where it was branched from master
applies master->b
and then starts to apply feature->c
at this point it has a conflict. I resolve (accepting the master
changes) and continue. Now it tries to apply feature->d
and finds the same conflict. Again I have to resolve and continue
. This happens over and over.
For example here are the changes:
master->a
<div id="foo">
master->b
<div id="bar">
feature->c
<div id="fubar">
feature->d
//Nothing has changed, inherited from feature->c
<div id="fubar">
I am assuming that when it reaches feature->c
it says change foo
to fubar
and then it notices that foo
is already changed to bar
. I resolve to bar
and then it does the same logic applying feature->d
My two questions:
1) Is my understanding of how git is working / dealing with commits/conflicts/rebasing correct?
2) How can I avoid having to resolve the same conflicts over and over again? I was thinking of squashing all of the commits on the feature branch so that there is only one to deal with. I was not sure if this was a good idea or exactly the best way to go about squashing in the scenario.
Note, this is a very simplified example. In reality I have a lot more commits and within each numerous files with numerous conflicts. Some of them appear to be the same throughout the rebase --continue
process and some are new for each commit
.
My end goal is to clean up this project as simply as possible (get the feature branch rebased off the current master). I do not care about the history of the commits.
I do not care about the history of the commits.
If you really don't care about history, a git merge --squash
is going to let you resolve all your conflicts at once and produce a single commit with all the changes.
To essentially do that --squash
in-place, you could do something like this:
git branch -m feature feature-old
git checkout master -b feature
git merge --squash feature-old
After you resolve all conflicts (once), you will create a single commit on feature
that has master
as a parent.
That being said, I'm a fan of keeping history. Definitely try rerere
first. You might also try an in-place rebase --interactive
(e.g. git rebase -i $(git merge-base HEAD master)
) to squash the fixup-type commits without completely eliminating all the discrete commits.
I had a similar issue and it turned out that I was resolving conflicts with --ours
when I should have been using --theirs
.
The reason is that --ours
is your changes in a merge
, but in a rebase
it is --theirs
because git effectively removes your commits and replays copies of them.
So when you resolve a conflict with your version with a rebase
do:
git checkout --theirs some.file
git add some.file
but when resolving a conflict with your version with a merge
do:
git checkout --ours some.file
git add some.file
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With