GitプロジェクトをGitHubに配置したいのですが、機密データ(ユーザー名とパスワード、capistranoの/config/deploy.rbなど)を含む特定のファイルが含まれています。
これらのファイル名を。gitignoreに追加できることは知っていますが、Git内の履歴は削除されません。
また、/。gitディレクトリを削除して最初からやり直したくありません。
Git履歴で特定のファイルのallトレースを削除する方法はありますか?
すべての実用的な目的のために、最初に心配する必要があることはパスワードの変更です! gitリポジトリが完全にローカルにあるのか、それともまだ他の場所にリモートリポジトリがあるのかを質問から明確にしてください。リモートであり、他から保護されていない場合、問題が発生します。これを修正する前に誰かがそのリポジトリを複製した場合、そのローカルマシンにパスワードのコピーがあり、履歴から削除された「修正済み」バージョンに更新するよう強制することはできません。あなたができる唯一の安全なことは、あなたがそれを使ったどこでもあなたのパスワードを他のものに変えることです。
これを回避するには、次のように修正します。 GitHubはその質問にFAQとして正確に回答しました :
Windowsユーザーへの注意:このコマンドでは、シングルではなくダブルクォート( ")を使用してください
git filter-branch --index-filter \
'git update-index --remove filename' <introduction-revision-sha1>..HEAD
git Push --force --verbose --dry-run
git Push --force
このコードをGitHubなどのリモートリポジトリにプッシュし、他の人がそのリモートリポジトリのクローンを作成したら、履歴を書き換えている状態になることに注意してください。この後、他の人が最新の変更をプルダウンしようとすると、早送りではないため変更を適用できないことを示すメッセージが表示されます。
これを修正するには、既存のリポジトリを削除して再クローンするか、 git-rebase manpage の「UPSREAM REBASEからの復旧」の手順に従う必要があります。
将来、機密情報を含むいくつかの変更を誤ってコミットしたが、beforeがリモートリポジトリにプッシュされることに気付いた場合、いくつかの簡単な修正があります。最後のコミットが機密情報を追加するものである場合、単に機密情報を削除してから実行できます:
git commit -a --amend
これにより、git rm
で行われたファイル全体の削除を含む、行った新しい変更で以前のコミットが修正されます。変更が履歴にさかのぼっても、まだリモートリポジトリにプッシュされていない場合は、インタラクティブなリベースを実行できます。
git rebase -i Origin/master
これにより、リモートリポジトリを使用した最後の共通の祖先以降に行ったコミットでエディタが開きます。機密情報を含むコミットを表す行の「選択」を「編集」に変更し、保存して終了します。 Gitは変更を順を追って説明し、次のことができる場所に移動します。
$EDITOR file-to-fix
git commit -a --amend
git rebase --continue
機密情報を含む変更ごと。最終的には、ブランチに戻り、新しい変更を安全にプッシュできます。
パスワードを変更することは良い考えですが、レポジトリの履歴からパスワードを削除するプロセスには、Gitからプライベートデータを削除するために明示的に設計されたgit-filter-branch
のより高速でシンプルな代替手段である BFG Repo-Cleaner をお勧めしますリポジトリ.
削除するパスワードなどをリストしたprivate.txt
ファイルを作成し(1行に1エントリ)、次のコマンドを実行します。
$ Java -jar bfg.jar --replace-text private.txt my-repo.git
レポジトリの履歴内のしきい値サイズ(デフォルトでは1MB)未満のすべてのファイルがスキャンされ、一致する文字列(latestコミットにない)がすべて置き換えられます文字列「***削除済み***」。その後、git gc
を使用して、デッドデータを削除できます。
$ git gc --Prune=now --aggressive
通常、BFGはgit-filter-branch
を実行するよりも10〜50倍高速であり、これらの2つの一般的なユースケースに合わせてオプションが簡素化および調整されています。
完全な開示:私はBFGリポジトリクリーナーの作成者です。
このスクリプト David Underhillがお勧めします。
Natacadoのフィルター分岐に加えて、これらのコマンドを追加して、残された混乱をクリーンアップします。
rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --Prune
完全なスクリプト(すべて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
最後の2つのコマンドは、次のように変更するとより適切に機能する場合があります。
git reflog expire --expire=now --all && \
git gc --aggressive --Prune=now
GitHubにプッシュした場合、1秒後に強制的にプッシュしても遅すぎます
GitHubは、コミットを未解決のままにします。
ただし、GitHubスタッフには、連絡を取った場合にそのようなダングリングコミットを削除する権限があります。これはあなたがすべきことです。 GitHubからダングリングコミットを削除する方法
ダングリングコミットは、次のいずれかで確認できます。
そのコミットでソースを取得する便利な方法の1つは、ダウンロードZipメソッドを使用することです。このメソッドは、たとえば、 https://github.com/cirosantilli/myrepo/archive/SHA.Zip =
不足しているSHAを取得するには、次のいずれかを実行します。
type": "PushEvent"
を使用したAPIイベントのリスト。例えば。鉱山: https://api.github.com/users/cirosantilli/events/public ( Wayback machine )http://ghtorrent.org/ や https://www.githubarchive.org/ のようなスクレイパーがあり、定期的にGitHubデータをプールして他の場所に保存します。
実際のコミット差分をスクレイプするかどうかはわかりませんが、技術的には可能です。
これをテストするために、レポジトリを作成しました: https://github.com/cirosantilli/test-dangling そして完了:
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
ただし、リポジトリを削除した場合、APIからすぐにコミットが消え、404が返されます。 https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2b2d653f7a3824 これは、同じ名前の別のリポジトリを再作成しても機能します。
だから私の推奨される行動方針は:
資格情報を変更する
それだけでは不十分な場合(裸の写真など):
貴重な問題データはありますか?
明確にするために:受け入れられた答えは正しいです。まず試してみてください。ただし、一部のユースケースでは不必要に複雑になる場合があります。特に、 'fatal:bad revision --Prune-empty'などの不快なエラーが発生した場合、またはレポの履歴を実際に気にしない場合です。
代替手段は次のとおりです。
もちろん、これにより、すべてのコミット履歴ブランチ、およびgithubリポジトリとローカルgitリポジトリの両方から問題が削除されます。これが受け入れられない場合は、別のアプローチを使用する必要があります。
これを核オプションと呼びます。
ここにWindowsでの私のソリューションがあります
git filter-branch --tree-filter "rm -f 'filedir/filename'" HEAD
git Push --force
パスが正しいことを確認してください。そうでない場合は機能しません
私はそれが役立つことを願っています
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
git forget-blob
を使用できます。
使用方法は非常に簡単ですgit forget-blob file-to-forget
。詳細はこちらで入手できます
履歴、reflog、タグなどのすべてのコミットから消えます
私は時々同じ問題に遭遇し、この投稿や他の記事に戻る必要があるたびに、プロセスを自動化しました。
これをまとめることができたStack Overflowの貢献者へのクレジット
これまでにこれを数回やらなければなりませんでした。これは一度に1つのファイルに対してのみ機能することに注意してください。
ファイルを変更したすべてのコミットのリストを取得します。一番下のものが最初のコミットになります:
git log --pretty=oneline --branches -- pathToFile
履歴からファイルを削除するには、最初のコミットsha1と前のコマンドからのファイルへのパスを使用し、これらをこのコマンドに入力します。
git filter-branch --index-filter 'git rm --cached --ignore-unmatch <path-to-file>' -- <sha1-where-the-file-was-first-added>..
そのため、次のようになります。
git rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore
Gitから追跡ファイルのキャッシュを削除し、そのファイルを
.gitignore
リストに追加します
Androidプロジェクトでは、admob_keys.xmlapp/src/main/res/values /フォルダー内の分離されたxmlファイルでした。この機密ファイルを削除するには、以下のスクリプトを使用し、完全に機能しました。
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