web-dev-qa-db-ja.com

git:完全な履歴のためにファイルの1行を変更します

Gitリポジトリを開始したとき、最初のコミットとしていくつかのファイルをコミットしました。さて、後で多くのコミットがあり、それらのファイルに、公開したくない情報の行が含まれていることに気付きました(コードの他の部分とは異なります)。だから私はこの1行を削除/変更しそして残りを保持したいコードの。

周りを検索すると、この解決策が見つかりました:初期コミットとして空のコミットを挿入し(ここで説明: Gitのルートコミットの前にコミットを挿入しますか? )、それに基づいてリベースし、古い最初のコミットを編集します修正します。残念ながら、多くの残酷なマージの競合がリベース中に発生します(ここで説明されているように: git:リベースによって引き起こされた競合の解決 )。

問題を解決する別の方法はありますか、それともすべての競合を手動でリベースして編集する必要がありますか?

前もって感謝します :)

40
tbolender

これは、すべてのブランチのファイルの履歴から問題のある行を削除するコマンドです。

git filter-branch --tree-filter 'sed -i "/sensitive information/ d" filename' -- --all

これにより、すべてのリビジョンがチェックアウトされ、そのリビジョンに対してsedコマンドが実行されてから、そのリビジョンがコミットされます。

この場合のsedコマンドは、filenameという名前のファイル内のパターンsensitive informationを含むすべての行に一致し、それらの行を削除します。

注:バックアップがある場合は、最初にsedスクリプトを試して、目的の動作を確認してください。長い履歴で実行するにはかなりの時間がかかる可能性があります。

50
Karl Bielefeldt

ファイルが存在しない場合でもエラーにならない次のコマンドを作成しました。

 filename=./path/to/your/filename
 filter=your_regex_here

 git filter-branch --tree-filter 'test -f $filename && sed -i.bak "/$filter/d" $filename  || echo “skipping file“' -- --all
8
Ted Yavuzkurt

git filter-branchをご覧ください

リンクの例でうまくいくはずです: http://git-scm.com/docs/git-filter-branch

1
manojlds

私の答えはすべての最高のものを組み合わせたものです。これは、行全体ではなく、指定されたフィルター文字列だけを置き換え、ファイルがコミットで見つからない場合はうまくスキップします。エスケープされた引用符はたくさんありますが、他の答えには本当に奇妙な引用符があり、私にはうまくいきませんでした。

 git filter-branch --tree-filter "test -f \"$filename\" && sed -i \"s/$filter//g\" \"$filename\" || echo \"skipping $filename\"" -- --all
1
Jacob Kern