I am getting conflicts on files I have not modified. Conflicts on files with one line changes when merging. I am starting to get a handle on what might be happening but still unable to resolve the problem.
Here is the branch structure.
Master is quite old and has not had changes from current_iteration in quite some time. However master has had changes directly applied it by rebasing other bases directly onto master. So technically master and current_iteration have diverged. We have consistently branched and tag off of current_iteration. The problem I am seeing is that when I do a merge from current_iteration back into my branch. I get way more conflicts than should occur based on the changes to current_iteration. I am able to do a git diff / git apply from current_iteration and it applies cleanly.
When I run a git show-branch --merge-base
on mapr-autoinit I see the commit was actually a commit on master months ago. However when I check git merge-base current_iteration mapr_autoninit
I see that the version is very recent and most likely would not have conflicts.
From what I have seen for the last few days it seems logical that if I merge master into current_iteration, commit and then merge current_iteration back into master. This should probably resolve my branches merge-base to point to a more recent version.
Also is it possible that I could stop tracking master. I tried using git config --unset branch.master.merge; git config --unset branch.master.remote
to stop tracking master but this did not solve my issue.
Is this a problem where the master and current_iteration have diverged and merge is trying to reconcile the merge by replaying the entire log?
Also here is more detail. I am opening a new question now that the question is much more specific. I will update both with a valid answer or delete the older depending on which is preferred.
Git merge resulting in unreasonable conflicts
General tools. The status command is in frequent use when a working with Git and during a merge it will help identify conflicted files. Passing the --merge argument to the git log command will produce a log with a list of commits that conflict between the merging branches.
Merge conflicts happen when you merge branches that have competing commits, and Git needs your help to decide which changes to incorporate in the final merge. Git can often resolve differences between branches and merge them automatically.
To see the beginning of the merge conflict in your file, search the file for the conflict marker <<<<<<< . When you open the file in your text editor, you'll see the changes from the HEAD or base branch after the line <<<<<<< HEAD .
I've never found git show-branch
output very useful myself and I am not sure how it is intended to be used, nor how others might use it successfully.
Also is it possible that I could stop tracking master ...
This irrelevant. What matters is the actual commit graph. The upstream of any branch is independent of the commit graph.
Is this a problem where the master and current_iteration have diverged and merge is trying to reconcile the merge by replaying the entire log?
No. What matters after the merge-base-finding is only that—the merge base commit, that is—plus the two branch tip commits. Everything in between is irrelevant.
However when I check
git merge-base current_iteration mapr_autoinit
I see that the version is very recent and most likely would not have conflicts.
This is usually the way to get started, since git merge-base
examines the commit graph, and uses it to compute the merge base commit(s). Note that git merge
by default runs the equivalent of git merge-base --all
. If this produces more than one merge base (more than one commit hash ID), you have a special situation. Let's assume that you don't for now, but it's a good idea to check.
Having found that merge base commit, you can look at git log
output (see the last section) and see how the merge base relates to the two branch tips. Git does not care about this—well, that's not quite right: after Git has found the merge base (which depends on this), Git stops caring about it—but you might find it helpful.
Having found the (single) merge base of current_iteration
and mapr_autoinit
(and assuming you are on one of these two branches), here's what Git does:
git diff --find-renames <merge-base-hash> current_iteration > /tmp/1
git diff --find-renames <merge-base-hash> mapr_autoinit > /tmp/2
I redirected these to /tmp
files here for ease of viewing multiple times and side-by-side or whatever, depending on your file viewer(s). Since I don't know which direction you're merging—from what, to what—I just numbered the two files, rather than calling them "ours" and "theirs". Note that the combining changes step is largely symmetric anyway. For each change to each file, there are four possibilities:
merge.conflictStyle
to diff3
—I highly recommend this—Git includes the merge-base version as well, to show you what you and they started with before you and they made conflicting changes.Viewing the results, with merge conflict markers and with the base version included via merge.conflictStyle
set to diff3
, is usually sufficient. (In particular, it sometimes shows up cases where Git has mis-paired changes and thinks they conflict, when in fact the changes are to other regions that do not conflict.) If not, it may help to look at the commit graph.
Something that does work, but can be difficult to make sense out of,1 is the output of git log --graph
. It's helpful to include the --decorate --oneline
options, and for this particular case, you will want to list the names of the current branch2 and the branch you intend to merge. For instance, if you have mapr_autoinit
checked out and intend to run git merge master
, you could run:
git log --graph --decorate --oneline mapr_autoinit master
Git will do its best to draw, in ASCII art with optional extra color added to help, the commit graph. The result depends a great deal on what's in the graph, of course. Here is a snippet from the Git repository for the Linux kernel:
* 1ffaddd029c8 (HEAD -> master, tag: v4.18-rc8, origin/master, origin/HEAD) Linux 4.18-rc8
* a8c199208cd6 Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
|\
| * 1b3a62643660 x86/boot/compressed/64: Validate trampoline placement against E820
* | 2f3672cbf9da Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
|\ \
| * | 0a0e0829f990 nohz: Fix missing tick reprogram when interrupting an inline softirq
| * | 80d20d35af1e nohz: Fix local_timer_softirq_pending()
* | | 0cdf6d4607df Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
One can use this to trace what has happened since the merge base. There are more tools:
git log --graph --decorate --oneline --boundary mapr_autoinit...master
for instance will show you what's not merged (commits marked *
), plus (due to --boundary
) boundary commits that are merged (commits marked o
) but without going any deeper into the graph than that.
For very simple cases—graphs that are not horrid with internal branch-and-re-merge—adding --left-right
to the three-dot syntax is sometimes helpful as well. For complex cases, with lots of internal branch-and-merge actions down each leg, --first-parent
is sometimes useful, and --simplify-by-decoration
is sometimes useful.
1Despite this, it's still worth perusing. If you prefer, use a GUI or similar that draws the graph more prettily, but be aware that at least some Git GUIs seem to draw incorrect graphs (coughvariouscoughwebservicescough).
2You can always just use the name HEAD
, in all capital letters, in place of the current branch name. All-lowercase works on case-insensitive file systems on Windows and MacOS for instance, but it's not good to get into that habit. A lone at-sign @
means HEAD
in any modern Git, though, so if you prefer, use that instead of spelling out HEAD
. Note that when using the two or three dot syntax (A..B
and A...B
), omitting one name entirely also means HEAD
: HEAD..B
, @..B
, and ..B
are three spellings for the same thing.
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