Home > Mobile >  Unable to git push due to filename casing after merging unrelated histories
Unable to git push due to filename casing after merging unrelated histories

Time:12-07

Trying to combine one repo into another repo while maintaining history using the following rough method:

  • Clone repo to be moved/merged (source) and git mv all files/folders into a subfolder that does not exist in the destination repo
  • Commit and push changes
  • Create a new branch in the repo to be merged into (destination)
  • Add a remote to the source repo: git remote add source-repo <path to remote>
  • git fetch source-repo
  • git merge remotes/source-repo/<branch_to_merge> --allow-unrelated-histories
  • git push

This worked great for several repos but on this one particular repo, I get the following error when trying to do that last push up to origin:

Enumerating objects: 10703, done.
Counting objects: 100% (10703/10703), done.
Delta compression using up to 20 threads
Compressing objects: 100% (3460/3460), done.
Writing objects: 100% (10697/10697), 2.08 GiB | 82.72 MiB/s, done.
Total 10697 (delta 7494), reused 10216 (delta 7135), pack-reused 0
error: remote unpack failed: error The tree object 83f05a173307d3874ab7a304ed3019d2c0af9fe9 was rejected: The file 'datetimeRangeOutput.json' and the file 'dateTimeRangeOutput.json' pushed differ in case. You must remove or rename one of them or disable case-enforcement (see https://aka.ms/git-platform-compat).
remote: Analyzing objects... (6458/10697)
To http://<remote_repo>
 ! [remote rejected]     merge_repos -> merge_repos (The tree object 83f05a173307d3874ab7a304ed3019d2c0af9fe9 was rejected: The file 'datetimeRangeOutput.json' and the file 'dateTimeRangeOutput.json' pushed differ in case. You must remove or rename one of them or disable case-enforcement (see https://aka.ms/git-platform-compat).)
error: failed to push some refs to 'http://<remote_repo>'

Trying git show and git ls-tree shows me the following which clearly does show a file with the same name and blob that differs only in casing:

git show 83f05a173307d3874ab7a304ed3019d2c0af9fe9
tree 83f05a173307d3874ab7a304ed3019d2c0af9fe9

dateTimeRangeOutput.json
datetime.PNG
datetime.rst
datetimeBasic.json
datetimeRangeBasic.json
datetimeRangeOutput.json
datetimeUnboundedRange.json
datetimerange.PNG

git ls-tree 83f05a173307d3874ab7a304ed3019d2c0af9fe9
100644 blob e55dd6082aac6c68c36fcb97fbb58f245c9edecf    dateTimeRangeOutput.json
100644 blob 4a4e321469e9833e88acabec37ad7ee9a7846d24    datetime.PNG
100644 blob 698a530c3a7d072b8f2eb25d919324a54d5b05d3    datetime.rst
100644 blob cbf11401b753506e34a9876cafcb257d946c918b    datetimeBasic.json
100644 blob 430a0be3e61b962db69937af378963d884beedcf    datetimeRangeBasic.json
100644 blob e55dd6082aac6c68c36fcb97fbb58f245c9edecf    datetimeRangeOutput.json
100644 blob e2c834e636d0e3c8781f93ad8bb3ec1a3ded7cb7    datetimeUnboundedRange.json
100644 blob 20ba2ec51c702d9ebeebe67e14e905cfc33fabfb    datetimerange.PNG

I've tried git mv the filename to another name and then back. I've tried git rm on the file (it's like a 2 line file that I can replace later if need be). I don't know where to go from here so that I can get this pushed up to the remote and ultimately merged into development branch.

Update to Maybe Make Clearer

I have tried git rm on the file in the source repo Before adding it as a remote to the destination repo. The repo/filesystem does not have the conflicting file at all in either repo on their respective branches at the time of push and I STILL get the same error.

Note 1: I've tried performing the steps on both Windows and Linux and have had the same results.

Note 2: It's possible that the same file (contents) with the different casing existed somewhere in the destination repo in the past but never at the folder location it exists in this push and it does not currently exist in the branch I'm pushing to at any location.

CodePudding user response:

The error message that you are getting:

error: remote unpack failed: error The tree object
83f05a173307d3874ab7a304ed3019d2c0af9fe9 was rejected:
The file 'datetimeRangeOutput.json' and the file 'dateTimeRangeOutput.json'
pushed differ in case. You must remove or rename one of them
or disable case-enforcement (see https://aka.ms/git-platform-compat).

is not actually from Git. It is from an add-on that Microsoft stuck in on their Azure server.1 Please visit https://aka.ms/git-platform-compat (as the error message advises) for full details on what they're doing.

The error is not specifically due to the use of --allow-unrelated-histories. It is instead due to the snapshot in at least one particular commit:

The tree object 83f05a173307d3874ab7a304ed3019d2c0af9fe9

This refers to some commit(s) (whose hash ID(s) is or are not actually 83f05a173307d3874ab7a304ed3019d2c0af9fe9, which makes the error message relatively low quality; it's probably the merge you made, though). A tree object is how a commit stores a snapshot, so each commit—which stores one snapshot—has one. Multiple commits can share one tree object; that's not terribly common (though easy to arrange) and probably is not the case with this particular repository.

The commit itself, as a result of your merge, contains the two files outlined:

datetimeRangeOutput.json
dateTimeRangeOutput.json

There are two ways to handle this despite the fact that you're using Azure:

  • You can disable the test.

  • You can make your merge commit such that it has only one of these two files.

The latter is the only Git option; the former is an Azure option. (Hence the distinction.)

To achieve the latter, run git merge with the --no-commit option:

git merge <insert any other desired options here> --no-commit <merge-specifier>

Git will perform the merge as usual, but then stop before committing.

Git builds a new commit not from the files in your working tree, but rather from the files in Git's index.2 These files are not stored in your file system's format and Git can therefore store both datetimeRangeOutput.json and dateTimeRangeOutput.json, and in this case, it is doing exactly that. (Use git ls-files --stage to see this.)

You can now pick one of those two files to use and remove the other one, or remove both and insert the correct one, using git rm --cached and/or git add:

git rm --cached datetimeRangeOutput.json dateTimeRangeOutput.json
[edit and/or rename the working tree copy as needed]
git add dateTimeRangeOutput.json    # with whatever case you wanted

Git will make the new commit from what's in its index, and after updating the index appropriately, you can run:

git merge --continue

or:

git commit

(these have the same effect). The snapshot you've prepared in Git's index will now be used to make the new commit. The git merge you ran built a new set of files in Git's index. If there was a conflict, it stopped regardless of your --no-commit option. If not, it stopped only if you said --no-commit (or --squash which implies --no-commit for no good reason). So here, you say --no-commit to force it to stop, so that you can modify the proposed new commit before going on to finish the merge.


1This may be a distinction without a difference as far as you are concerned, but it's useful to some folks, so I make it.

2This thing—Git's index—has three names, for no particularly good reason:

  • The index, which is the name I use above.
  • The staging area, which is where --stage comes from in git ls-files --stage.
  • The cache, which is where --cached comes from in git rm --cached.

Because Git is inconsistent about which one it uses, you'll need to be aware of all three names. While the index takes on an expanded role during conflicted merges, its main role is to hold your proposed next commit. Everything you do in Git, as far as Git is concerned anyway, is really all about updating Git's index so that you can make new commits. Files in your working tree are just useless junk, except for when you git add them to copy them into Git's index.

  •  Tags:  
  • git
  • Related