Strange git behaviour reverting changes made in lo

2019-07-18 04:39发布

问题:

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?

回答1:

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



回答2:

In git, changes don't get reverted automatically; it is very careful not to lose anything. Check for people doing git rebase, git push -f ("so that it works" when their push doesn't work because it isn't a fast forward), or git reset. Any history editing is dangerous. Have them read through some of the tutorials linked at git-scm.

Go over your workflow, compare with the standard git workflows and suggestions (there are several around). Git is a tool, in the best Unix tradition: meant for expert users who know what they are doing. So it keeps out of the way, and doesn't ever try to second-guess the user. That backfires occasionally as long as they are rank newbies, but they learn soon (or give up in frustration ;-).



回答3:

I suspect this could be an editor problem; perhaps the text editor of the developer whose name is on the reverting commits is not loading the changes that have been pulled from upstream, so when he saves, commits and pushes his changes, the text editor ends up overwriting what was brought in from Git. This is made more more plausible by the fact it's only one kind of file that's getting reverted.