Git: jak usunąć plik z indeksu bez usuwania plików z dowolnego repozytorium

Kiedy używasz

git rm --cached myfile

Nie usuwa z lokalnego systemu plików, co jest celem. Jeśli jednak plik został już wersjonowany i zatwierdzony, przesunął go do centralnego repozytorium i wciągnął do innego repozytorium przed użyciem polecenia, usunie on Plik z tego systemu.

Czy istnieje sposób na usunięcie pliku z wersji bez usuwania go z dowolnego systemu plików?

Edit: mam nadzieję.

Author: Nick Volynkin, 2010-04-09

7 answers

Nie sądzę, aby commit Git mógł nagrać intencję typu "przestań śledzić ten plik, ale nie usuwaj go".

Wprowadzenie takiej intencji będzie wymagało interwencji poza Gitem w repozytoriach, które scalają (lub rebase) commit usuwający plik.


Zapisz kopię, Zastosuj usunięcie, Przywróć

Prawdopodobnie najprostszą rzeczą do zrobienia jest powiedzieć dalszym użytkownikom, aby zapisać kopię pliku, wyciągnąć usunięcie, a następnie przywrócić plik. Jeśli ciągną poprzez rebase i "przenoszą" modyfikacje do pliku, dostaną konflikty. Aby rozwiązać takie konflikty, użyj git rm foo.conf && git rebase --continue (Jeśli commit kolidujący z plikiem zmienił się oprócz zmian w usuniętym pliku) lub git rebase --skip (Jeśli commit kolidujący zmienił się tylko w usuniętym pliku).

Przywróć plik jako nie śledzony po wyciągnięciu Commita, który go usunie

Jeśli już wyciągnęli zatwierdzenie usunięcia, nadal mogą odzyskać poprzednią wersję pliku za pomocą git Pokaż:

git show @{1}:foo.conf >foo.conf

Lub z Git checkout (za komentarz Williama Pursella; ale pamiętaj, aby ponownie usunąć go z indeksu!):

git checkout @{1} -- foo.conf && git rm --cached foo.conf

Jeśli podjęli inne działania od momentu wyciągnięcia twojego usunięcia (lub wciągają rebase do odłączonej głowicy), mogą potrzebować czegoś innego niż @{1}. Mogą użyć git log -g, aby znaleźć commit tuż przed usunięciem.


W komentarzu wspominasz, że plik, który chcesz "untrack, but keep" to rodzaj pliku konfiguracyjnego, który jest wymagany do uruchomienia Oprogramowania (bezpośrednio z repozytorium).

Zachowaj plik jako 'domyślny' i aktywuj go ręcznie / automatycznie

Jeśli nie jest całkowicie nie do przyjęcia utrzymanie zawartości pliku konfiguracyjnego w repozytorium, możesz zmienić nazwę śledzonego pliku z (np.) foo.conf na foo.conf.default, a następnie polecić użytkownikom cp foo.conf.default foo.conf po zastosowaniu zmiany nazwy zatwierdzenia. Lub, jeśli użytkownicy skrypt lub inny program skonfigurowany przez zawartość w repozytorium (np. Makefile lub podobny)) do uruchamiania / wdrażania oprogramowania, można włączyć domyślny mechanizm do procesu uruchamiania/wdrażania:

test -f foo.conf || test -f foo.conf.default &&
    cp foo.conf.default foo.conf

Z takim mechanizmem domyślnym, użytkownicy powinni być w stanie wyciągnąć commit, który zmienia nazwę foo.conf na foo.conf.default bez konieczności wykonywania dodatkowej pracy. Ponadto unikniesz konieczności ręcznego kopiowania pliku konfiguracyjnego, jeśli tworzenie dodatkowych instalacji/repozytoriów w przyszłości.

Przepisywanie Historii Wymaga Ręcznej Interwencji W Każdym Razie...

Jeśli utrzymanie zawartości w repozytorium jest niedopuszczalne, prawdopodobnie będziesz chciał całkowicie usunąć ją z historii za pomocą czegoś takiego git filter-branch --index-filter …. Oznacza to przepisywanie historii, które będzie wymagało ręcznej interwencji dla każdej gałęzi / repozytorium (patrz sekcja "recovery From Upstream Rebase" w sekcji Git rebase manpage ). Specjalne traktowanie wymagane dla pliku konfiguracyjnego byłoby kolejnym krokiem, który należy wykonać podczas odzyskiwania po przepisaniu:

  1. Zapisz kopię pliku konfiguracyjnego.
  2. Odzyskaj po przepisaniu.
  3. Przywróć plik konfiguracyjny.

Zignoruj to, aby zapobiec nawrotom

Niezależnie od używanej metody, prawdopodobnie będziesz chciał umieścić nazwę pliku konfiguracyjnego w pliku .gitignore w repozytorium, aby że nikt nie może ponownie (jest to możliwe, ale wymaga -f/--force). Jeśli masz więcej niż jeden plik konfiguracyjny, możesz rozważyć 'przeniesienie' ich wszystkich do jednego katalogu i zignorowanie całości (przez 'przenoszenie' mam na myśli zmianę miejsca, w którym program oczekuje znalezienia swoich plików konfiguracyjnych, i nakłonienie użytkowników (lub mechanizm uruchamiania/wdrażania) do skopiowania / przeniesienia plików do ich nowej lokalizacji; oczywiście nie chciałbyś git mv pliku do katalogu, który ma być będziesz ignorować).

 105
Author: Chris Johnsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-10 07:52:26

Miałem ten sam problem w tym tygodniu, kiedy przypadkowo popełniłem błąd, a następnie próbowałem usunąć plik kompilacji ze współdzielonego repozytorium, i to:

Http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html

Działa dobrze dla mnie i nie wymienione do tej pory.

git update-index --assume-unchanged <file>

Aby usunąć plik, który Cię interesuje z kontroli wersji, użyj wszystkich innych poleceń normalnie.

git update-index --no-assume-unchanged <file>
Jeśli kiedykolwiek zechcesz to włożyć z powrotem.

Edytuj: Zobacz komentarze Chrisa Johnsena i KPM, to działa tylko lokalnie, a plik pozostaje pod kontrolą wersji dla innych użytkowników, jeśli również tego nie robią. Przyjęta odpowiedź daje bardziej kompletne / poprawne metody radzenia sobie z tym. Również niektóre uwagi z linku, jeśli używasz tej metody:

Oczywiście jest sporo zastrzeżeń, które wchodzą w grę z tym. Jeśli dodasz plik bezpośrednio, zostanie on dodany do indeksu. Połączenie commita z tą flagą spowoduje merge to fail z wdziękiem, dzięki czemu można obsługiwać go ręcznie.

 84
Author: Tom Power,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-03 08:11:12

Aby usunąć plik z indeksu, użyj:

git reset myfile

Nie powinno to mieć wpływu na Twoją lokalną kopię ani na czyjąkolwiek inną.

 29
Author: Armand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-09 12:51:48

Po wykonaniu polecenia git rm --cached spróbuj dodać myfile do pliku .gitignore (utwórz go, jeśli nie istnieje). To powinno powiedzieć gitowi, aby zignorował myfile.

Plik .gitignore jest wersjonowany, więc musisz zatwierdzić go i wepchnąć do zdalnego repozytorium.

 13
Author: awgy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-09 02:03:36
  1. git rm --cached remove_file
  2. Dodaj plik do gitignore
  3. git add .gitignore
  4. git commit -m "Excluding"
  5. miłej zabawy;)
 9
Author: Анастасия Ермолик,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-09 18:08:02

Moim rozwiązaniem jest ściągnięcie drugiej kopii roboczej, a następnie wykonanie:

git log --pretty="format:" --name-only -n1 | xargs git checkout HEAD^1

Który mówi, że pobieramy wszystkie ścieżki plików w najnowszym komentarzu i sprawdzamy je z rodzica HEAD. Zrobione.

 1
Author: Tom Viner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-05 16:24:22

Powyższe rozwiązania działają dobrze w większości przypadków. Jeśli jednak musisz również usunąć wszystkie ślady tego pliku (np. poufne dane, takie jak hasła), będziesz również chciał usunąć go z całej historii zatwierdzeń, ponieważ plik nadal może być stamtąd pobrany.

Oto rozwiązanie, które usuwa wszystkie ślady pliku z całej historii zatwierdzeń, tak jakby nigdy nie istniał, ale utrzymuje plik na swoim miejscu system.

Https://help.github.com/articles/remove-sensitive-data/

Możesz przejść do kroku 3, jeśli jesteś w lokalnym repozytorium git i nie musisz wykonywać suchej próby. W moim przypadku potrzebowałem tylko kroków 3 i 6, ponieważ już stworzyłem mój .plik gitignore i był w repozytorium, nad którym chciałem pracować.

Aby zobaczyć swoje zmiany, może być konieczne przejście do katalogu głównego GitHub w repozytorium i odświeżenie strony. Następnie przejdź przez linki, aby dostać się do Stary commit, który kiedyś miał plik, aby zobaczyć, że został usunięty. Dla mnie samo odświeżenie starej strony commit nie pokazało zmiany.

Początkowo wyglądało to onieśmielająco, ale naprawdę było łatwe i działało jak urok ! :-)

 0
Author: SherylHohman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-11 20:00:03