Usuń plik z repozytorium Git bez usuwania go z lokalnego systemu plików

3043

Moje początkowe zatwierdzenie zawierało niektóre pliki dziennika. Dodałem *logdo mojego .gitignore, a teraz chcę usunąć pliki dziennika z mojego repozytorium.

git rm mylogfile.log

usunie plik z repozytorium, ale także usunie go z lokalnego systemu plików.

Jak mogę usunąć ten plik z repozytorium bez usuwania mojej lokalnej kopii pliku?

mveerman
źródło
14
Warto zauważyć, że najbardziej pozytywna odpowiedź jest dla niektórych niebezpieczna. Jeśli używasz zdalnego repozytorium niż podczas wypychania lokalnego, wyciągnij gdzie indziej tylko te pliki, które usunąłeś z git, ZOSTANĄ USUNIĘTE . Jest to wspomniane w jednej z odpowiedzi, ale nie skomentowane.
RichieHH

Odpowiedzi:

4347

Z pliku man :

Gdy --cachedzostanie podany, zawartość przemieszczana musi być zgodna z końcem gałęzi lub plikiem na dysku, umożliwiając usunięcie pliku tylko z indeksu.

Tak więc dla jednego pliku:

git rm --cached mylogfile.log

i dla jednego katalogu:

git rm --cached -r mydirectory
bdonlan
źródło
150
Łatwo przegapić, ponieważ nie jest tak oczywiste jak svn rm --keep-local.
Martin
114
Ale jak mogę zachować pliki na zdalnych serwerach? Zachowuje to mój lokalny, ale jeśli popchnę i pobiorę z innego serwera, plik zostanie usunięty. Dodałem również plik
.gitignore
6
To nadal usuwa pliki, git pulljeśli jesteś za opóźnieniem pogit rm
Petr Peller
9
Warto zauważyć, że po uruchomieniu polecenia w odpowiedzi musisz użyć git commit -m "Commit message"i git push. Jeśli masz inne zmiany etapowe (sprawdź za pomocą git status), zostaną one również zatwierdzone w tym momencie.
Sinjai,
9
Ponieważ jest to najbardziej akceptowana odpowiedź i nie odpowiada, o co jest proszony, powiem, co robię. Używam polecenia git rm --cached mylogfile.logi usuwam plik z repozytorium. Aby uniknąć utraty pliku w systemie produkcyjnym, wykonuję kopię zapasową pliku i ciągnę po tym. Plik zostanie usunięty, jak wspomniano wcześniej, i należy go skopiować z kopii zapasowej. Jest to dość bolesne, ale nie znalazłem lepszego rozwiązania tego problemu.
Marcel Grolms
275

Aby usunąć cały folder z repozytorium (np. Pliki Resharper):

git rm -r --cached folderName

Popełniłem niektóre pliki resharper i nie chciałem, aby były trwałe dla innych użytkowników projektu.

Sam Tyson
źródło
13
Dodatkowa uwaga dla przyszłych gości: nie używaj GUI do „synchronizacji” zatwierdzenia z powrotem do repozytorium. Spowoduje to ściągnięcie plików z powrotem do lokalnego repozytorium. Musisz zrobić, Git Push repo branchaby faktycznie usunąć pliki z pilota.
RubberDuck,
211

Możesz także usunąć pliki z repozytorium na podstawie swojego .gitignore bez usuwania ich z lokalnego systemu plików:

git rm --cached `git ls-files -i -X .gitignore`

Lub alternatywnie w Windows Powershell:

git rm --cached $(git ls-files -i -X .gitignore)
zero
źródło
7
Nie działa w systemie Windows. git ls-files -i -X ​​.gitignore działa, ale nie wiem jak wysłać pliki do 'git rm'. Czy wiesz jak to zrobić?
Erik Z
17
Działa w systemie Windows, jeśli używasz Git Bash zamiast konsoli cmd
Andreas Zita,
17
Kocham to. Działało poza tym, że miałem kilka plików, które ostatecznie miały spacje w nazwie pliku. I tu zmodyfikowane rozwiązanie to: git ls-files -i -X .gitignore | xargs -I{} git rm --cached "{}". Proszę rozważyć modyfikację lub dodanie tego roztworu do odpowiedzi tutaj, ponieważ jest to doskonałe narzędzie, aby ...
mpettis
Nie próbowałem, ale powinien zostać przetestowany, czy usunie także takie pliki, .gitkeepktóre zachowują pusty folder w repozytorium. Na przykład. .gitignorezawiera folder, uploadsa repo jest zmuszone do śledzenia .gitkeep. Usunięcie wszystkich repozytoriów pod uploadsnim spowoduje również usunięcie .gitkeep.
Vladimir Vukanac
Ta sugestia działała idealnie w PowerShell: git rm --cached $ (git ls-files -i -X
.gitignore
89

Zgodnie z moją odpowiedzią tutaj: /programming/6313126/how-to-remove-a-directory-in-my-github-repository

Aby usunąć folder / katalog lub plik tylko z repozytorium git, a nie z lokalnego, spróbuj 3 prostych kroków.


Kroki, aby usunąć katalog

git rm -r --cached File-or-FolderName
git commit -m "Removed folder from repository"
git push origin master

Kroki, aby zignorować ten folder w kolejnych zatwierdzeniach

Aby zignorować ten folder od następnych zatwierdzeń, utwórz jeden plik w katalogu głównym o nazwie .gitignore i umieść w nim nazwę tego folderu. Możesz umieścić tyle, ile chcesz

Plik .gitignore będzie wyglądał następująco

/FolderName

usuń katalog

eirenaios
źródło
@gaurav cieszę się, że pomogło!
eirenaios
69

Ponadto, jeśli zatwierdziłeś poufne dane (np. Plik zawierający hasła), powinieneś całkowicie usunąć je z historii repozytorium. Oto przewodnik wyjaśniający, jak to zrobić: http://help.github.com/remove-sensitive-data/

BoD
źródło
13
Ta odpowiedź powinna zawierać wymagane polecenia do wykonania tego zadania zamiast linku do innej strony internetowej.
Florian Lemaitre
1
Chciałbym również zauważyć, że korzystanie z narzędzia do czyszczenia repozytoriów git bfg było łatwiejsze i szybsze.
Lubed Up Slug
64

Bardziej ogólne rozwiązanie:

  1. Edytuj .gitignoreplik.

    ECHO mylogfile.log >> .gitignore

  2. Usuń wszystkie elementy z indeksu.

    git rm -r -f --cached .

  3. Przebuduj indeks.

    git add .

  4. Dokonaj nowego zatwierdzenia

    git commit -m "Removed mylogfile.log"

mAsT3RpEE
źródło
2
Czy to faktycznie usunie plik?
Mr_and_Mrs_D
6
Od GitHub? NIE. Jeśli już wysłałeś na github, nie usunie go z witryny. Ale zaktualizuje twoje lokalne repozytorium git.
mAsT3RpEE,
5
Skasowany komentarz faktycznie został bardziej wyeliminowany :) Problem z rozwiązaniem rm --cashedpolega na tym, że w końcu usunie plik, gdy ktoś wyciągnie - prawda? I nie tego ludzie chcą, gdy mówią „Usuń plik z repozytorium bez usuwania go z lokalnego systemu plików ”. Dlaczego powyższe rozwiązanie zostało zaakceptowane, jest poza mną - prawdopodobnie OP działał sam i nigdy się nie wycofał? Dunno. Rozumiem, że github „raz pchany zawsze tam” ofc
Mr_and_Mrs_D
Nie sądzę, aby istniało 100% rozwiązanie, chyba że zapytasz samego githuba. Na razie trzymaj się tego. Skopiuj plik, dodaj do gitignore, zrób rzeczywisty git rm -r, zatwierdz, wypchnij, przywróć plik. Czy udało ci się znaleźć inne rozwiązanie?
mAsT3RpEE,
9
Moim problemem nie jest github - chodzi o to, że plik zostanie faktycznie usunięty ze współpracowników po ich ściągnięciu . I nie chcą plik ma zostać usunięty. W przeszłości sprawiało mi to ogromne problemy. Zastanawiałem się więc, czy istnieje rozwiązanie, które tak naprawdę nie usuwa pliku. Zobacz także komentarz w zaakceptowanej odpowiedzi: stackoverflow.com/questions/1143796/…
Mr_and_Mrs_D
24

Git pozwala zignorować te pliki, zakładając, że są niezmienione. Odbywa się to przez uruchomienie git update-index --assume-unchanged path/to/file.txtpolecenia. Po oznaczeniu pliku jako takiego git całkowicie zignoruje wszelkie zmiany w tym pliku; nie pojawią się, gdy uruchomiony jest status git lub git diff, ani nigdy nie zostaną popełnione.

(Od https://help.github.com/articles/ignoring-files )

Dlatego nie usuwając go, ale ignorując zmiany na zawsze. Myślę, że działa to tylko lokalnie, więc współpracownicy nadal widzą zmiany, chyba że wykonają to samo polecenie jak powyżej. (Wciąż muszę to jednak zweryfikować).

Uwaga: Nie odpowiada to bezpośrednio na pytanie, ale opiera się na dalszych pytaniach w komentarzach innych odpowiedzi.

Rystraum
źródło
2
Hm, robię to, ale widzę, że plik może zostać zastąpiony, jeśli ktoś inny wprowadzi w nim zmiany w repozytorium.
AlxVallejo
17

Jeśli chcesz po prostu wyśledzić plik i nie usuwać go z lokalnego i zdalnego repozytorium, użyj tego polecenia:

git update-index --assume-unchanged  file_name_with_path
Afraz Ahmad
źródło
2
Chociaż jest to dobra odpowiedź, należy zauważyć, że nie powoduje to „wyśledzenia” pliku w tym sensie, że ludzie zwykle używają tego słowa w Git, gdzie nieśledzony plik to taki, który nie znajduje się w historii repozytorium i nigdy nie był . Ta odpowiedź polega na przechowywaniu pliku w repozytorium, ale uniemożliwia Gitowi zauważenie, że w nim zostały wprowadzone zmiany. Ma to kilka istotnych różnic - co najważniejsze, plik jest nadal obecny dla innych, a jeśli ktoś inny wprowadzi w nim zmiany, a ty wyciągniesz, lokalną kopię można zastąpić bez potwierdzenia.
Soren Bjornstad,
8

Powyższe odpowiedzi nie działały dla mnie. użyłemfilter-branch usuwać wszystkie zatwierdzone pliki.

Usuń plik z repozytorium git za pomocą:

git filter-branch --tree-filter 'rm  file'

Usuń folder z repozytorium git za pomocą:

git filter-branch --tree-filter 'rm -rf directory'

Spowoduje to usunięcie katalogu lub pliku ze wszystkich zatwierdzeń.

Możesz określić zatwierdzenie, używając:

git filter-branch --tree-filter 'rm -rf directory' HEAD

Lub zakres:

git filter-branch --tree-filter 'rm -rf vendor/gems' t49dse..HEAD

Aby przekazać wszystko zdalnie, możesz:

git push origin master --force
Martijn Mellens
źródło
2
W połączeniu z tym git rm -r --cached NAMEjest trik, aby usunąć go z lokalnego repozytorium git i zapobiec
wpływowi
1
Powoduje to przepisanie historii gita i trzeba by było popchnąć po niej - to chyba trochę poza zakresem pytania. W słynnym publicznym repozytorium nie można tak po prostu zmienić linii historii, ponieważ każdy, kto już sklonował repo, miałby problemy podczas ciągnięcia.
Guillaume Perrot
0

Zignoruj ​​pliki, usuń pliki z git, zaktualizuj git (do usunięcia).

Uwaga: nie dotyczy to historii wrażliwych informacji.

Ten proces z pewnością wymaga pewnego zrozumienia tego, co dzieje się z git. Z czasem, gdy to osiągnąłem, nauczyłem się wykonywać takie procesy, jak:

1) Zignoruj ​​pliki

  • Dodaj lub zaktualizuj projekt, .gitignoreaby je zignorować - w wielu przypadkach, takich jak Twój, katalog nadrzędny, nplog/ Będzie wyrażeniem regularnym do użycia.
  • zatwierdzaj i wypychaj tę .gitignorezmianę pliku (nie jestem pewien, czy wypychanie wymagało przypomnienia sobie, bez szkody, jeśli zrobiono).

2) Usuń pliki z git (tylko).

  • Teraz usuń pliki z git (tylko) za pomocą git remove --cached some_dir/
  • Sprawdź, czy nadal pozostają lokalnie (powinny!).

3) Dodaj i zatwierdź tę zmianę (w gruncie rzeczy jest to zmiana polegająca na „dodawaniu” usuwania rzeczy, pomimo mylącej w przeciwnym razie polecenia „dodawania”!)

  • git add .
  • git commit -m"removal"
Michael Durrant
źródło