2

I have a fork of zprezto at http://github.com/ohcibi/prezto

To reproduce my problem:

  1. git clone http://github.com/ohcibi/prezto
  2. cd prezto
  3. git checkout ohcibi (i have a branch with that name, no typo here!)
  4. git merge master
  5. A bunch of conflicts are shown

The commit log shows that there are only 3 commits in ohcibi that are new since the last merge commit which is around april 26th. All 3 of the commits do not touch any of the files that conflict (except one file where the confict is to be expected).

But why is that merge conflicting on the other files and even .gitmodules as well?

Note: I don't need help solving that merge conflict! I know how to do that and I deliberately did not add the git-merge-conflict-resolution-tag to that question as it would be a wrong tag (so it is not missing, don't add it!). I want to know why those conflicts happen in the first place (given that the conflicting files are *not* changed in both branches, which is the usual reason for a merge conflict, that I am aware of).

ohcibi
  • 2,518
  • 3
  • 24
  • 47
  • Well are these other files truly identical in both branches? Could there even be differences in whitespace or line endings? I have seen conflicts pop up in all sorts of places where I did not expect it. – Tim Biegeleisen Sep 20 '17 at 15:54
  • I'm afraid you did not read the question carefully. The 3 commits that are exclusive to the `ohcibi` branch *do not manipulate the files in question in any way*. So even if it was caused by some whitespaces, there must be commits in `ohcibi` that add those whitespace changes but there arent. I repeat: the conflicted files *are not touched by one of the branches*. one can actually verify that by cloning the repository and showing the commit log (`git log --graph --decorate --all`) – ohcibi Sep 20 '17 at 15:59
  • 1
    ohcibi - 126 commits ahead and 136 behind of master How it can be difference only 3 commits? – Alexan Sep 20 '17 at 16:04
  • Did you look at a diff between the three files in each version? – Tim Biegeleisen Sep 20 '17 at 16:07
  • @TimBiegeleisen 3 commits.. not 3 files... ....... – ohcibi Sep 20 '17 at 16:10
  • @Alexan idk why github is showing it like that.. if you clone the repository and look at the graph that git is actually showing you will see that there are only 3 new commits in `ohcibi` since the last merge from `master` into `ohcibi` – ohcibi Sep 20 '17 at 16:12
  • did you do rebase? – Alexan Sep 20 '17 at 16:29
  • Do you mean if I have tried it and if it solves the problem or do you mean if I did a rebase instead of a merge? No (i.e. I tried and it does not solve the problem) and no – ohcibi Sep 20 '17 at 16:30
  • It's a bit more complicated. Does https://github.com/ohcibi/prezto/commit/03ef67fbb1df617198fb7cb393e73754d0e2fda1 (6th in the `ohcibi` branch, just before the "Merge from master" one) included in the difference, by your opinion, in `master`. Answer - it is not (you can see the branches in the link) – max630 Sep 20 '17 at 16:43
  • I mean after rebase the same commits are considered different and it can cause conflicts. – Alexan Sep 20 '17 at 16:44
  • @max630 youre right. I misphrased the question on that regard. – ohcibi Sep 20 '17 at 16:48
  • @max630 I updated the question. Thanks for the hint. – ohcibi Sep 20 '17 at 16:49
  • The key to solving this is viewing the actual commit graph, and finding the merge base commit(s). *GitHub won't show you the graph.* Use `git log --graph` or a graphical viewer like `gitk` or `git-gui` to visualize the graph; use `git merge-base --all` to have Git compute the merge base(s) for you. – torek Sep 20 '17 at 17:32

1 Answers1

5

Git uses three points on the tree in order to merge, your branch's head, the head of the branch you're merging in, and the most recent common ancestor of the two. When in doubt you can run the merge-base plumbing command to find out what commit git sees at the most recent common ancestor.

git merge-base <branch1> <branch2>

Running that command I find the mergebase to be 4f87376b5

It's been just shy of 5 months since you last merged master into your branch. When you merged, master was pointing to a commit made on 2017-04-24. (Which is now the merge-base for your current merge.)

There have been 123 commits made on the master branch since that time, the most recent being made on 2017-09-19. These 123 commits can conflict with the changes in any of the 137 commits on your branch that are unreachable from master.

Git isn't looking at the "number of commits" or when and where they happened. All it's looking at is the cumulative difference between each branch head and the merge base. You can run git diff 4f87376b5 ohcibi and git diff 4f87376b5 origin/master to see the scope of changes being integrated from each side of the merge.

LightBender
  • 4,046
  • 1
  • 15
  • 31
  • Well the problem is a bit more complicated as to be avoided by a simple strict fetch & merge, which I am doing anyways all the time 8-). `4f8737` still doesn't really show the problem but `git show-branch` does as it lists all the diverged commits which is every commit since the first in `ohcibi`. `ohcibi` is meant to be not included into master but `master` should be merged into `ohcibi` from time to time which seems not to work as I expected. – ohcibi Sep 20 '17 at 17:28
  • @ohcibi I misread the date when I was looking the first time, thought it said Aug instead of Apr. So it isn't an out of date issue (I've updated my answer) it's just a situation that there have been a LOT of changes in that time period. – LightBender Sep 20 '17 at 18:01
  • This hasn't anything to do with a LOT of changes either. I found an explanation: The parent repository had been moving around a bit. It was at another place where it diverged because the original maintainer seemed lost. Eventually he came back and decided *not* to merge in the changes from the temporary upstream. I decided to rebase those changes into my `ohcibi` branch when I moved back to the original upstream as the temporary won't be continued. Now I'm doomed to have those merge conflicts whenever upstream adds changes that conflict with those that were made in the temporary upstream. – ohcibi Sep 20 '17 at 19:18
  • @ohcibi That makes sense, but it lands you in the same place, there are a lot of changes made in your branch that conflict with the master branch. incidentally, if you've built your branch off of changes that were rejected by the project maintainer, you're probably better off building a new branch off the updated source of record. This would resolve your problem and avoid any issues with integrating that rejected code into master if your branch is ever accepted. – LightBender Sep 20 '17 at 19:32
  • No it does not land me in the same place as I cannot do anything about it. The commits in the ohcibi branch will never be in the master branch and therefore conflict forever. The ohcibi branch was never meant to contain changes in those files; but as I rebased changes from that temporary upstream into `ohcibi` this isn't anymore the case. My initial idea of this setup is broken because of my rebase which I didn't think of when I did it. I just need to think of something new but this is another issue. – ohcibi Sep 20 '17 at 19:40
  • this isn't a situation where I want to merge in changes from `ohcibi` into upstreams master.. thats why the branches will be diverged forever. `ohcibi` should only contain my local dotfile setup that hasn't anything to do with prezto or even zsh. When I want to contribute to upstream I branch of master, make a PR and then wait for it to be merge or simply merge it directly into `ohcibi` myself... `ohcibi` is allowed to have a messy history – ohcibi Sep 20 '17 at 19:42
  • @ohcibi In that case, your best bet is probably to create a new branch and cherry pick the actual commits you've made onto a new branch based off the updated remote master. That will eliminate those old commits and get you back into a state where you can easily integrate new changes from the remote. – LightBender Sep 20 '17 at 19:46
  • No. The whole problem here is that `ohcibi` now contains commits with changes in upstream files which will of course conflict eventually. My initial idea was to not include those kind of commits to avoid exactly that kind of conflicts (I can remember now). When I did the rebase some years later I forgot about that constraint. But the rebase wasn't by accident either, so there are now two conflicting ideas in my setup. One is the idea to maintain my personal dotfiles in that `ohcibi` branch and the other is to keep both changes from the temporary and the original upstream in my fork. – ohcibi Sep 20 '17 at 19:54