2012-09-24 1 views
2

Я использую ответ this question, чтобы удалить клонирование репозитория в список файлов, которые я хочу сохранить в отключение этого проекта. Скажем, я хочу удалить все, кроме каталога src/main и его подкаталогов. Поскольку у меня будет несколько файлов и каталогов, я использую --index-filter вместо --subdirectory-filter.git-filter-branch с -index-filter: странная ошибка bash (!: Событие не найдено)

Я думал, что должно работать:

git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ↩ 
    src/!(main)" --prune-empty -- --all 

Но все это я получаю

-bash: !: event not found 

Я перепробовал все виды различных путей вместо src/!(main). Я всегда получаю именно это сообщение об ошибке. Кажется, это проблема bash, потому что эта строка также не входит в мою историю командной строки?


То есть, если у меня есть главные файлы уровня A и B, и подкаталог C/D, как я могу удалить все, кроме эти три вещи?

+0

В то же время, у меня есть успех, давая 'г rm' список всех файлов __remove__, вместо того, чтобы указать те, в __keep__. В этом случае большая боль, потому что есть много по сравнению с теми, кого я хочу сохранить; но, похоже, это работает. –

ответ

4

The! это проблема, поскольку она используется для отзыва истории команд. Внутри кавычек, обратная косая черта впереди тоже не помогает, поэтому \! должны быть вне кавычек. Может быть проиллюстрировано с помощью несколько примеров с эхом:

/home/user1> echo "src/!(main)" 
-bash: !: event not found 
/home/user1> echo "src/\!(main)" 
src/\!(main) 
/home/user1> echo "src/"\!"(main)" 
src/!(main) 
+0

Это означает, что * extglob * соответствует всем в 'src', но' main'. – kynan

+0

@kynan: globbing (включая extglob) не работает внутри кавычек. Вы пытаетесь использовать extglob шаблон для расширения имени файла? – cdarke

+1

Это то, что намеревался ОП: посмотрите на выяснение вопроса и ответ на вопрос, как его исправить. – kynan

0

Восклицательный знак используется в синтаксисе Баша, чтобы сделать history expansion, что и вызывает путаницу. Вы должны избегать этого, используя обратную косую черту или одинарные котировки:

git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ↩ 
    src/\!(main)" --prune-empty -- --all 
+0

Хммм. Это просто дает мне «синтаксическую ошибку возле неожиданного токена» («' - 'eval: строка 349: 'git rm -r -f --cached --ignore-unmatch src/\! (Main)'' –

+0

К сожалению, при использовании внутри кавычек сохраняется \ – cdarke

3

Чтобы ответить на фактический вопрос добавлен в разъяснении: вы пытаетесь использовать extglob BASh в удалить все в src но main в git index-filter. Это не работает, потому что команда индексного фильтра не, выполненная вашей оболочкой, а sh через eval (см. /usr/lib/git-core/git-filter-branch:327).

You can't tell git to enable extglob when doing this, but you can make your shell expand the extglob before passing it to index-filter:

git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch $(ls -xd src/!(main))" --prune-empty -- --all 
+0

/usr/local/opt/git/libexec/git-core/git-filter-branch для меня на OSX –

+0

@JamesEJ Это означает, что git не на вашем '$ PATH' – kynan

+0

Я хотел увидеть источник, был невероятно полезен! –