1

I accidentally added a huge file to my repo (~250 MB) with the name --exclude. This file was generated on OS X while I was writing some new code for this repo. Now, I was trying to learn how to delete it from Git's history from here and here. The tutorials are nice and clear, but the problem is that Git "thinks" --exclude is not a file but an option.

When I run this command:

git filter-branch \
    --index-filter "git rm -r --cached --ignore-unmatch '--exclude' " HEAD

Git complains:

error: unknown option `exclude'
usage: git rm [<options>] [--] <file>...

I tried to use file's sha number but it changed nothing.What is the correct way to delete such a files?

Community
  • 1
  • 1
Michael IV
  • 11,016
  • 12
  • 92
  • 223

3 Answers3

3

Try at least to separate the git rm options from the file parameters, using a '--' (double-hyphen)

 git filter-branch --index-filter "git rm -r --cached --ignore-unmatch -- '--exclude' " HEAD
                                                                       ^^
                                                                 (double-hyphen)

See more on the double hyphen syntax in "Deleting a badly named git branch".

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
3

Common UNIX way of constructing argument line is

<command> <keys&arguments> [--] <arguments>

In you case

command: git rm
keys: -r --cached --ignore-unmatch
arguments: '--exclude'

Usually keys are detected by leading -s.

But you can always force move them to arguments by explicitly writing them in the arguments part of the line using -- So you get

git filter-branch --index-filter "git rm -r --cached --ignore-unmatch -- '--exclude' " HEAD
Lol4t0
  • 12,444
  • 4
  • 29
  • 65
  • 1
    Note that what this answer calls 'keys' are also often called 'options' and that keys/options are arguments, too, so that what this answer calls 'arguments' are sometimes called 'non-option arguments'. Further note that (other than many other UNIX commands) with most (probably all) git subcommands, you can't put arbitrary non-option arguments after the `--` separator, but only files and directories. – das-g Feb 28 '16 at 11:21
2

The recommended way to do this is to use the -- separator as seen in the answers by VonC and Lol4t0 and to put the file name after it.

But using wildcards to avoid the --… part of --exclude, as Lasse suggests in a comment works indeed, too, as Git seems to do its own wildcard expansion, independent of the shell.

If you were just using it in a single, manual git rm, you'd have to either

  • escape it:

    git rm -r --cached --ignore-unmatch \*exclude
    

    or

  • quote it

    git rm -r --cached --ignore-unmatch '*exclude'
    

    or

  • delete the actual file first

    rm ./--exclude
    git rm -r --cached --ignore-unmatch *exclude
    

so that the shell doesn't already perform the expansion and the wildcard is passed to Git at all. But in

git filter-branch \
    --index-filter "git rm -r --cached --ignore-unmatch *exclude" HEAD

the whole inner command is quoted anyway, and git filter-branch doesn't seem to invoke the shell to interpret it, so this works as-is. (Usage with nested commands is probably the reason why Git implements its own wildcard expansion at all.)

Community
  • 1
  • 1
das-g
  • 9,718
  • 4
  • 38
  • 80