How do I get my git merge conflicts back after merging incorrectly?

I’m trying to merge 2 branches that have a lot of changes in them, several with merge conflicts. I merged the files using git mergetool, but I’ve subsequently realized that I merged a couple of them incorrectly. I basically want to go back to the conflicted state for those couple files, so I can re-run the mergetool and correct my errors. I don’t want to throw away my entire merge, since most of it is correct.

I’ve tried resetting to my head and then doing git checkout -m other_branch -- my_file to no avail. I ended up resetting to HEAD, getting the file out of the other branch, and just doing git add --patch on the file, only staging what I wanted. But there must be a better way…

  • Searching for a string in a git repository, across all branches/commits/stashes/etc
  • Git Local Repository All Steps
  • What is the practical difference between `git rm --cached`, `git reset --` and `git reset HEAD` to unstage changes?
  • How can I deploy old commits to Heroku
  • Pruning branches that were deleted in upstream Git repo but still exist in my fork
  • VS Code configuring Git Sync
  • How does Github detect mirrored repositories?
  • Git pull and merge during a merge
  • Make .git directory web inaccessible
  • How do I get back to my earlier commits after fixing a forgotten fork?
  • Clean history : remove delete actions and ignore some files
  • Git hosting with personal namespaces
  • 4 Solutions collect form web for “How do I get my git merge conflicts back after merging incorrectly?”

    First, check out if you have conflicted state in the index (before resetting to HEAD), via

    $ git ls-files --stage --abbrev my_file
    

    You should get something like the following:

    100644 257cc56  1        my_file
    100644 b7d6715 2        my_file
    100644 5716ca5  3        my_file
    

    If you don’t get that, you would have to use git update-index, like Charles Bailey said, or use temporary files. If you have that, then

    $ git checkout -m my_file
    

    should work (I have checked this).

    You can do this with git update-index using either the --cacheinfo or --index-info options to remove the 0 entry in the index for a given file and populating the 1, 2 and 3 entries with the base, local and remote versions respectively but it is going to be fiddly.

    It’s probably going to be easier to extract the various versions to temporary files, and manually run your merge tool, writing the answer to the correct file and adding the result of the successful merge.

    e.g.

    git show $(git merge-base HEAD MERGE_HEAD):file >base-file
    git show HEAD:file >local-file
    git show MERGE_HEAD:file >remote-file
    

    Run mergetool manually, writing to file.

    git add file
    

    You can use:

    git checkout [--ours|--theirs|--merge] <paths>
    

    to checkout the path(s) as found on the branch being merged into or from or to recreate the conflicting merge.

    The git-checkout manpage has a bit more on this issue.

    As Charles Bailey pointed out this does not work when the merged file has already been added to the index. I played around a bit and here is a script that should do the job:

    #!/bin/bash
    #
    # Distributed under the GNU General Public License, version 2.0.
    #
    # git-goat:
    #
    #   Restore a merge conflict, after it has already been resolved.
    
    # Lifted from contrib/completion/git-completion.bash
    __gitdir ()
    {
        if [ -z "${1-}" ]; then
            if [ -n "${__git_dir-}" ]; then
                echo "$__git_dir"
            elif [ -d .git ]; then
                echo .git
            else
                git rev-parse --git-dir 2>/dev/null
            fi
        elif [ -d "$1/.git" ]; then
            echo "$1/.git"
        else
            echo "$1"
        fi
    }
    
    into=$(git describe --all HEAD)
    from=$(cat $(__gitdir)/MERGE_HEAD)
    base=$(git merge-base $into $from)
    
    case "$1" in --ours|--theirs|--merge) whose=$1; shift; esac
    
    [ -z "$1" ] && echo "fatal: at least one file has to be specified" && exit
    
    for file in "$@"
    do
        (
            echo -e "0 0000000000000000000000000000000000000000\t$file"
            git ls-tree $base $file | sed -e "s/\t/ 1\t/"
            git ls-tree $into $file | sed -e "s/\t/ 2\t/"
            git ls-tree $from $file | sed -e "s/\t/ 3\t/"
        ) | git update-index --index-info
        git checkout ${whose:-"--merge"} $file
    done
    

    Note that I haven’t tested this much. If you find any problems or have other improvements here is a forkable “gist”.

    If you accidentally accept say yes to the conflict resolved prompt without saving the changes from mergetool, I think you can just stash the staged changes and redo the merge.

    git stash
    git merge <other branch>
    
    Git Baby is a git and github fan, let's start git clone.