Search code examples
gitgithubdvcsgit-workflow

Strange git behaviour reverting changes made in local branches after pulling upstream merges


We have a team of around 10 developers and we are frequently running into a situation where someone's changes got reverted unexpectedly. Our workflow has been very simple. Developers make local commits, pull from upstream, and then push to upstream (this is our workflow in a nutshell, but it may also include issuing pull requests on Github from a developer's personal fork of upstream). The strange behavior is a developer makes local commits, pulls from upstream, and then finds his changes have reverted back. It's as if git is resolving conflicts with theirs strategy although none of us have this setting, nor are there actual merge conflicts involved. The changes are more like this:

Local commit:

.some_style {
-  width: 150px;
+  width: 100px;
  color: black;
}

After merge:

.some_style {
  width: 150px;
  color: black;
}

There are no other commits touching this section of code, and no one is manually resolving merge conflicts (which shouldn't exist anyway). After the developer completes the merge and pushes it upstream, we sometimes see a diff log on another developer's commit that appears to reverse the changes made by the first developer. Usually this revert commit appears under someone else's name, although they have not touched the file in question.

Some other developer's commit:

.some_style {
+  width: 150px;
-  width: 100px;
  color: black;
}

We have no idea how this is happening or how to recreate it. Perhaps our knowledge of git collaboration is lacking in some respect and hopefully someone can point us in the right direction.

EDIT This problem seems to only affect css/scss files. I noticed that the diff headers are showing the wrong information:

@@ -359,10 +367,12 @@ img.badge-pic {

 #sampleProfileCover {
   float: left;
-  width: 200px;
+  width: 230px;
+  height: 150px;
   text-align: center;
   img {
     width: 200px;
+    height: 220px;
   }
 }

Notice that the header identifies this style as img.badge-pic. That style actually appears much earlier in the file. Could git be having trouble parsing css/sass?


Solution

  • This can happen if you do git push --force to send conflicting commits to the server. This can work if the writer of the other conflicting commit then immediately pulls the forced commit and merges it -- he still has his own commit attached and the pull will show the conflict on his side (no one else will notice except when doing fsck -- SOMEONE HAS TO DO the merge. Just pushing it into oblivion is not a solution and abviously git's default settings are not for the average developer! Then the conflicting commit will be pushed aside and dangle around without being attached to the tip or how you call it. You can check that by running git fsck:

    $ git fsck
    Checking object directories: 100% (256/256), done.
    dangling commit 4f851a97274917a1486f81833c6e96c4b1efeabc
    

    You can also prevent your developers from using force. Solution: add the following to your repositories config file:

    [receive]
        denyNonFastForwards = true
    

    See also http://randyfay.com/content/avoiding-git-disasters-gory-story