A colleague, whom we'll call Aaron, was assigned to renovate a section of a website as a long-term project. He created a new Git branch, called aaron
. All his changes were made on this branch. While he was working, I continued to maintain the site as a whole, committing my changes to master
.
Eventually, Aaron merged his branch into master
. This somehow reverted all of the commits I'd made to master
between the time of the merge and the time when the aaron
branch was first created. If I type git show <hash of merge commit>
, I can see diffs for every file I changed while Aaron was working on his branch. Those diffs show a reversion of every change I made. It looks the way it would if Aaron had manually copied the contents of each file on his branch into master
and committed the changes. (He didn't do this. I'm just trying to illustrate what the log is showing.)
According to Aaron, he didn't do anything weird. He says he just ran git pull origin/aaron
.
What could have caused this? Is it possible that git pull origin aaron
would have reverted all my changes to master
?
Also, is there an easy way to reinstate my changes to master without reverting all of his work?
EDIT 1:
One of the files that was changed in master
and then reverted after merge was foo.txt
. So I did this:
git checkout aaron
git log foo.txt
The log does not reflect any changes to foo.txt
after the moment the aaron
branch was created. I was sort of expecting to see a reversion of my changes somewhere in the log for the aaron
branch, but I didn't. So, is this final proof that Aaron did something other than the simple pull that he claims to have done?
EDIT 2:
I had said he typed origin/aaron
, but he actually typed origin aaron
. I've changed it above.
EDIT 3
As per suggestions below, I chose to solve this by rewriting history. I am at this point convinced that the problem was caused by a misguided attempt to resolve conflicts.
The only way for git pull origin/aaron
to do this is if he had a merge from master
into aaron
first, that discarded all of the changes on master
(perhaps by using git merge -s ours master
).
Go check the history. Are there any previous merges from master
into aaron
? And do they discard master
's changes? If there are none, then the only explanation is he did not run git pull origin/aaron
.
As for reinstating the changes, you could just back out his merge and re-create it yourself. That's going to modify history, but if you're ok with that, it's the easiest solution. If you're not ok with that, then it gets slightly more complicated. In that case, you'll want to create a temporary branch, back out his merge, and re-merge correctly. Then go back to master and run git read-tree tempbranch
. This will update your index with the results of your temporary correct merge[1], and you can then commit this.
[1]: Note, this won't modify your working tree, so you'll want to follow this up with something like git checkout -- .
.
Given that all the changes occurred in the merge commit you're seeing what's known as an evil merge. man gitglossary
defines it this way:
evil merge
An evil merge is a merge that introduces changes that do not appear in any
parent.
There's an explanation of what this means in this answer. The important thing to know for you is that this isn't something that git will do by itself. Creating an evil merge requires human intervention in some way.
Where I've typically seen it happen is when someone does a merge and gets confused because of conflicts. For instance, one thing that could potentially have caused this is if aaron started his pull, got overwhelmed by conflicts, and decided that it was safe to solve the conflicts by copying his file(s) over top of the existing file(s). When he makes the merge commit after doing this you'll see exactly this.
As far as fixing it, I would do what Kevin Ballard suggested if you can. git -reset --hard
the master branch back to how it looked before the merge and then redo the merge.
来源:https://stackoverflow.com/questions/14388968/git-pull-reverted-commits-in-master