2015-04-16 10 views
8

Mam problem z tym skryptem Basha, który piszę. Próbuję zastosować krok 3 z this procedure from Github documentation, aby usunąć wszystkie pliki z historii naszych repozytoriów z naszej historii git. Na przykład, jeśli .gitignore ignoruje .txt, chcę usunąć wszystkie .txt z historii. I tak dalej dla każdej linii .gitignore.Nie można użyć skryptu bash do usunięcia plików z historii git

Jestem w stanie użyć symbolu wieloznacznego w przykładowym pliku. Więc mogę uruchomić następujące usunąć wszystkie pliki .txt:

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

więc starałem się zrobić skrypt bash, aby zrobić to samo.

Zrobiłem prosty plik .gitignore przetestować to z, jak następuje:

#foo 
*.txt 
*.docx 

Mój skrypt wygląda następująco:

#!/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 

Jednak to powoduje następujące dane wyjściowe:

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

(jeden raz dla każdej linii pliku .gitignore)

0.123.

Co zrobiłem źle?

+0

Podaj swoje zmienne! – Biffen

+1

Nie można umieszczać złożonych poleceń w ciągu znaków. Nie próbuj. http://mywiki.wooledge.org/BashFAQ/050 Zwłaszcza, że ​​nie możesz poprawnie wycenić cytatów. –

+0

Polecenie, którego używam, zawiera pojedyncze cudzysłowy. Kiedy po prostu próbowałem uruchomić polecenie i dodać do niego linię $, uruchomione polecenie zawierało "git rm --cached --ignore unmatch $ line" zamiast zawierać zawartość $ line. – Jake

Odpowiedz

7

Wierzę, że to może zrobić, co chcesz.

#!/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 

Unikałem wszystkich bezsensownych zmiennych pośrednich, które po prostu skomplikowały rzeczy. (Chociaż tylko usuwając jeden cytat z str1 i upuszczanie str2 mogło być wystarczająco to saner o ile mi wiadomo).

Filtr po prostu musi być pojedynczy łańcuch ale jak skonstruować ten ciąg jest do ty.

Prawdopodobnie możesz również zebrać wszystkie wzorce z gitignore i po prostu uruchomić gałąź filtru raz (i nie potrzebujesz wtedy --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 

Należy również pamiętać, że powinieneś być pewien, że masz do czynienia tylko z prostych wzorów tutaj, ponieważ zrozumienie wzorców rm i .gitignore nie jest całkiem takie same we wszystkich przypadkach nie sądzę.

+0

To zadziałało! Dzięki wielkie. Przyjmuję odpowiedź tak szybko, jak tylko mogę. – Jake

+0

Jeszcze raz dziękuję. Zacząłem pisać bez dodatkowych zmiennych łańcuchowych, ale nie używałem zbyt wielu skryptów bash, nie wiedziałem, jak zdobyć $ line tam, gdzie było to potrzebne. To rozwiązanie było znacznie prostsze i pomocne. – Jake

Powiązane problemy