Commits a
, b
and c
are the same (same message, but a different hash, because they're actually a different commit, right?).
Yes: the hash ID is the "true name", as it were, of the commit. (I'm assuming that the patch obtained by running git show
on those commits is the same as those of their duplicates, too, i.e., that it's not just the messages that are the same, but also the delta into which the commit converts.)
When I try to merge dev
into master
, I get loads of conflicts in many files. I really don't [know] why ...
What git merge
does is to (attempt to) combine two sets of changes from a merge base. The merge base is, roughly, "where the branches come together", which in your simplified diagram, would be the commit just below this point:
|/ [origin/master] x
|
since that point is where the lines come together.
Git finds the changes by running git diff
with various options (well, it does an internal diff so there's no actual literal git diff -M50% ...
but you get the same effect if you do this manually):
- compare merge-base commit to commit that is tip of
dev
- compare merge-base commit to commit that is tip of
master
Whatever these two differences show, Git tries to combine them—take their union, more or less, although this term is error prone since "union merge" is a different thing entirely—and apply that to the base to get the final merge result.
You get conflicts if both branch tips make some change(s) to the same file(s) in the base, but the two tips make changes that cannot be combined easily. Git just throws up its metaphorical hands, and says: "I cannot make sense of this. You fix it."
I'm not exactly sure but I believe that's the result of a bad rebase done at that point (that date).
Well, it's certainly possible that it is the result of a rebase. Whether it is a bad rebase is kind of a matter of opinion :-) but what git rebase
does, after all, is to copy commits. Normally, after copying, we all just forget about the originals. That way we don't see both the originals and the copies, and it seems as though Git has magically replaced existing commits, which it hasn't because that's impossible.
Whenever some other branch hangs on to the original commits, though, we see behind the curtain. Over here are the originals, and over there are the copies, and only some branch names point to the new copies.
If you can get everyone to switch over to the new copies, and forget the originals, you're good. Or, you can give up on using copies, and have everyone use the originals; you're good then, except for whatever needs fixing up that the rebase was supposed to handle. But once multiple users have multiple copies of multiple commits, there may be no going back: you may have to fix this by adding merges and getting everyone to pick up the new merges. (It's much easier to convince everyone to pick up new work that just adds on to the existing commit graph, because that's what git fetch
+ git merge
do.)