Reputation: 3198
Several months ago, we migrated a bunch of Subversion repositories to Git using svn-all-fast-export. (That information explains how this directory got in the Git directory in the first place, but probably isn't pertinent to removing it.) Today, one of our developers attempted to git checkout
an old branch of one of those repositories, only to be confronted with an error:
$ git checkout 2.3.4
error: invalid path 'MPC/.git/HEAD'
error: invalid path 'MPC/.git/config'
error: invalid path 'MPC/.git/description'
error: invalid path 'MPC/.git/hooks/applypatch-msg.sample'
...
error: invalid path 'MPC/.git/packed-refs'
error: invalid path 'MPC/.git/shallow'
$
A quick bit of sleuthing in our archived Subversion repository revealed that someone had committed a .git
directory (surely by mistake) to the MPC
directory years ago. They deleted it in the next branch. When the repository and its branches and commit history were migrated, that .git
directory got written to the Git tree, essentially "breaking" this branch. No big deal, right? Just delete the directory! Well ... how?
I can't check out the branch, so I can't simply git rm
. I tried git clone --single-branch --branch 2.3.4
but, no surprise here, I got the same error. Exactly what I was expecting. So I cloned with git --sparse
, but to my surprise, that still didn't work. The default sparse patterns:
/*
!/*/
Should mean that only the top-level files get checked out, but not anything under MPC
. However, when I try to check out the branch, I still get the same errors about that .git
directory, and the top-level of the working copy is completely empty. I've tried adding specific excludes such as !.git
, !\.git
, !.git/
, !\.git/
!MCP
, !/MPC
, !/MPC/.git
, !/MPC/\.git
, !/MPC/.git/
, !/MPC/\.git/
!/*/.git
, !/*/\.git
, !/*/.git/
, and !/*/\.git/
, and even more than that, but every pattern I try just gives me this error:
warning: unrecognized pattern: [the pattern I tried]
warning: disabling cone pattern matching
error: invalid path 'MPC/.git/HEAD'
...
Or:
warning: unrecognized negative pattern: [the pattern I tried]
warning: disabling cone pattern matching
error: invalid path 'MPC/.git/HEAD'
...
I do wonder if some combination of git mktree
, git write-tree
, and/or git commit-tree
can help me here, but I don't even know where to start with those commands.
To be clear ... if this becomes a show-stopper issue for my team and I can't find an easier solution, I will archive all new commits to this repo, re-migrate it, and re-apply all new commits. But I don't want to do that if I don't absolutely have to. That's days of time down the drain. There's gotta be a way to delete this ... right?
Upvotes: 1
Views: 106
Reputation: 489708
Unfortunately, no existing commit can ever be changed. Fixing this means rewriting history, e.g., using git filter-repo
(the newfangled thing that replaces the oldfangled git filter-branch
).
There's a pretty high (and clear) cost to this kind of history rewrite: everyone has to abandon the original repository, and all of its clones, in favor of the new rewritten repository. So if you can live with the bad commit continuing to exist, you might want to do that. On the other hand, the "fix the repository" thing is a one-time flag-day.
You can clone the repository without checking out the "bad" commit, then make a new "good" commit that's basically the bad commit minus the .git
directory, with the parent being the "bad" commit at the tip of the old branch, and make the branch name select the new good commit. Actually achieving the new good commit is a bit of an exercise in frustration since you'll need to extract the bad commit without extracting the bad commit. I'd poke around with git archive
and maybe even git fast-export
here, and if all else fails, build a hacked up Git that has the "bad directory .git
" checking snipped out, so that you can run hacked-git checkout
to check out the bad commit, then git rm -r MPC/.git
and git commit
(or hacked-git
if/as needed for the git rm
step, depending on whether the code triggers here).
Upvotes: 1