Reputation:
I'm updating an old feature branch with upstream and there's lots of merge conflicts. Resolving the conflicts in-place is not safe because I cannot reason about the actual change using only the text diff.
I need to find the commit in the upstream branch that made the change so that I can incorporate the update to my branch manually, considering the semantic differences (and to figure out what other parts of the branch need an adjustment).
How can I find such commit for each conflicting chunk?
Upvotes: 2
Views: 576
Reputation:
After investigating suggested solutions, I decided to reverse the merge by starting fresh on the tip of upstream in a new commit and merging in the feature branch with --squash. That way the merge is based on the upstream changes and you can better decide to how resolve conflicts or go with ours
and adjust the code in a follow-up commit.
Upvotes: 0
Reputation: 60275
When a merge base is so far back the changes have become soup and you can't separate out what's what, there's git imerge
, which automates walking forward from the merge base step by step, stopping at the pairs that introduce conflicts along the way. It's not often needed, but when you need it it does a whole lot of note-taking and note-consulting for you.
Upvotes: 3
Reputation: 97718
You could flip the problem around: instead of merging the feature branch into upstream, try rebasing it onto upstream.
A merge will apply all changes at once. Specifically, it will find the last common ancestor of the two branches, and compare each branch to that. The merge algorithm is then looking at those two changes, and doesn't care about commits in between. The question "which commit caused this conflict" has no meaning to the merge algorithm.
A rebase will instead apply each commit in turn, attempting to create a new commit as though you'd made the same changes based on the specified upstream. If a commit causes conflicts, it will stop at that particular commit for you to fix it, and the conflict view will show you the changes from that commit only. Once you've fixed it, running git rebase --continue
will attempt to apply the next commit, and either succeed or stop again for you to fix more conflicts.
The downside is that you may have to fix very similar conflicts multiple times, or fix conflicts in code that wouldn't actually have conflicted in a straight merge. For instance, if you made a conflicting change and then reverted it in a later commit, it won't cause a conflict in a merge, but it may cause two conflicts with rebase (the first recreating the original change; and the second recreating the revert).
Once you've got a fully rebased branch, you can merge it into upstream with a guarantee that there will be no conflicts, because all the commits on upstream are already incorporated in its history.
Upvotes: 1