2015-04-16 2 views
8

У меня проблема с этим сценарием bash, который я пишу. Я пытаюсь применить шаг 3 из this procedure from Github documentation, чтобы удалить все файлы в нашей истории хранилищ из нашей истории git. Например, если .gitignore игнорирует .txt, я хочу удалить все .txt из истории. И так далее для каждой линии .gitignore.Невозможно использовать скрипт bash для удаления файлов из истории git

Я могу использовать подстановочный знак в файле примера. Таким образом, я могу запустить следующую команду, чтобы удалить все файлы с расширением .txt:

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *.txt' --prune-empty --tag-name-filter cat -- --all 

Так что я попытался сделать Баш скрипт, чтобы сделать то же самое.

Я сделал простой файл .gitignore, чтобы проверить это с, следующим образом:

#foo 
*.txt 
*.docx 

Мой сценарий оболочки выглядит следующим образом:

#!/bin/bash 

s1="#" 
str1="'git rm --cached --ignore-unmatch " 
str2="'" 

cat .gitignore | while read line 
do 
    if [[ $line == *"$s1"* ]] 
    then 
     echo #skip 
    else 
     str3=$str1$line$str2 
     git filter-branch --force --index-filter $str3 --prune-empty --tag-name-filter cat -- --all 
    fi 
done 

Однако это приводит следующий вывод:

fatal: bad revision 'rm' 
fatal: bad revision 'rm' 

(один раз для каждой строки файла .gitignore)

Что я сделал не так?

+0

Укажите свои переменные! – Biffen

+1

Вы не можете поместить сложные команды в строку. Не пытайтесь. http://mywiki.wooledge.org/BashFAQ/050 В частности, вы не можете правильно определить кавычки. –

+0

Команда, которую я использую, имеет одинарные кавычки. Когда я просто попытался запустить команду и добавить $ line к ней, в результате запускаемой команды включается «git rm --cached --ignore unmatch $ line» вместо содержания строки $. – Jake

ответ

7

Я считаю, что это может сделать то, что вы хотите.

#!/bin/bash 

cat .gitignore | while read line 
do 
    if [[ $line == *#* ]] 
    then 
     echo #skip 
    else 
     git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch '"$line" --prune-empty --tag-name-filter cat -- --all 
    fi 
done 

Я избегал всех бессмысленных промежуточных переменных, которые только что усложнили. (Хотя только удаление единственной цитаты из str1 и капельной str2 могла быть достаточно, это разумнее, насколько я понимаю.)

Фильтр просто должен быть одна строкой, но как построить эту строку до вы.

Возможно, вы также можете собрать все шаблоны из gitignore и просто запустить ветвь фильтра один раз (и не нужно --force в этом пункте) тоже.

#!/bin/bash 

patts=() 
while read -r line 
do 
    if [[ $line != *#* ]]; then 
     patts+=("$line") 
    fi 
done < .gitignore 

git filter-branch --index-filter 'git rm --cached --ignore-unmatch '"${patts[*]}" --prune-empty --tag-name-filter cat -- --all 

Также обратите внимание, что вы должны, вероятно, быть уверенными, что вы имеете дело только с простыми узорами здесь, потому что rm и .gitignore понимание моделей не совсем то же самое во всех случаях я не думаю.

+0

Это сработало! Спасибо. Я приму ответ, как только смогу. – Jake

+0

Еще раз спасибо. Я начал писать без дополнительных строковых переменных, но, не очень используя скрипты bash, я был смущен тем, как получить $-строку, где мне это нужно. Это решение было намного проще и полезно. – Jake

Смежные вопросы