Git: unable to create symlink (File name too long)
I had pushed a project from linux to bitbucked and then cloned it on windows. Turns out there were two symlinks, which appeared as textfiles on windows. Since I knew where they should point to, I replaced them by copies of their destination files, committed and pushed.
Now the butbucket repository looks okay when I look it it from their web interface. However a git clone on my unix machine gives me two messages like:
error: unable to create symlink ... (File name too long)
and the two files, which were symlinks previously are absent. I tried cloning into /tmp/... to get shorter filenames, but got the same results. That suggests, that something went bad with the bitbucket repository. I tried core.symlinks
on and off.
I can live without the symlinks, but I'd like to have a working repository. Does anybody know a way (other than recreating the repository)?
As soon as you changed the content of a fake-symlink-file without also changing its mode from symlink to regular file and committed the result, you made a blob that can't be extracted on an OS with real symlinks, because you have an object that is supposed to be a symlink but its content is too long to be a pathname. The web interface is not doing you any favors by hiding this problem.
You're probably going to have to back up to that commit, fix it, and re-commit everything after it. git rebase -i
will help, but it still might not be easy, especially if you've made more changes to the files while they were in this bogus symlink-but-not-really-a-symlink state.
Supposing that the bad commit is abcdef123
, you need to do this:
git rebase -i 'abcdef123^'
which will put you in an editor with a list of commits. abcdef123
should be on the first line. On that line, change pick
to edit
. If there is more than one bad commit, change all of them to edit
. Save and exit the editor.
Now you'll be back in the point in time where you committed the bad file. This is your chance to alter history, putting things right that once went wrong. Inspect the commit with
git show
and undo the bad part by restoring the original symlink pathname into the file and git add
ing it. Or you could really get rid of the symlink properly with git rm
, then create a new file and git add
that. If you choose the first option, be aware that the content of a symlink is just a pathname. It's not a text file - it doesn't have a newline on the end. If you edit it with a text editor that adds a newline, you'll have a broken symlink (pointing to a file with a newline in its name).
After you've done your git add
, reinsert the fixed commit into its place in history:
git commit --amend
git rebase --continue
If you changed multiple commits from pick
to edit
you'll have to repeat that procedure for each one. The final git rebase --continue
will bring you back to the present.
If you are at a past commit during the rebase and you discover that the whole commit is bad (it did nothing else besides replacing a symlink with the unmodified content of the file it points to), then you can git rebase --skip
instead of amending and continuing. If you know ahead of time that this is going to happen, you can just delete the bad commit from the git rebase -i
list instead of changing its pick
to edit
.
If you have multiple branches affected by the bad commit(s), you will have to repeat the whole procedure for each branch. Check out a branch, run the git rebase -i
to completion (which is when git rebase --continue
says "Successfully rebased"), then check out the next branch and do it again.
In the future, when splitting your development work between Windows and a real OS, do your Windows work with cygwin. Inside cygwin, symlinks are symlinks and you can't mess them up like you did.
Here's a solution that doesn't require you to go back and fix commits. After all it may not be feasible if the repo is remote or shared. It uses core.symlinks=false. You said you tried this but did not say when. You must do it before a checkout, which a normal clone does by default. So you must clone with the --no-checkout option.
git clone --no-checkout the-repo tmp-clone-dir
cd tmp-clone-dir
git config core.symlinks false
git checkout
cp the-problem-file the-problem-file.bak # make a backup
git rm the-problem-file
git commit -m 'Removed problem file pretending to be a symlink' the-problem-file
mv the-problem-file.bak the-problem-file # restore the backup; now it will be of type file
git commit -m 'Added back the problem file - now with the correct type' the-problem-file
git push origin master
cd ..
rm -rf tmp-clone-dir # IMPORTANT
That last step is important because you don't want to do more work in a repo with core.symlinks=false. It's just asking for trouble.
The above assumes that you want the file to be a file not a symlink. If it was meant to be a symlink then you'd stop after the first commit, remove the tmp-clone-dir and go back to your normal repo checkout to make the symlink and commit it.
The benefit in this method is that you don't break any related clones and branches as it preserves history. The downside to this is that the broken commit is still there and will cause problems for anyone if they attempt to use that particular bad commit.
我有这个问题,这解决了它对我来说:
git config core.symlinks false
git rm <problem-file>
git commit <problem-file>
git push
git config core.symlinks true
链接地址: http://www.djcxy.com/p/78112.html
下一篇: Git:无法创建符号链接(文件名太长)