18

First I merge sth, then conflicts occurs, so I git merge --abort, but failed, I have to do git status first, then git merge --abort succeeded.

$ git merge features/test
Auto-merging src/cmd.c
CONFLICT (content): Merge conflict in src/main.c
Auto-merging src/client.c
Automatic merge failed; fix conflicts and then commit the result.
$ git merge --abort
error: Entry 'src/option.h' not uptodate. Cannot merge.
fatal: Could not reset index file to revision 'HEAD'.
$ git merge --abort
error: Entry 'src/option.h' not uptodate. Cannot merge.
fatal: Could not reset index file to revision 'HEAD'.
$ git status 
# On branch te
# You have unmerged paths.
#   (fix conflicts and run "git commit")
#
# Changes to be committed:
#
**********
#
# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#
**********
#
$ git merge --abort
$ git status
# On branch te
nothing to commit, working directory clean

Is anything I'm doing wrong?

git version 1.8.3.1

1
  • git version 2.21.0 (Apple Git-122.2) I had that problem as well, git status also is the workaround
    – bshirley
    Commented Jan 29, 2020 at 20:14

6 Answers 6

9

First, we need to run

git status

then

git merge --abort
5

Running this will lose any changes that have not been committed!

git reset head

git checkout -- .

Read more on how git reset head functions here

4

Not sure if we had the same issue, but for me, when i ran git status, it revealed that I had 2 files with the message "Changes not staged for commit:"

I wanted to role back the entire merge, so I decided to discard those two file changes by using git restore. Then I was able to abort the merge.

TLDR:

git restore path/name/of/file/to/restore

git merge --abort
3

Is anything I'm doing wrong?

No: the git merge --abort should have worked, without having to run git status first. Report a bug for whichever Git version you are using. Edit: 1.8.3.1 is positively ancient. You should upgrade if possible.

0
3

Note: even upgrading Git might not be enough, not until Git 2.19 (Q3 2018), since "git merge --abort" etc. did not clean things up properly when there were conflicted entries in the index in certain order that are involved in D/F conflicts.
This has been corrected with Git 2.19.

See commit ad37620, commit 25c200a (31 Jul 2018) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster -- in commit 8ba8642, 17 Aug 2018)

read-cache: fix directory/file conflict handling in read_index_unmerged()

read_index_unmerged() has two intended purposes:

  • return 1 if there are any unmerged entries, 0 otherwise
  • drops any higher-stage entries down to stage #0

There are several callers of read_index_unmerged() that check the return value to see if it is non-zero, all of which then die() if that condition is met.

For these callers, dropping higher-stage entries down to stage #0 is a waste of resources, and returning immediately on first unmerged entry would be better.
But it's probably only a very minor difference and isn't the focus of this series.

The remaining callers ignore the return value and call this function for the side effect of dropping higher-stage entries down to stage #0.
As mentioned in commit e11d7b5 ("'reset --merge': fix unmerged case", 2009-12-31, Git 1.7.0),

The only reason we want to keep a previously unmerged entry in the index at stage #0 is so that we don't forget the fact that we have corresponding file in the work tree in order to be able to remove it when the tree we are resetting to does not have the path.

In fact, prior to commit d1a43f2 ("reset --hard/read-tree --reset -u: remove unmerged new paths", 2008-10-15, Git 1.6.0.4), read_index_unmerged() did just remove unmerged entries from the cache immediately but that had the unwanted effect of leaving around new untracked files in the tree from aborted merges.

So, that's the intended purpose of this function.

The problem is that when directory/files conflicts are present, trying to add the file to the index at stage 0 fails (because there is still a directory in the way), and the function returns early with a -1 return code to signify the error.

As noted above, none of the callers who want the drop-to-stage-0 behavior check the return status, though, so this means all remaining unmerged entries remain in the index and the callers proceed assuming otherwise.

Users then see errors of the form:

error: 'DIR-OR-FILE' appears as both a file and as a directory
error: DIR-OR-FILE: cannot drop to stage #0

and potentially also messages about other unmerged entries which came lexicographically later than whatever pathname was both a file and a directory. Google finds a few hits searching for those messages, suggesting there were probably a couple people who hit this besides me.
Luckily, calling git reset --hard multiple times would workaround this bug.

Since the whole purpose here is to just put the entry temporarily into the index so that any associated file in the working copy can be removed, we can just skip the DFCHECK and allow both the file and directory to appear in the index.
The temporary simultaneous appearance of the directory and file entries in the index will be removed by the callers by calling unpack_trees(), which excludes these unmerged entries marked with CE_CONFLICTED flag from the resulting index, before they attempt to write the index anywhere.


In case of problem, git fsck can help:
Before Git 2.28 (Q3 2020), the check in "git fsck" to ensure that the tree objects are sorted still had corner cases it missed unsorted entries.

See commit fe74704, commit 3d71b1c, commit fc12aa7, commit 8671559 (21 May 2020) by René Scharfe (rscharfe).
(Merged by Junio C Hamano -- gitster -- in commit 7e75aeb, 09 Jun 2020)

fsck: detect more in-tree d/f conflicts

Signed-off-by: René Scharfe

(D/F: Directories/Files)

If the conflict candidate file name from the top of the stack is not a prefix of the current candiate directory then we can discard it as no matching directory can come up later.

But we are not done checking the candidate directory -- the stack might still hold a matching file name, so stay in the loop and check the next candidate file name.

2
  • I encountered the error in git version 2.21.0 (Apple Git-122.2)
    – bshirley
    Commented Jan 29, 2020 at 20:14
  • @bshirley Strange. That would merit to be studied in its own separate question, to see if this error is really from the same scenario. Also, would it persist with Git 2.25?
    – VonC
    Commented Jan 29, 2020 at 22:24
1

In my case, git status didn't help, but after committing local changes it was then willing to abort.

My git version: v2.25.0.windows.1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.