Search code examples
gitgit-push

git push failed with error object hasDotgit: contains '.git'


I wanted to push a git repo to a self hosted gitlab server, and I got the following error:

# git push -u origin --all --no-thin
Enumerating objects: 854410, done.
Counting objects: 100% (854410/854410), done.
Delta compression using up to 4 threads
Compressing objects: 100% (209251/209251), done.
remote: error: object 57364fe6ff4138ec58762676f24a581f5810025a: hasDotgit: contains '.git'
remote: fatal: fsck error in packed object
error: remote unpack failed: index-pack abnormal exit

Use git show to check the object 57364fe6ff4138ec58762676f24a581f5810025a, I got following output:

# git show 57364fe6ff4138ec58762676f24a581f5810025a
tree 57364fe6ff4138ec58762676f24a581f5810025a      
                                               
.clang-format                                      
.editorconfig                                      
.git/                                              
.gitignore                                         
.style.yapf                                        
AUTHORS                                            
LICENSE                                            
OWNERS                                             
README.md                                          
base/                                              
build/                                             
docs/                                              
infra/                                             
out/                                               
tools/                                             
util/           

Does anyone know how to deal with this situation? This is a repo maintained by a team which has thousands of commit after this commit. I can't do git reset on it. I think some expert tools like "git filter-repo" or "git filter-branch" maybe can help me, but I don't know how use them.


Solution

  • You have to find the commits that contain a .git directory, and edit them.


    Finding the commits :

    A starting point is to find the .git directories in your current working directory, then list all commits that modified this directory :

    # from your directory root :
    find . -name .git
    
    # if you find directories other than the root .git directory :
    git log --oneline --graph -- path/to/.git
    

    Editing the commits :

    Basically : if you find a rogue .git folder which has been versioned in your repo, you need to call git rm --cached path/to/.git on the commits that contain it.

    • If this rogue .git directory appeared in your last commit only :

      git rm --cached path/to/.git
      git commit --amend
      
    • If you see a handful of commits in the git log command above : use git rebase -i, set the target commits to "edit", and remove the fawlty directory

    • You can also use a systematic rewriting tool, such as git filter-branch or git filter-repo

      git filter-branch --index-filter 'git rm --cached path/to/.git' --all