0

What does it mean when you have, on a branch (master, in this case), a list of duplicated commits (exact as the dev branch), but with a different date, but the same date?

The SourceTree graph looks like this (overly simplified):

| [master] e 
| d
| c
| b
| a
|| [dev] c
|| [origin/dev] b
|| a
|/ [origin/master] x
|

Commits a, b and c are the same (same message, but a different hash, because they're actually a different commit, right?). There are a couple of new commits though (d, e), on top of the master branch. And from a to e in master, they have the same date.

I'm not exactly sure but I believe that's the result of a bad rebase done at that point (that date).

When I try to merge dev into master, I get loads of conflicts in many files. I really don't why, but I shouldn't get any, all I was trying to do was to tidy up the repo, delete some branches (I actually deleted a branch that might have had some commits on it and now they only live on this bad rebase, the d and e ones, but I'm not sure) and have master and dev branch match each other locally and in the origin.

How to fix this situation? What is going on exactly?

I've been trying to fix this with SourceTree but also the command line, but whatever I try I always keep coming back to the same situation described above.

zok
  • 6,065
  • 10
  • 43
  • 65
  • 1
    If the tree in the post reflects precisely what you have, you only have one commit on the branch you want to merge back. If so, create a new branch from the master, and make a `git chery pick` to grab that commit alone. That is what I would do – Leonardo Alves Machado Sep 18 '17 at 16:50
  • Thanks, but not sure what you mean - a, b and c in my example are actually 70 commits, and d and e just 5. I'd rather wipe out all these duplicated (and new ones) commits from master, merge master into dev, and redo some work. This mess hasn't been pushed to remote. – zok Sep 19 '17 at 09:08

1 Answers1

1

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.)

torek
  • 448,244
  • 59
  • 642
  • 775
  • Thanks, that's very helpful. The duplicated commit string (represented as a, b, c in my example) is actually huge (about 70 commits) so I'm trying to get rid of them. [this](http://www.kodama.gr/2013/07/28/using-git-rebase-to-remove-duplicate-cherry-picked-commits/) looks like my situation but if I rebase master from dev I get a massive load of conflicts - and it doesn't make sense to solve them because 99,9% of the code on this project I've written myself alone. I'm trying to make sense of `reflog` right now but I'd like to just wipe out all duplicated commits from master and redo some work – zok Sep 19 '17 at 09:03
  • It seems the best thing I could do now is delete all duplicated (and new ones) commits from master, merge master into dev, and redo some work. This mess hasn't been pushed to remote. – zok Sep 19 '17 at 09:09
  • Forgot to mention but I actually just need to have `master` and `dev` in sync pointing to my last commit on master, and would rather keep my tree clean of duplicates and commits with the same date. That's really all I need – zok Sep 19 '17 at 09:31
  • Ah, the "not yet pushed" always makes things nicer. Just the sheer number of commits, and the fact that their hash IDs all look random, still makes for a hairy job. – torek Sep 19 '17 at 14:58
  • Yes! I actually solved it by cherry picking the 5 new commits into dev and applying a hard reset in master to the common ancestor. :) – zok Sep 19 '17 at 15:16