0

I recently encountered a really puzzling problem with Git when merging 2 branch. The problem arose when the auto-merge tried to merge 2 files that contents "mostly" whitespace insert INSIDE a line. For exemple, look at this file after a git merge (or git rebase) :

<<<<<<< f03b9ee0db23cbe39ff231d8fcc3b37bac20cc3d¬                                                                                     
1   public static function findTopParent($tid, $domaine_tree) {¬                   
2 =======¬                                                                         
3   public static function findTopParent($tid,$domaine_tree) {¬                    
4 >>>>>>> Version 8 - last extraction¬ 

(Notice the space after $tid,) The purpose of this "light" edit was only to play nice with Drupal coding convention (asking to leave a whitespace after coma in function parameters).

I should add that this was one case where merge left revision mark. But there's many cases where the auto-merge does is work without errors but do an awful job at merging files with a chunk of code on top (without space inside) and a chunk of code below (with space)

But having running my usual git merge without much warning or errors, my site stop to work with all kind of function redefinitions errors. Opening the files, I saw chunks of code get repeated all over the place, original code above and the "new" code with whitespaced coma in functions below. So what the hell????? How come simple modification like this is interpreted by Git like a new line or even worse new chunks of code??

I maded thoses changes all over the place for a couples of days and now I having a really bad time re-merging with my main branch. And now, I'm kind of scared to do this kind of "small" change to my files in fear of creating bizarre bugs hiding in replicating code. I check git merge doc but only find whitespace problems related to space at end of line, beginning of line (instead of tabs) or whitespace use for tabbing (core.whitespace). But nothing about problem with space added INSIDE. :-( Need some fresh eyes on this!

EDIT:

To be clear and easier to understand here one extract from a real file, before and after.

In master before the merge:

// Menu Link MLID des pages HUB (statiques) du main-menu
// Requête BD : SELECT * FROM menu_links where plid = 999
// 726 = Loi et Réglements
// 728 = Aide financière de dernier recours
define ('LOI_AIDE_PAGE_MLID',934);
define ('REGLEMENT_PAGE_MLID',935);
define ('AFDR_PAGE_MLID',894);

// Taxonomy VID
define ('DOMAINE_VID',3);

In feature before merge (notice the added space after coma):

// Menu Link MLID des pages HUB (statiques) du main-menu
// Requête BD : SELECT * FROM menu_links where plid = 999
// 726 = Loi et Réglements
// 728 = Aide financière de dernier recours
define ('LOI_AIDE_PAGE_MLID', 934);
define ('REGLEMENT_PAGE_MLID', 935);
define ('AFDR_PAGE_MLID', 894);

// Taxonomy VID
define ('DOMAINE_VID', 3);

Then, on feature branch:

git commit "blablabla"
git pull --rebase origin master (no message, everythings look cool)
git checkout master
git merge feature (fast-forward, no message)
...
run the site... error duplicate constant !?!?

open files and now this!?!

// Menu Link MLID des pages HUB (statiques) du main-menu
// Requête BD : SELECT * FROM menu_links where plid = 999
// 726 = Loi et Réglements
// 728 = Aide financière de dernier recours
define ('LOI_AIDE_PAGE_MLID',934);
define ('REGLEMENT_PAGE_MLID',935);
define ('AFDR_PAGE_MLID',894);

// Taxonomy VID
define ('DOMAINE_VID',3);

// Menu Link MLID des pages HUB (statiques) du main-menu
// Requête BD : SELECT * FROM menu_links where plid = 999
// 726 = Loi et Réglements
// 728 = Aide financière de dernier recours
define ('LOI_AIDE_PAGE_MLID', 934);
define ('REGLEMENT_PAGE_MLID', 935);
define ('AFDR_PAGE_MLID', 894);

// Taxonomy VID
define ('DOMAINE_VID', 3);

And also found file with revision mark but the change is also only ONE whitespace difference.

Steve S.
  • 521
  • 9
  • 30
  • 1
    Please give us some git commands you have maded to get into this state. – Alexander Pogrebnyak Jan 30 '16 at 01:17
  • Sitting on master, git checkout -b feature, work work work (add whitespace inside line), git checkout master, git merge feature. Look at files, uh? auto-merge is wrong! – Steve S. Jan 30 '16 at 01:28
  • Are there any other commits on master between feature fork point and merge point? – Alexander Pogrebnyak Jan 30 '16 at 01:37
  • In the case where I discover the "bug", there was maybe 20 commits max. I also add that there is no issue about cr-lf. I check the file also for encoding and everything was unix/utf-8 files. – Steve S. Jan 30 '16 at 01:47
  • Possible duplicate of [Git merge left HEAD marks in my files](http://stackoverflow.com/questions/10657315/git-merge-left-head-marks-in-my-files) – Schwern Jan 30 '16 at 01:55
  • "*my site stop to work with all kind of function redefinitions errors*" If you're doing work and merges on your production machine... now you know why you shouldn't. – Schwern Jan 30 '16 at 01:56
  • Hopefully, I was still on my dev branch. I should add some details to my workflow. We usually create a feature branch and work on this of couples of day and then merge back to master by doing : First before merging back, doing a git pull --rebase origin master and see if any conflict occured. No problem there. Then going back to master and merging (fast-forward) the feature branch ( git merge feature, git push). The merge have show some errors (like the exemple over) AND some merge going un-notice because auto-merge simply put chunck of code below original code. – Steve S. Jan 30 '16 at 02:05
  • @SteveS. Are you *SURE* you only ran `git merge feature; git push`? You sure it wasn't `git merge feature; git commit -a; git push`? It's hard to know what state you're in without knowing what commands got run. If you add *all* of the commands you ran, and their results, to the question we could help you better. Also, are you using some sort of merge tool? – Schwern Jan 30 '16 at 02:13
  • No special merge tool. And no commit between a merge and a push. – Steve S. Jan 30 '16 at 02:25
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/102050/discussion-between-schwern-and-steve-s). – Schwern Jan 30 '16 at 02:28

1 Answers1

1

You have a merge conflict. This is normal and will happen from time to time. That's when two branches changed the same line (or neighboring lines) so the computer doesn't know which one to use. Even something as small as a whitespace change will trigger this.

You say you did something like this:

git checkout -b feature
...work commit work commit...
git checkout master
git merge feature

But that can't result in a merge conflict because master never changed. I think you did this...

git checkout -b feature
...make some commits on feature...
git checkout master
...make some commits on master (or maybe a pull)...
git checkout feature
...make some more commits on feature...
git checkout master
git merge feature

Normally when you merge Git does it automatically and commits the change. This time the auto-merge failed and you're in a merge conflict. No commit has happened. Git has done the best it can to edit and add the code and then thrown up its hands saying "help, I need a human!" and left you to deal with the rest.

Now it's your job to finish the commit. This is basically the same as making any other commit. Git has already added all the files it successfully merged. The rest are changed but unstaged. It's your job to fix the unstaged files, add them, and commit.

The unstaged files will have conflict markers showing you what lines are in conflict between the two branches. That's this.

<<<<<<< f03b9ee0db23cbe39ff231d8fcc3b37bac20cc3d¬                                                                                     
1   public static function findTopParent($tid, $domaine_tree) {¬                   
2 =======¬                                                                      
3   public static function findTopParent($tid,$domaine_tree) {¬                    
4 >>>>>>> Version 8 - last extraction¬ 

You have to decide which version of that line you're going to choose, or you can rewrite the line entirely. The first one is from commit f03b9ee0, the second is from the branch Version 8. Just delete all the conflict marker stuff and the version of the line you don't want. Or write a new line.

public static function findTopParent($tid, $domaine_tree) {

There's no magic here, you're just editing the file like normal. The result should be the code you want to commit.

After you've done that for all conflicts in the file, git add the file.

Repeat until there's no more conflicted files and everything is added. Then commit.

You can read more about merge conflicts in the Pro Git. And here's another question covering resolving conflicts in Git.

Community
  • 1
  • 1
Schwern
  • 153,029
  • 25
  • 195
  • 336
  • I mention above that before doing my merge of feature back to master, I'm doing a git pull --rebase origin master, the merge fast-forward. The pattern that create chunk of code (one with space and the other without) go un-notice by auto-merge. – Steve S. Jan 30 '16 at 02:08
  • @SteveS. You didn't mention the pull earlier, that's what introduced the conflicting change in master (though not the conflict itself). I don't know what you mean by "*The pattern that create chunk of code (one with space and the other without) go un-notice by auto-merge.*" Your auto-merge attempt resulted in a conflict. Unless you ran `git commit` after the merge you should have staged and unstaged changes left over. Run a `git status` to find out. – Schwern Jan 30 '16 at 02:10
  • Added more info in the description. It's not a problem with unstaged changes. – Steve S. Jan 30 '16 at 02:24