J'aimerais mettre un projet Git sur GitHub, mais il contient certains fichiers contenant des données sensibles (noms d'utilisateur et mots de passe, comme /config/deploy.rb pour capistrano).
Je sais que je peux ajouter ces noms de fichiers à .gitignore , mais cela ne supprime pas leur historique dans Git.
Je ne veux pas non plus recommencer en supprimant le répertoire /.git.
Existe-t-il un moyen de supprimer tout les traces d'un fichier particulier dans votre historique Git?
À toutes fins pratiques, la première chose à laquelle vous devez vous inquiéter est (MODIFICATION DE VOS MOTS DE PASSE!} _ Votre question ne vous permet pas de savoir si votre dépôt git est entièrement local ou si vous avez déjà un dépôt distant ailleurs ; s'il est distant et non sécurisé des autres, vous avez un problème. Si quelqu'un a cloné ce référentiel avant de résoudre ce problème, il conservera une copie de vos mots de passe sur sa machine locale. Il est impossible de le forcer à mettre à jour votre version "corrigée". La seule chose à faire est de changer votre mot de passe pour quelque chose d'autre partout où vous l'avez utilisé.
Avec cela, voici comment y remédier. GitHub a répondu exactement à cette question en tant que FAQ :
Remarque pour les utilisateurs de Windows: utilisez des guillemets doubles (") au lieu de simples dans cette commande
git filter-branch --index-filter \
'git update-index --remove filename' <introduction-revision-sha1>..HEAD
git Push --force --verbose --dry-run
git Push --force
Gardez à l'esprit qu'une fois que vous avez envoyé ce code dans un référentiel distant tel que GitHub et que d'autres ont cloné ce référentiel distant, vous êtes maintenant dans une situation de réécriture de l'historique. Lorsque les autres utilisateurs essaient de récupérer vos dernières modifications après cela, ils reçoivent un message indiquant que les modifications ne peuvent pas être appliquées car il ne s'agit pas d'une avance rapide.
Pour résoudre ce problème, ils devront soit supprimer leur référentiel existant et le cloner à nouveau, soit suivre les instructions sous "RECUPÉRATION À PARTIR DE LA REBASE UPSTREAM" dans la page de manuel git-rebase .
À l'avenir, si vous validez accidentellement certaines modifications avec des informations sensibles mais que vous remarquez que avant poussant vers un référentiel distant, des correctifs plus simples sont nécessaires. Si votre dernière validation est celle pour laquelle vous ajoutez les informations sensibles, vous pouvez simplement supprimer les informations sensibles, puis exécuter:
git commit -a --amend
Cela modifiera le commit précédent avec toutes les nouvelles modifications que vous avez apportées, y compris la suppression de fichiers entiers avec un git rm
. Si les modifications sont plus en arrière dans l'historique mais ne sont toujours pas poussées vers un référentiel distant, vous pouvez effectuer une rebase interactive:
git rebase -i Origin/master
Cela ouvre un éditeur avec les commits que vous avez effectués depuis votre dernier ancêtre commun avec le référentiel distant. Remplacez "pick" par "edit" sur toutes les lignes représentant une validation avec des informations sensibles, puis enregistrez et quittez. Git suivra les modifications et vous laissera à un endroit où vous pourrez:
$EDITOR file-to-fix
git commit -a --amend
git rebase --continue
Pour chaque changement avec des informations sensibles. Finalement, vous allez revenir sur votre branche et vous pouvez pousser en toute sécurité les nouvelles modifications.
Changer vos mots de passe est une bonne idée, mais pour le processus de suppression des mots de passe de l'historique de votre référentiel, je recommande le BFG Repo-Cleaner , une alternative plus rapide et plus simple à git-filter-branch
explicitement conçue pour supprimer les données privées des référentiels Git.
Créez un fichier private.txt
répertoriant les mots de passe, etc. que vous souhaitez supprimer (une entrée par ligne), puis exécutez la commande suivante:
$ Java -jar bfg.jar --replace-text private.txt my-repo.git
Tous les fichiers de taille inférieure à un seuil (1 Mo par défaut) dans l'historique de votre référentiel seront analysés et toute chaîne correspondante (ne figurant pas dans votre dernière commit) sera remplacée par la chaîne "*** REMOVED *** ". Vous pouvez ensuite utiliser git gc
pour effacer les données mortes:
$ git gc --Prune=now --aggressive
Le BFG est généralement 10 à 50 fois plus rapide que l'exécution de git-filter-branch
et les options sont simplifiées et personnalisées autour de ces deux cas d'utilisation courants:
_ {Divulgation complète: je suis l'auteur du BFG Repo-Cleaner.} _
Je recommande ce script de David Underhill, a fonctionné à merveille pour moi.
Il ajoute ces commandes en plus de la branche-filtre de natacado pour nettoyer le gâchis qu'il laisse derrière lui:
rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --Prune
Texte complet (tout crédit à David Underhill)
#!/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
Les deux dernières commandes peuvent fonctionner mieux si elles sont modifiées comme suit:
git reflog expire --expire=now --all && \
git gc --aggressive --Prune=now
Si vous avez déjà poussé sur GitHub, les données sont compromises même si vous forcez Push it away une seconde plus tard parce que:
GitHub continue de s’engager pendant longtemps.
Le personnel de GitHub a le pouvoir de supprimer ces commits suspendus si vous les contactez, mais vous devez le faire: Comment supprimer un commit suspendu de GitHub?
Les commits suspendus peuvent être vus à travers:
Un moyen pratique d’obtenir la source à ce commit est alors d’utiliser la méthode de téléchargement Zip, qui peut accepter n’importe quelle référence, par exemple: https://github.com/cirosantilli/myrepo/archive/SHA.Zip
Il est possible de récupérer les SHA manquants soit par:
type": "PushEvent"
. Par exemple. mine: https://api.github.com/users/cirosantilli/events/public ( Wayback machine )Il existe des scrappers comme http://ghtorrent.org/ et https://www.githubarchive.org/ qui mettent régulièrement en commun les données GitHub et les stockent ailleurs.
Je ne pouvais pas trouver s'ils récupéraient le diff réel, mais c'est techniquement possible.
Pour tester cela, j'ai créé un repo: https://github.com/cirosantilli/test-dangling et fait:
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
Si vous supprimez le référentiel, les validations disparaissent même immédiatement de l’API et donnent 404, par exemple. https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2b2d653f7a3824 Ceci fonctionne même si vous recréez un autre référentiel portant le même nom.
Donc, mon action recommandée est:
changer vos identifiants
si cela ne suffit pas (par exemple, des photos nues):
Pour être clair: la réponse acceptée est correcte. Essayez-le d'abord. Toutefois, cela peut s'avérer inutilement complexe pour certains cas d'utilisation, en particulier si vous rencontrez des erreurs odieuses telles que "fatal: bad revision" ou si vous ne vous souciez pas de l'historique de votre repo.
Une alternative serait:
Ceci supprimera bien sûr toutes les branches d’historique de commit et les problèmes de votre référentiel github et de votre référentiel git local. Si cela est inacceptable, vous devrez utiliser une autre approche.
Appelez cela l'option nucléaire.
Voici ma solution sous windows
git filter-branch --tree-filter "rm -f 'filé/nom_fichier'" HEAD
git Push --force
assurez-vous que le chemin est correct sinon cela ne fonctionnera pas
J'espère que ça aide
Utilisez 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
Vous pouvez utiliser git forget-blob
.
L'utilisation est assez simple git forget-blob file-to-forget
. Vous pouvez obtenir plus d'informations ici
Il disparaîtra de tous les commits de votre historique, de vos remarques, de vos tags, etc.
Je rencontre le même problème de temps en temps, et chaque fois que je dois revenir à ce poste et à d’autres, c’est pourquoi j’ai automatisé le processus.
Crédits aux contributeurs de Stack Overflow qui m'ont permis de mettre cela ensemble
J'ai eu à le faire plusieurs fois à ce jour. Notez que cela ne fonctionne que sur 1 fichier à la fois.
Obtenez une liste de tous les commits qui ont modifié un fichier. Celui du bas sera le premier commis:
git log --pretty=oneline --branches -- pathToFile
Pour supprimer le fichier de l'historique, utilisez le premier commit sha1 et le chemin d'accès au fichier de la commande précédente, et entrez-les dans cette commande:
git filter-branch --index-filter 'git rm --cached --ignore-unmatch <path-to-file>' -- <sha1-where-the-file-was-first-added>..
Alors, ça ressemble à quelque chose comme ça:
git rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore
Supprimer le cache du fichier suivi de git et l'ajouter à la liste
.gitignore
Dans mon projet Android, j'avais le fichier admob_keys.xml en tant que fichier xml séparé dans le dossier app/src/main/res/values / . Pour supprimer ce fichier sensible, j'ai utilisé le script ci-dessous et a parfaitement fonctionné.
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch app/src/main/res/values/admob_keys.xml' \
--Prune-empty --tag-name-filter cat -- --all