Git: how to revert after a merge conflict corruption

22,376

Solution 1

Your two problems can be solved in the same way:

git checkout HEAD my/filename.js

Where HEAD is literal (git shorthand for current branch name) and my/filename.js should be replaced by the actual filename of your file. This will restore your file to how it was before the update, effectively "undoing" the changes from the other person. Commit this result locally and then push as normal (no --force should be necessary if you when you have updated from the central repo)

In general, the way to resolve a merge conflict is to edit your file until it's the way you want it, and then run git add. The reason git (and svn for that matter) leave the "<<<" and ">>>" results in your file after a failed merge or update is to help you or your tools to resolve the merge. Setting up a tool to help you do this will probably be worth it, but it's a shame it doesn't come out of the box.

By the way, your initial instinct from SVN to replace the unwanted file with your known good one would work just fine with one additional step: after deleting the file, restoring the good one and running git add my/filename.js. In this case checkout will also add it to the index (double-check with a git status), so you can immediately commit (locally) and then push the (now resolved) merge conflict back to the central repository.

Solution 2

You probably just want to revert the other persons commit. It is important with git that you don't run a pull if you have uncommitted local changes. If you do you can end with a merge that is very difficult to back out of.

git merge --abort

will abort the merge you have started by pulling others changes into your code. This may recover the unchecked in changes you had before you started the pull. If you have large changes in the file then take a backup somewhere else and hand merge them afterwards if it doesn't work.

run

git log --stat

and find the commit which changed your file. run

git revert <commit id>

where is the id of then commit changing your file. This will make a commit which rolls the other's commit back, push that change. If the other person had other things in the commit then they can rework their patch by reverting your revert and editing the commit to remove the changes in your file and then pushing the change again.

In the future never have unchecked-in changes when you pull, it causes trouble.

You could also consider a commit hook on the server which stops people other than you committing to that file in the future.

Solution 3

To completly drop the foreign changes in a merge conflict, you can use

git checkout --ours -- <path-to-file> && git add <path-to-file>

This resolves the conflict with the specific file using your version. The add is necessary to tell git that the conflict is resolved.

Share:
22,376

Related videos on Youtube

John Little
Author by

John Little

[email protected]

Updated on July 22, 2022

Comments

  • John Little
    John Little 5 months

    OK, as a SVN and CVS expert of 20 years, I am finding git very challenging. I have read lots of guides, not found one which is comprehensible. Many apologies for my stupidity with git.

    We only use master, no branches. Git was forced on us.

    I have a js file which I "own" noone else should be touching it. But someone did, and checked it in. I tried to checkin my copy, and fails. So I pull the updated version, which "corrupts" my copy with a lot of <<< and >>> entries.

    Basically, I wanted to reject all his changes, and overwrite them with mine. with SVN, I would simply make a copy of my local js file, delete it, checkout from the repo to get the offending one, copy my copy back, then check the result in. Really simple.

    I haven't found a way to do this in git, as if you delete the file, it thinks you want to delete it.

    So I tried editing the merged file, but got mixed up which lines are the new and which the old. So now the file is unusable. i have "lost" my local copy.

    I read about this: "git push origin master --force" but:

    1. its too late, I've already lost my version.
    2. i read another post which says never do this as it breaks people's pulls, but they don't offer an alternative "correct" way reject someones checkin,, and replace one file with your own.

    So I assume I have to go back to a previous local commit to recover that one file. The only way I can find to do this is "git checkout [revision] .". But if I do that, I'm not on master any more, and don't know how to get back to it. Also, I expect it wont let me, because I edited and saved the problem file so it wont let me checkout a prev. version. I assume I would have to commit the broken file, then try and go back two commits, backup the file, then in a new directory checkout master again, overwrite the file, then check this in.

    So I have two problems:

    1. how to get my file back.
    2. once I have it back, how do I overwrite the file someone else checked in with my own, without affecting the other stuff they checked in & pushed?
  • John Little
    John Little almost 9 years
    This makes sense, thanks. Unfortunately, I have broken it further. I read that the way to get a file back was to revert, which I did with tortoise Git. now I have my file back. But it "broke" the other files which the person checked in which were not in conflict. When I do a git status, it says "your branch and origin/master have diverged (whatever that means), and y have 1 and 19 commits each". Then it says "changes to be commited: and lists the two files which I got from the Pull which were ok - i.e. It wants to commit some weird version of those files which I have not changed.
  • John Little
    John Little almost 9 years
    Git pull says "you have not concluded your merge", and git commit says 1) that the file I fixed is still in conflict, 2) that the files I didnt touch are locally modified, when they are not.
  • John Little
    John Little almost 9 years
    I would add that in SVN, having got this screwed, I would simply delete my directory, check the entire thing out from scratch, and try and manually put my changes back in. Git is not that easy as there is a local database somewhere.
  • user3033893
    user3033893 almost 9 years
    Ohh... Revert is particularly tricky because it means something completely different between SVN and git. With SVN, revert throws away local changes to restore a clean checkout. With git, revert creates a new commit that "reverses" all changes from a previous commit. That is why it "broke" the other files which the other person checked in. When you accidentally revert something in git and push it, the only way to fix it is to revert the revert, which creates yet ANOTHER commit that "reverses" the previous one. (yuck) If you haven't pushed it yet, there are other ways to fix it.
  • user3033893
    user3033893 almost 9 years
    A file will remain "in conflict" until you run git add on it. You should not run git add on it until you have actually resolved all the conflicts (removed the '<<<' and '>>>' lines). One way of resolving it was the checkout command I gave initially. The files that you didn't touch are probably the updates from the central repo that didn't have any conflicts.
  • user3033893
    user3033893 almost 9 years
    Additionally, you CAN delete your directory and re-clone from the central repository. The things that are stored in the local database (the hidden .git directory at the root of the source tree) that would be lost by doing this are any branches and commits that you have made locally but not yet pushed. Since you mentioned that you only work on master (no feature branches, etc) you would only lose local unsaved changes. And possibly some personal settings in the .git/config file (aliases, for example).
  • John Little
    John Little almost 9 years
    Is that how you resolve a conflict - you have to add after? Very useful, thanks

Related