Usuń poufne pliki i ich commity z historii Gita

Chciałbym umieścić projekt Gita na Githubie, ale zawiera on pewne pliki z poufnymi danymi (nazwy użytkowników i hasła, jak /config / deploy.rb dla capistrano).

Wiem, że mogę dodać te nazwy plików do .gitignore , ale to nie usunie ich historii w Git.

Nie chcę też zaczynać od nowa usuwając /.katalog git.

Czy istnieje sposób na usunięcie wszystkich śladów konkretnego pliku w historii Gita?

Author: Roberto Tyley, 2009-05-16

10 answers

Dla wszystkich praktycznych celów, pierwszą rzeczą, którą powinieneś się martwić, jest zmiana haseł! z twojego pytania nie wynika, czy Twoje repozytorium git jest całkowicie lokalne, czy też masz zdalne repozytorium gdzie indziej; jeśli jest zdalne i nie jest zabezpieczone przed innymi, masz problem. Jeśli ktoś sklonował to repozytorium, zanim to naprawisz, będzie miał kopię Twoich haseł na swoim lokalnym komputerze i nie ma sposobu, aby zmusić go do aktualizacji do twoja "naprawiona" wersja z nią odeszła z historii. Jedyną bezpieczną rzeczą, którą możesz zrobić, jest zmiana hasła na coś innego wszędzie, gdzie go używasz.


Z tym na uboczu, oto jak to naprawić. GitHub odpowiedział dokładnie na to pytanie jako FAQ :

Uwaga dla użytkowników systemu Windows : użyj podwójnych cudzysłowów (") zamiast singli w tym poleceniu

git filter-branch --index-filter \
'git update-index --remove filename' <introduction-revision-sha1>..HEAD
git push --force --verbose --dry-run
git push --force

Należy pamiętać, że po wypchnięciu tego kodu do zdalnego repozytorium, takiego jak GitHub i inne mają sklonowane zdalne repozytorium, jesteś teraz w sytuacji, gdy przepisujesz historię. Gdy inni spróbują wyciągnąć najnowsze zmiany po tym, otrzymają komunikat informujący, że zmiany nie mogą być zastosowane, ponieważ nie jest to przewijanie do przodu.

Aby to naprawić, będą musieli albo usunąć istniejące repozytorium i sklonować je ponownie, albo postępować zgodnie z instrukcjami w sekcji "odzyskiwanie z rebase' U " na stronie Man git-rebase.


W przyszłości, jeśli przypadkowo Zatwierdź niektóre zmiany wrażliwymi informacjami, ale zauważysz przed przepchnięciem do zdalnego repozytorium, są pewne łatwiejsze poprawki. Jeśli ostatni commit jest Tym, który dodaje poufne informacje, możesz po prostu usunąć poufne informacje, a następnie uruchomić:

git commit -a --amend

, które zmienią poprzedni commit o wszelkie nowe zmiany, w tym usunięcie całego pliku za pomocą git rm. Jeśli zmiany są dalej w historii, ale nadal nie pchane do zdalnego repozytorium, możesz zrobić interaktywną rebase:

git rebase -i origin/master

Otwiera edytor z zatwierdzeniami, które wprowadziłeś od ostatniego wspólnego przodka ze zdalnym repozytorium. Zmień "pick" na "edit" W dowolnej linii reprezentującej commit z poufnymi informacjami, a następnie zapisz i zakończ. Git przejdzie przez zmiany i pozostawi cię w miejscu, w którym możesz:

$EDITOR file-to-fix
git commit -a --amend
git rebase --continue

Dla każdej zmiany z wrażliwymi informacjami. W końcu wylądujesz z powrotem na swojej gałęzi i możesz bezpiecznie popchnąć nowy zmiany.

 370
Author: natacado,
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
2016-05-26 12:16:07

Zmiana haseł jest dobrym pomysłem, ale w procesie usuwania haseł z historii repo, polecam BFG Repo-Cleaner, szybszą i prostszą alternatywę dla git-filter-branch zaprojektowaną do usuwania prywatnych danych z Git repos.

Utwórz plik private.txt z listą haseł itp., które chcesz usunąć (jeden wpis w linii), a następnie uruchom następujące polecenie:

$ java -jar bfg.jar  --replace-text private.txt  my-repo.git

Wszystkie pliki poniżej progu (domyślnie 1MB) w historii repo będą zeskanowany, a każdy pasujący ciąg znaków (który nie znajduje się w Twoim najnowszym commicie) zostanie zastąpiony ciągiem "***REMOVED***". Następnie możesz użyć git gc, Aby wyczyścić martwe dane:

$ git gc --prune=now --aggressive

BFG jest zwykle 10-50x szybszy niż działanie git-filter-branch, A opcje są uproszczone i dopasowane do tych dwóch powszechnych przypadków użycia:

  • Usuwanie Crazy Big Files
  • usuwanie haseł, poświadczeń i innych prywatnych dane

pełne ujawnienie: jestem autorem BFG Repo-Cleaner.

 70
Author: Roberto Tyley,
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
2014-07-11 06:41:03

Polecam ten skrypt autorstwa Davida Underhilla, zadziałał jak urok dla mnie.

Dodaje te polecenia w dodatku natacado filter-branch, aby oczyścić bałagan, który pozostawia po sobie:

rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --prune

Pełny scenariusz (wszystkie podziękowania dla Davida Underhilla)

#!/bin/bash
set -o errexit

# Author: David Underhill
# Script to permanently delete files/folders from your git repository.  To use 
# it, cd to your repository's root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2

if [ $# -eq 0 ]; then
    exit 0
fi

# make sure we're at the root of git repo
if [ ! -d .git ]; then
    echo "Error: must run this script from the root of a git repository"
    exit 1
fi

# remove all paths passed as arguments from the history of the repo
files=$@
git filter-branch --index-filter \
"git rm -rf --cached --ignore-unmatch $files" HEAD

# remove the temporary history git-filter-branch
# otherwise leaves behind for a long time
rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune

Ostatnie dwa polecenia mogą działać lepiej, jeśli zostaną zmienione na następujące:

git reflog expire --expire=now --all && \
git gc --aggressive --prune=now
 16
Author: Jason Goemaat,
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-01-14 03:53:50

Jeśli już nacisnąłeś na GitHub, dane są zagrożone, nawet jeśli wymusisz wypchnięcie ich sekundę później Ponieważ:

Aby to przetestować, stworzyłem repo: https://github.com/cirosantilli/test-dangling i zrobione:

git init
git remote add origin [email protected]:cirosantilli/test-dangling.git

touch a
git add .
git commit -m 0
git push

touch b
git add .
git commit -m 1
git push

touch c
git rm b
git add .
git commit --amend --no-edit
git push -f

Jeśli usuniesz repozytorium , commity znikną nawet z API natychmiast i dadzą 404, np. https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2b2d653f7a3824 to działa nawet jeśli odtworzysz inne repozytorium o tej samej nazwie.

Więc mój zalecany sposób działania to:

  • Zmień swoje referencje

  • Jeśli to za mało (np. nagie fotki):

    • Usuń repozytorium
    • skontaktuj się z obsługą
 10
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
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
2018-05-24 21:23:06

Dla jasności: przyjęta odpowiedź jest prawidłowa. Najpierw spróbuj. Jednak w niektórych przypadkach może to być niepotrzebnie skomplikowane, szczególnie jeśli napotkasz paskudne błędy, takie jak 'fatal: bad revision --prune-empty', lub naprawdę nie obchodzi cię historia repo.

Alternatywą byłoby:

  1. cd do podstawowej gałęzi projektu
  2. Usuń wrażliwy kod / plik
  3. rm-rf .git / # Usuń wszystkie informacje o git z Twój kod
  4. przejdź do github i usuń swoje repozytorium
  5. postępuj zgodnie z tym przewodnikiem, aby przenieść kod do nowego repozytorium, jak zwykle - https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/

To oczywiście usunie wszystkie gałęzie historii zatwierdzeń i problemy zarówno z twojego repo github, jak i lokalnego repo git. Jeśli jest to niedopuszczalne, będziesz musiał użyć alternatywnego podejścia.

Nazwij to opcją nuklearną.

 8
Author: lostphilosopher,
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-01-25 23:38:51

Oto moje rozwiązanie w windows

Git filter-branch --tree-filter" RM-f 'filedir/filename' " HEAD

Git push --force

Upewnij się, że ścieżka jest poprawna w przeciwnym razie to nie zadziała

Mam nadzieję, że to pomoże

 6
Author: vertigo71,
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
2016-12-02 19:19:31

Użyj filter-branch :

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

git push origin *branch_name* -f
 5
Author: Shiv Krishna Jaiswal,
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-09-17 14:50:54

Możesz użyć git forget-blob.

Użycie jest dość proste git forget-blob file-to-forget. Więcej informacji znajdziesz tutaj

Https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

Zniknie ze wszystkich commitów w twojej historii, reflogu, tagach i tak dalej

Co jakiś czas napotykam ten sam problem i za każdym razem muszę wracać do tego posta i innych, dlatego zautomatyzowałem ten proces.

Napisy do współpracownicy z Stack Overflow, który pozwolił mi złożyć to razem

 4
Author: nachoparker,
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-01-23 07:41:12

Musiałem to zrobić kilka razy do tej pory. Zauważ, że działa to tylko na jednym pliku na raz.

  1. Pobiera listę wszystkich zmian, które zmodyfikowały plik. Ten na dole będzie pierwszym commitem:

    git log --pretty=oneline --branches -- pathToFile

  2. Aby usunąć plik z historii użyj pierwszego zatwierdzenia sha1 i ścieżki do pliku z poprzedniego polecenia, i wypełnij je w tym poleceniu:

    git filter-branch --index-filter 'git rm --cached --ignore-unmatch <path-to-file>' -- <sha1-where-the-file-was-first-added>..

 2
Author: b01,
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-03-21 18:23:36

Więc wygląda to mniej więcej tak:

git rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore

Usuń pamięć podręczną śledzonego pliku z git i dodaj ten plik do listy .gitignore

 1
Author: przbadu,
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
2018-02-16 04:53:08